content_workflow_bynder-1.0.0/content_workflow_bynder_ui/src/Form/MappingEditSteps/MappingSteps.php

content_workflow_bynder_ui/src/Form/MappingEditSteps/MappingSteps.php
<?php

namespace Drupal\content_workflow_bynder_ui\Form\MappingEditSteps;

use Drupal\content_workflow_bynder_ui\Traits\MappingTrait;
use GatherContent\DataTypes\Element;
use GatherContent\DataTypes\ElementText;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\content_workflow_bynder\Entity\MappingInterface;

/**
 * Class MappingSteps.
 *
 * @package Drupal\content_workflow_bynder_ui\Form
 */
abstract class MappingSteps {

  use StringTranslationTrait;
  use DependencySerializationTrait;
  use MappingTrait;

  /**
   * Mapping object.
   *
   * @var \Drupal\content_workflow_bynder\Entity\Mapping
   */
  public $mapping;

  /**
   * Template object.
   *
   * @var \GatherContent\DataTypes\Template
   */
  public $template;

  /**
   * Array of entity reference fields in mapping.
   *
   * @var array
   */
  protected $entityReferenceFields;

  /**
   * Array of entity reference fields in mapping.
   *
   * @var array
   */
  protected $entityReferenceFieldsOptions;

  /**
   * MetatagQuery helper object.
   *
   * @var \Drupal\content_workflow_bynder\MetatagQuery
   */
  protected $metatagQuery;

  /**
   * MappingSteps constructor.
   *
   * @param \Drupal\content_workflow_bynder\Entity\MappingInterface $mapping
   *   Mapping object.
   * @param array $template
   *   Template array.
   */
  public function __construct(MappingInterface $mapping, array $template) {
    $this->mapping = $mapping;
    $this->template = $template;
    /** @var \Drupal\content_workflow_bynder\MetatagQuery $metatagQuery */
    $this->metatagQuery = \Drupal::service('content_workflow_bynder.metatag');
  }

  /**
   * Sets entityReferenceFields variable.
   *
   * @param array|null $value
   *   Value.
   */
  public function setEntityReferenceFields($value) {
    $this->entityReferenceFields = $value;
  }

  /**
   * Sets entityReferenceFieldsOptions variable.
   *
   * @param array|null $value
   *   Value.
   */
  public function setEntityReferenceFieldsOptions($value) {
    $this->entityReferenceFieldsOptions = $value;
  }

  /**
   * Gets entityReferenceFields variable.
   */
  public function getEntityReferenceFields() {
    return $this->entityReferenceFields;
  }

  /**
   * Gets entityReferenceFieldsOptions variable.
   */
  public function getEntityReferenceFieldsOptions() {
    return $this->entityReferenceFieldsOptions;
  }

