content_workflow_bynder-1.0.0/content_workflow_bynder_ui/src/Form/MappingEditFormBase.php
content_workflow_bynder_ui/src/Form/MappingEditFormBase.php
<?php namespace Drupal\content_workflow_bynder_ui\Form; use Drupal\content_workflow_bynder_ui\Traits\MappingTrait; use GatherContent\DataTypes\Template; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\taxonomy\Entity\Term; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class MappingEditFormBase. * * @package Drupal\content_workflow_bynder_ui\Form */ class MappingEditFormBase extends EntityForm implements ContainerInjectionInterface { use MappingTrait; /** * Flag for mapping if it's new. * * @var bool */ protected $new; /** * Step in multipart form. * * Values: * - field_mapping * - er_mapping * - completed. * * @var string */ protected $step; /** * Mapping data. * * @var array */ protected $mappingData; /** * Content Workflow full template. * * @var object */ protected $template; /** * Machine name of content type. * * @var string */ protected $contentType; /** * Machine name of entity type. * * @var string */ protected $entityType; /** * Type of import for entity reference fields. * * Values: * - automatic * - manual * - semiautomatic. * * @var string */ protected $erImportType; /** * Flag for skipping ER mapping. * * @var bool */ protected $skip; /** * Count of imported or updated taxonomy terms. * * @var int */ protected $erImported; /** * Array of entity reference fields in mapping. * * @var array */ protected $entityReferenceFields; /** * Array of entity reference fields in mapping. * * @var array */ protected $entityReferenceFieldsOptions; /** * Entity field manager. * * @var \Drupal\Core\Entity\EntityFieldManagerInterface */ protected $entityFieldManager; /** * {@inheritdoc} */ public function __construct(EntityFieldManagerInterface $entityFieldManager) { $this->entityFieldManager = $entityFieldManager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity_field.manager') ); } /** * 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; } /** * Ajax callback for mapping multistep form. * * @return array * Array of form elements. * * @inheritdoc */ public function getMappingTable(array &$form, FormStateInterface $form_state) { $this->contentType = $form_state->getValue('content_type'); $fields = $this->entityReferenceFieldsOptions; $form['mapping']['#attached']['drupalSettings']['content_workflow_bynder'] = (empty($fields) ? NULL : $fields); $form_state->setRebuild(TRUE); return $form['mapping']; } /** * Ajax callback for mapping multistep form. * * @return array * Array of form elements. * * @inheritdoc */ public function getContentTypes(array &$form, FormStateInterface $form_state) { $form_state->setRebuild(TRUE); return $form['content_workflow_bynder']['content_type']; } /** * Generate automatically terms for local field from Content Workflow options. * * @param \Drupal\field\Entity\FieldConfig $handlerSettings * Field config for local field. * @param array $localOptions * Array of remote options. * @param string $langcode * The language of the generated term. */ public function automaticTermsGenerator(FieldConfig $handlerSettings, array $localOptions, $langcode) { $settings = $handlerSettings->getSetting('handler_settings'); /** @var \Drupal\taxonomy\Entity\Term[] $terms */ if (!empty($settings['auto_create_bundle'])) { $vid = $settings['auto_create_bundle']; } else { $vid = reset($settings['target_bundles']); } // Check if field exists. $this->cwbOptionIdsFieldExists($vid); foreach ($localOptions as $id => $localOption) { $query = $this->entityTypeManager->getStorage('taxonomy_term')->getQuery(); $query->accessCheck(TRUE); $group = $query->orConditionGroup() ->condition('contentworkflowbynder_option_ids', $id) ->condition('name', $localOption); $term_ids = $query->condition($group) ->condition('vid', $vid) ->condition('langcode', $langcode) ->execute(); $term_id = array_shift($term_ids); if (!empty($term_id)) { $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($term_id); if ($langcode === LanguageInterface::LANGCODE_NOT_SPECIFIED) { if ($term->label() !== $localOption) { $term->setName($localOption); } $values = $term->get('contentworkflowbynder_option_ids')->getValue(); $mappedValues = array_map(function ($array) { return $array['value']; }, $values); if (!in_array($id, $mappedValues)) { $term->contentworkflowbynder_option_ids->appendItem($id); } } else { if ($term->getTranslation($langcode)->label() !== $localOption) { $term->getTranslation($langcode)->setName($localOption); } $values = $term->getTranslation($langcode)->get('contentworkflowbynder_option_ids')->getValue(); $mappedValues = array_map(function ($array) { return $array['value']; }, $values); if (!in_array($id, $mappedValues)) { $term->getTranslation($langcode)->contentworkflowbynder_option_ids->appendItem($id); } } $term->save(); $this->erImported++; } else { $term_values = [ 'vid' => $vid, 'langcode' => $langcode, ]; $term = Term::create($term_values); $term->setName($localOption); $term->set('contentworkflowbynder_option_ids', $id); $term->save(); $this->erImported++; } } } /** * Prepare options for every language for every field. * * @param \GatherContent\DataTypes\Template $template * GatherContent template object. * * @return array * Array with options. */ public function prepareOptions(Template $template) { $options = []; foreach ($this->entityReferenceFields as $cwbMapping) { foreach ($cwbMapping as $fieldSettings) { foreach ($template['related']->structure->groups as $group) { if ($group->id === $fieldSettings['tab']) { foreach ($group->fields as $field) { if ($field->id === $fieldSettings['name']) { foreach ($field->metaData->choiceFields['options'] as $option) { $options[$option['optionId']] = $option['label']; } } } } } } } return $options; } /** * Validate if contentworkflowbynder_option_ids field exists on specified vocabulary. * * If field doesn't exists, create it for specified vocabulary. * * @param string $vid * Taxonomy vocabulary identifier. */ public function cwbOptionIdsFieldExists($vid) { if ($this->entityTypeManager->hasDefinition('taxonomy_term')) { $definitions = $this->entityFieldManager->getFieldStorageDefinitions('taxonomy_term'); if (!isset($definitions['contentworkflowbynder_option_ids'])) { FieldStorageConfig::create([ 'field_name' => 'contentworkflowbynder_option_ids', 'entity_type' => 'taxonomy_term', 'type' => 'string', 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, 'locked' => TRUE, 'persist_with_no_fields' => TRUE, 'settings' => [ 'is_ascii' => FALSE, 'case_sensitive' => FALSE, ], ])->save(); } $field_config = FieldConfig::loadByName('taxonomy_term', $vid, 'contentworkflowbynder_option_ids'); if (is_null($field_config)) { FieldConfig::create([ 'field_name' => 'contentworkflowbynder_option_ids', 'entity_type' => 'taxonomy_term', 'bundle' => $vid, 'label' => 'Content Workflow Option IDs', ])->save(); } } } /** * Handle manual type of taxonomy terms. * * @param array|null $languages * Array with languages available for mapping. * @param \Drupal\Core\Entity\EntityStorageInterface $entityStorage * Storage object for taxonomy terms. * @param array $row * Array with mapping options. */ public function manualErImport($languages, EntityStorageInterface $entityStorage, array $row) { if (!empty($languages) && !empty($row['terms'])) { $terms = $entityStorage->loadByProperties(['contentworkflowbynder_option_ids' => $row[$languages[0]]]); /** @var \Drupal\taxonomy\Entity\Term $term */ $term = array_shift($terms); // If term already exists. if (!empty($term)) { // If term was changed, remove option ids for every // language. if ($term->id() !== $row['terms']) { // We don't know how many languages are translated. $translation_languages = $term->getTranslationLanguages(TRUE); foreach ($translation_languages as $language) { if ($term->hasTranslation($language) && !empty($row[$language])) { $option_ids = $term->getTranslation($language) ->get('contentworkflowbynder_option_ids'); foreach ($option_ids as $i => $option_id) { if ($option_id == $row[$language]) { unset($option_ids[$i]); } } $term->getTranslation($language) ->set('contentworkflowbynder_option_ids', $option_ids); } } } } // Set new values to correct term. $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($row['terms']); if (!empty($languages)) { foreach ($languages as $language) { $term->getTranslation($language) ->set('contentworkflowbynder_option_ids', $row[$language]); } } $term->save(); $this->erImported++; } elseif (empty($languages) && !empty($row['terms'])) { $und_lang_value = $row[LanguageInterface::LANGCODE_NOT_SPECIFIED]; if (!empty($und_lang_value)) { $terms = $entityStorage->loadByProperties(['contentworkflowbynder_option_ids' => $und_lang_value]); /** @var \Drupal\taxonomy\Entity\Term $term */ $term = array_shift($terms); // If term already exists. if (!empty($term)) { // If term was changed, remove option ids for every // language. if ($term->id() !== $row['terms']) { $option_ids = $term->get('contentworkflowbynder_option_ids'); foreach ($option_ids as $i => $option_id) { if ($option_id == $und_lang_value) { unset($option_ids[$i]); } } $term->set('contentworkflowbynder_option_ids', $option_ids); } } // Set new values to correct term. $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($row['terms']); $term->set('contentworkflowbynder_option_ids', $und_lang_value); $term->save(); $this->erImported++; } } } /** * Handle semiautomatic import of taxonomy terms. * * @param array|null $languages * Array with languages available for mapping. * @param \Drupal\Core\Entity\EntityStorageInterface $entityStorage * Storage object for taxonomy terms. * @param array $row * Array with mapping options. * @param array $options * ContentWorkflowBynder options for every language and every field. * @param string $vid * Taxonomy vocabulry identifier. */ public function semiErImport($languages, EntityStorageInterface $entityStorage, array $row, array $options, $vid) { if (!empty($languages)) { $terms = $entityStorage->loadByProperties(['contentworkflowbynder_option_ids' => $row[$languages[0]]]); /** @var \Drupal\taxonomy\Entity\Term $term */ $term = array_shift($terms); if (!empty($term)) { foreach ($languages as $language) { if (!empty($row[$language]) && $term->hasTranslation($language) && $term->getTranslation($language)->label() !== $options[$row[$language]]) { $term->getTranslation($language) ->setName($options[$row[$language]]); } } $term->save(); $this->erImported++; } else { $term = Term::create([ 'vid' => $vid, ]); foreach ($languages as $language) { if (!empty($row[$language])) { if (!$term->hasTranslation($language)) { $term->addTranslation($language); } $term->getTranslation($language) ->set('contentworkflowbynder_option_ids', $row[$language]); $term->getTranslation($language) ->setName($options[$row[$language]]); } } if (!empty($term->getTranslationLanguages())) { $term->save(); $this->erImported++; } } } else { /** @var \Drupal\taxonomy\Entity\Term $term */ $und_lang_value = $row[LanguageInterface::LANGCODE_NOT_SPECIFIED]; if (!empty($und_lang_value)) { $terms = $entityStorage->loadByProperties(['contentworkflowbynder_option_ids' => $und_lang_value]); $term = array_shift($terms); if (!empty($term)) { if ($term->label() !== $options[$und_lang_value]) { $term->setName($options[$und_lang_value]); } $term->save(); $this->erImported++; } else { $term = Term::create([ 'vid' => $vid, 'contentworkflowbynder_option_ids' => $und_lang_value, ]); $term->setName($options[$und_lang_value]); $term->save(); $this->erImported++; } } } } /** * Get available languages from currect row. * * @param array $row * Currect row from mapping. * * @return array * Array with available languages. */ public function getAvailableLanguages(array $row) { $languages = array_keys($row); foreach ($languages as $i => $language) { if ($language === 'und') { unset($languages[$i]); } elseif ($language === 'terms') { unset($languages[$i]); } } return $languages; } /** * Get vocabulary identifier for field in content type. * * @param string $field_id * ID of local field. * * @return string * Identifier of vocabulary. */ public function getVocabularyId($field_id) { // Load vocabulary. $id_array = explode('||', $field_id); $field_config = FieldConfig::load($id_array[count($id_array) - 1]); $settings = $field_config->getSetting('handler_settings'); /** @var \Drupal\taxonomy\Entity\Term[] $terms */ if (!empty($settings['auto_create_bundle'])) { $vid = $settings['auto_create_bundle']; return $vid; } else { $vid = reset($settings['target_bundles']); return $vid; } } /** * Extract mapping data from submitted form values. * * @param array $formValues * Array with all submitted values. * * @return array * Mapping data. */ public function extractMappingData(array $formValues) { $form_definition_elements = [ 'return', 'form_build_id', 'form_token', 'form_id', 'op', ]; $non_data_elements = array_merge($form_definition_elements, [ 'cwb_template', 'content_type', 'entity_type', 'id', 'updated', 'project', 'template_name', 'er_mapping_type', 'submit', 'close', ]); $mapping_data = []; foreach ($formValues as $key => $value) { if (!in_array($key, $non_data_elements)) { $mapping_data[$key] = $value; } } $this->mappingData = $mapping_data; return $mapping_data; } }