  /**
   * Returns form array.
   *
   * @param \Drupal\Core\Form\FormStateInterface $formState
   *   Form state object.
   *
   * @return mixed
   *   Return form array.
   */
  public function getForm(FormStateInterface $formState) {
    $form['form_description'] = [
      '#type' => 'html_tag',
      '#tag' => 'i',
      '#value' => $this->t('Please map your Content Workflow Template fields to your Drupal
      Content Type Fields. Please note that a Content Workflow field can only be
      mapped to a single Drupal field. So each field can only be mapped to once.'),
    ];

    $form['project'] = [
      '#type' => 'item',
      '#title' => $this->t('Project name:'),
      '#markup' => $this->mapping->getGathercontentProject(),
      '#wrapper_attributes' => [
        'class' => [
          'inline-label',
        ],
      ],
    ];

    $form['content_workflow_bynder'] = [
      '#type' => 'container',
    ];

    $form['content_workflow_bynder']['template_name'] = [
      '#type' => 'item',
      '#title' => $this->t('Content Workflow template:'),
      '#markup' => $this->mapping->getGathercontentTemplate(),
      '#wrapper_attributes' => [
        'class' => [
          'inline-label',
        ],
      ],
    ];

    return $form;
  }

  /**
   * Do validation.
   */
  public function doValidate(array &$form, FormStateInterface $formState) {
    $form_definition_elements = [
      'return',
      'form_build_id',
      'form_token',
      'form_id',
      'op',
    ];
    $non_data_elements = array_merge($form_definition_elements, [
      'content_type',
      'entity_type',
      'id',
      'updated',
      'project',
      'template_name',
      'er_mapping_type',
      'submit',
      'close',
    ]);

    $mapping_data = [];
    foreach ($formState->getValues() as $key => $value) {
      if (!in_array($key, $non_data_elements)) {
        $mapping_data[$key] = $value;
      }
    }
    // Check if is translatable.
    $entity_type = (empty($this->mapping->getMappedEntityType()) ? $formState->getValue('entity_type') : $this->mapping->getMappedEntityType());
    $content_type = (empty($this->mapping->getContentType()) ? $formState->getValue('content_type') : $this->mapping->getContentType());
    $translatable = \Drupal::moduleHandler()->moduleExists('content_translation')
      && \Drupal::service('content_translation.manager')
        ->isEnabled($entity_type, $content_type);
    // Validate if each language is used only once
    // for translatable content types.
    $content_lang = [];
    $metatag_lang = [];

    if ($translatable) {
      foreach ($mapping_data as $groupId => $group) {
        $groupType = (isset($group['type']) ? $group['type'] : 'content');
        if ($group['language'] != 'und') {
          if (!in_array($group['language'], ${$groupType . '_lang'})) {
            ${$groupType . '_lang'}[] = $group['language'];
          }
          else {
            $element = $groupId . '[language]';
            $formState->setErrorByName($element, $this->t('Each language can be used only once'));
          }
        }
      }
    }

    // Validate if each field is used only once.
    $content_fields = [];
    $metatag_fields = [];

    if ($translatable) {
      foreach ($content_lang as $lang) {
        $content_fields[$lang] = [];
      }
      foreach ($metatag_lang as $lang) {
        $metatag_fields[$lang] = [];
      }
      $content_fields[LanguageInterface::LANGCODE_NOT_SPECIFIED] = $metatag_fields[LanguageInterface::LANGCODE_NOT_SPECIFIED] = [];
    }

    foreach ($mapping_data as $groupId => $group) {
      $groupType = (isset($group['type']) ? $group['type'] : 'content');

      if (isset($group['elements'])) {
        foreach ($group['elements'] as $k => $element) {
          if (empty($element)) {
            continue;
          }

          $lang_code = 'und';
          if ($translatable) {
            $lang_code = $group['language'];
          }
          if (isset(${$groupType . '_fields'}[$lang_code]) && in_array($element, ${$groupType . '_fields'}[$lang_code])) {
            $formState->setErrorByName($groupId,
              $this->t('A Content Workflow field can only be mapped to a single Drupal field. So each field can only be mapped to once.'));
            continue;
          }

          if ($groupType == 'content' && in_array($this->getFieldFromId($k, $groupId)->type, ['text', 'guidelines'])) {
            ${$groupType . '_fields'}[$lang_code][] = $element;
          }
        }
      }
    }

    // Validate if at least one field in mapped.
    if (!$translatable && empty($content_fields) && empty($metatag_fields)) {
      $formState->setErrorByName('form', $this->t('You need to map at least one field to create mapping.'));
    }
    elseif ($translatable &&
      count($content_fields) === 1
      && empty($content_fields[LanguageInterface::LANGCODE_NOT_SPECIFIED])
      && empty($metatag_fields[LanguageInterface::LANGCODE_NOT_SPECIFIED])
      && count($metatag_fields) === 1
    ) {
      $formState->setErrorByName('form', $this->t('You need to map at least one field to create mapping.'));
    }

    // Validate if title is mapped for translatable content.
    if ($translatable) {
      $titleField = $entity_type . '.' . $content_type . '.title';
      foreach ($content_fields as $k => $lang_fields) {
        if (!in_array($titleField, $lang_fields)
          && !in_array('title', $lang_fields)
          && $k !== LanguageInterface::LANGCODE_NOT_SPECIFIED
        ) {
          $formState->setErrorByName('form', $this->t('You have to map Drupal Title field for translatable content.'));
        }
      }
    }
  }

  /**
   * Wrapper function for filterFieldsRecursively.
   *
   * Use for filtering only equivalent fields.
   *
   * @param string $id
   *   ContentWorkflowBynder id of the field to retrieve.
   * @param string $group_id
   *   ContentWorkflowBynder id of the group containing the field.
   *
   * @return \GatherContent\DataTypes\Element
   *   The GatherContent field..
   */
  protected function getFieldFromId($id, $group_id) {
    if ($group_id && !strpos($id, '/')) {
      return $this->template['related']->structure->groups[$group_id]->fields[$id];
    }
    if ($group_id && strpos($id, '/')) {
      $ids = explode('/', $id);
      $component = $this->template['related']->structure->groups[$group_id]->fields[$ids[0]];
      $children = $component->getChildrenFields();
      return $children[$ids[1]];
    }
  }

  /**
   * Wrapper function for filterFieldsRecursively.
   *
   * Use for filtering only equivalent fields.
   *
   * @param \GatherContent\DataTypes\Element $cwb_field
   *   Type of field in GatherContent.
   * @param string $content_type
   *   Name of Drupal content type.
   * @param string $entity_type
   *   Name of Drupal entity type.
   *
   * @return array
   *   Associative array with equivalent fields.
   */
  protected function filterFields(Element $cwb_field, $content_type, $entity_type = 'node') {
    return $this->filterFieldsRecursively($cwb_field, $content_type, $entity_type);
  }

  /**
   * Helper function.
   *
   * Use for filtering only equivalent fields.
   *
   * @param object $cwb_field
   *   Type of field in ContentWorkflowBynder.
   * @param string $content_type
   *   Name of Drupal content type.
   * @param string $entity_type
   *   Name of Drupal Entity type.
   * @param array $nested_ids
   *   Nested ID array.
   * @param string $bundle_label
   *   Bundle label string.
   * @param int $counter
   *   Field depth, to avoid infinite recursion.
   *
   * @return array
   *   Associative array with equivalent fields.
   */
  protected function filterFieldsRecursively($cwb_field, $content_type, $entity_type = 'node', array $nested_ids = [], $bundle_label = '', int $counter = 0) {
    if ($counter > 2) {
      return [];
    }
    $mapping_array = [
      'attachment' => [
        'file',
        'image',
        'entity_reference',
        'entity_reference_revisions',
      ],
      'guidelines' => [
        'text_long',
        'entity_reference_revisions',
      ],
      'text' => [
        'text',
        'text_long',
        'text_with_summary',
        'string_long',
        'string',
        'email',
        'telephone',
        'date',
        'datetime',
        'entity_reference_revisions',
      ],
      'choice_radio' => [
        'list_string',
        'entity_reference',
        'entity_reference_revisions',
      ],
      'choice_checkbox' => [
        'list_string',
        'entity_reference',
        'entity_reference_revisions',
      ],
    ];
    $entityFieldManager = \Drupal::service('entity_field.manager');
    $entityTypeManager = \Drupal::entityTypeManager();
    $entityDefinition = $entityTypeManager->getDefinition($entity_type);
    $titleKey = $entityDefinition->getKey('label');

    /** @var \Drupal\Core\Field\FieldDefinitionInterface[] $instances */
    $instances = $entityFieldManager->getFieldDefinitions($entity_type, $content_type);

    $fields = [];
    // Fields.
    foreach ($instances as $instance) {
      if ($instance instanceof BaseFieldDefinition) {
        // Set label field.
        if ($cwb_field->type === 'text'
          && $cwb_field instanceof ElementText
          && $cwb_field->metaData->isPlain
          && $titleKey == $instance->getName()
        ) {
          $fields[$titleKey] = $instance->getLabel();
        }
        continue;
      }
      if (in_array($instance->getType(), $mapping_array[$cwb_field->type])) {
        // Constrains:
        // - do not map plain text (Drupal) to rich text (CWB).
        // - do not map radios (CWB) to text (Drupal),
        // if widget isn't provided by select_or_other module.
        // - do not map section (CWB) to plain text (Drupal).
        // - map only taxonomy entity reference (Drupal) to radios
        // and checkboxes (CWB).
        switch ($cwb_field->type) {
          case 'text':
            if (
              (!isset($cwb_field->metaData->isPlain) || !$cwb_field->metaData->isPlain) &&
              in_array($instance->getType(), [
                'string',
                'string_long',
                'email',
                'telephone',
              ])
            ) {
              continue 2;
            }
            break;

          case 'section':
            if (in_array($instance->getType(), [
              'string',
              'string_long',
            ])) {
              continue 2;
            }
            break;

          case 'choice_radio':
          case 'choice_checkbox':
            if (
              $instance->getType() == 'entity_reference' &&
              $instance->getSetting('handler') !== 'default:taxonomy_term'
            ) {
              continue 2;
            }
            break;
        }

        $fieldStorageDefinition = $instance->getFieldStorageDefinition();

        if ($instance->getType() === 'entity_reference_revisions') {
          $settings = $instance->getSetting('handler_settings');

          if (!empty($settings['target_bundles'])) {
            $bundles = $settings['target_bundles'];

            if (!empty($settings['negate']) && !empty($settings['target_bundles_drag_drop'])) {
              $negated_bundles = array_filter(
                $settings['target_bundles_drag_drop'],
                function ($v) {
                  return !$v['enabled'];
                }
              );

              $bundles = array_combine(array_keys($negated_bundles), array_keys($negated_bundles));
            }

            $target_type = $fieldStorageDefinition->getSetting('target_type');
            $bundle_entity_type = $entityTypeManager
              ->getStorage($target_type)
              ->getEntityType()
              ->get('bundle_entity_type');

            $new_nested_ids = $nested_ids;
            $new_nested_ids[] = $instance->id();

            foreach ($bundles as $bundle) {
              $new_bundle_label = ((!empty($bundle_label)) ? $bundle_label . ' - ' : '') . $instance->getLabel();
              $bundle_name = $entityTypeManager
                ->getStorage($bundle_entity_type)
                ->load($bundle)
                ->label();

              $new_bundle_label .= ' (bundle: ' . $bundle_name . ')';

              $targetFields = $this->filterFieldsRecursively($cwb_field, $bundle, $target_type, $new_nested_ids, $new_bundle_label, $counter + 1);

              if (!empty($targetFields)) {
                $fields = $fields + $targetFields;
              }
            }
          }
        }
        else {
          $key = $instance->id();

          $instanceIsMultiple = $fieldStorageDefinition->isMultiple();

          // CWB field is a multi value field.
          if (!empty($cwb_field->metaData->repeatable['isRepeatable'])
            && $cwb_field->metaData->repeatable['isRepeatable']
          ) {
            if (!$instanceIsMultiple) {
              continue;
            }

            $instanceCardinality = $fieldStorageDefinition->getCardinality();

            // Has unlimited values.
            if ($cwb_field->metaData->repeatable['limitEnabled'] === FALSE) {
              if ($instanceCardinality > 0) {
                continue;
              }
            }
            else {
              // Has limited values.
              if ($cwb_field->metaData->repeatable['limit'] !== $instanceCardinality) {
                continue;
              }
            }
          }
          else {
            // Single values.
            if ($instanceIsMultiple && $cwb_field->type === 'text') {
              continue;
            }
          }

          if (!empty($nested_ids)) {
            $new_nested_ids = $nested_ids;
            $new_nested_ids[] = $instance->id();
            $key = implode('||', $new_nested_ids);
          }

          $fields[$key] = ((!empty($bundle_label)) ? $bundle_label . ' - ' : '') . $instance->getLabel();

          if ($instance->getType() === 'entity_reference' && $instance->getSetting('handler') === 'default:taxonomy_term') {
            $mappingData = unserialize($this->mapping->getData());

            if ($mappingData) {
              foreach ($mappingData as $groupName => $group) {
                $cwbField = array_search($key, $group['elements']);
                if (empty($cwbField)) {
                  continue;
                }
                if (isset($group['language'])) {
                  $this->entityReferenceFields[$key][$group['language']]['name'] = $cwbField;
                  $this->entityReferenceFields[$key][$group['language']]['tab'] = $groupName;
                }
                else {
                  $this->entityReferenceFields[$key][LanguageInterface::LANGCODE_NOT_SPECIFIED]['name'] = $cwbField;
                  $this->entityReferenceFields[$key][LanguageInterface::LANGCODE_NOT_SPECIFIED]['tab'] = $groupName;
                }
              }
            }

            if (empty($this->entityReferenceFieldsOptions) || !in_array($key, $this->entityReferenceFieldsOptions)) {
              $this->entityReferenceFieldsOptions[] = $key;
            }
          }
        }
      }
    }

    return $fields;
  }

  /**
   * Return only supported metatag fields.
   *
   * @param object $content_workflow_bynder_field
   *   Object of field from ContentWorkflowBynder.
   * @param string $content_type
   *   Machine name of the content type.
   * @param string $entity_type
   *   Machine name of the entity type.
   *
   * @return array
   *   Array of supported metatag fields.
   */
  protected function filterMetatags($content_workflow_bynder_field, $content_type, $entity_type = 'node') {
    if (
      $content_workflow_bynder_field->type === 'text' &&
      isset($content_workflow_bynder_field->metaData->isPlain) &&
      $content_workflow_bynder_field->metaData->isPlain
    ) {
      /** @var \Drupal\content_workflow_bynder\MetatagQuery $metatagQuery */
      $metatagQuery = \Drupal::service('content_workflow_bynder.metatag');
      return $metatagQuery->getMetatagFields($entity_type, $content_type);
    }

    else {
      return [];
    }
  }

  /**
   * Get list of languages as assoc array.
   *
   * @return array
   *   Assoc array of languages keyed by lang code, value is language name.
   */
  protected function getLanguageList() {
    $languages = \Drupal::service('language_manager')
      ->getLanguages(LanguageInterface::STATE_CONFIGURABLE);
    $language_list = [];
    foreach ($languages as $lang_code => $language) {
      /** @var \Drupal\Core\Language\Language $language */
      $language_list[$lang_code] = $language->getName();
    }
    return $language_list;
  }

  /**
   * Get list of bundle types.
   *
   * @return array
   *   Assoc array of bundle types.
   */
  public function getBundles($entityType) {
    $bundleTypes = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entityType);
    $response = [];

    foreach ($bundleTypes as $key => $value) {
      $response[$key] = $value['label'];
    };

    return $response;
  }

  /**
   * Get list of entity types.
   *
   * @return array
   *   Assoc array of entity types.
   */
  public function getEntityTypes() {
    $entityTypes = \Drupal::entityTypeManager()->getDefinitions();
    $unsupportedTypes = [
      'user',
      'file',
      'menu_link_content',
    ];
    $response = [];

    foreach ($entityTypes as $key => $value) {
      if ($value) {
        $class = $value->getOriginalClass();
        if (in_array(FieldableEntityInterface::class, class_implements($class))
          && !in_array($key, $unsupportedTypes)) {
          $label = (string) $value->getLabel();
          $response[$key] = $label;
        }
      }
    }

    return $response;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc