diff --git a/src/TermMerger.php b/src/TermMerger.php index 2b341f6..2185dd0 100644 --- a/src/TermMerger.php +++ b/src/TermMerger.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\taxonomy\TermInterface; +use Drupal\term_reference_change\ReferenceMigrator; /** * Implements TermMergerInterface to provide a term merger service. @@ -28,18 +29,11 @@ class TermMerger implements TermMergerInterface { private $entityTypeManager; /** - * The entity field manager. + * The term reference migration service. * - * @var \Drupal\Core\Entity\EntityFieldManagerInterface + * @var \Drupal\term_reference_change\ReferenceMigrator */ - private $entityFieldManager; - - /** - * The entity type bundle info. - * - * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface - */ - private $entityTypeBundleInfo; + private $migrator; /** * TermMerger constructor. @@ -50,13 +44,16 @@ class TermMerger implements TermMergerInterface { * The entity type bundle info service. * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager * The entity field manager service. + * @param \Drupal\term_reference_change\ReferenceMigrator $migrator + * The reference migration service. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException */ - public function __construct(EntityTypeManagerInterface $entityTypeManager, EntityTypeBundleInfoInterface $entityTypeBundleInfo, EntityFieldManagerInterface $entityFieldManager) { + public function __construct(EntityTypeManagerInterface $entityTypeManager, ReferenceMigrator $migrator) { $this->entityTypeManager = $entityTypeManager; $this->termStorage = $this->entityTypeManager->getStorage('taxonomy_term'); - $this->entityFieldManager = $entityFieldManager; - $this->entityTypeBundleInfo = $entityTypeBundleInfo; + $this->migrator = $migrator; } /** @@ -153,162 +150,8 @@ class TermMerger implements TermMergerInterface { */ private function migrateReferences(array $fromTerms, TermInterface $toTerm) { foreach ($fromTerms as $fromTerm) { - $this->migrateReference($fromTerm, $toTerm); + $this->migrator->migrateReference($fromTerm, $toTerm); } } - /** - * Updates the term reference on all entities from the old to the new. - * - * @param \Drupal\taxonomy\TermInterface $fromTerm - * The term to migrate away from. - * @param \Drupal\taxonomy\TermInterface $toTerm - * The term to migrate to. - */ - private function migrateReference(TermInterface $fromTerm, TermInterface $toTerm) { - $referenceFieldNames = $this->findTermReferenceFieldNames(); - $referencingEntities = $this->loadReferencingEntities($fromTerm); - - foreach ($referencingEntities as $entity) { - foreach ($referenceFieldNames as $fieldName) { - $values = $entity->{$fieldName}->getValue(); - if (empty($values)) { - continue; - } - - $referenceUpdated = FALSE; - foreach ($values as &$value) { - if ($value['target_id'] !== $fromTerm->id()) { - continue; - } - - $referenceUpdated = TRUE; - $value['target_id'] = $toTerm->id(); - } - - if (!$referenceUpdated) { - continue; - } - - $entity->{$fieldName}->setValue($values); - $entity->save(); - } - } - } - - /** - * Finds all names of term reference fields. - * - * @return string[] - * Array of entity reference field names for fields that reference taxonomy - * terms. - */ - private function findTermReferenceFieldNames() { - $fieldNames = []; - - foreach ($this->findTermReferenceFields() as $bundle) { - foreach ($bundle as $fieldsInBundle) { - $fieldNames = array_merge($fieldNames, $fieldsInBundle); - } - } - - return $fieldNames; - } - - /** - * Finds all term reference fields. - * - * @return array - * Nested array of field names for taxonomy term entity reference fields. - * [entity type id][bundle id] = array of field names. - */ - private function findTermReferenceFields() { - $termReferenceFields = []; - - $entityTypes = $this->entityTypeManager->getDefinitions(); - foreach ($entityTypes as $entityType) { - if (!$entityType->entityClassImplements(FieldableEntityInterface::class)) { - continue; - } - - $referenceFields = $this->findTermReferenceFieldsForEntityType($entityType->id()); - if (empty($referenceFields)) { - continue; - } - - $termReferenceFields[$entityType->id()] = $referenceFields; - } - - return $termReferenceFields; - } - - /** - * Finds all term reference fields for a given entity type. - * - * @param string $entityType - * The entity type name. - * - * @return array - * The term reference fields keyed by their respective bundle. - */ - private function findTermReferenceFieldsForEntityType($entityType) { - $bundleNames = array_keys($this->entityTypeBundleInfo->getBundleInfo($entityType)); - - $referenceFields = []; - foreach ($bundleNames as $bundleName) { - $fieldDefinitions = $this->entityFieldManager->getFieldDefinitions($entityType, $bundleName); - foreach ($fieldDefinitions as $fieldDefinition) { - if ($fieldDefinition->getType() !== 'entity_reference') { - continue; - } - - if ($fieldDefinition->getSetting('target_type') !== 'taxonomy_term') { - continue; - } - - if ($fieldDefinition->isComputed()) { - continue; - } - - // Exclude parent fields because they cause fatal errors during the - // query. This is because they are currently a special case. - // @see https://www.drupal.org/node/2543726 - if ($fieldDefinition->getName() === 'parent') { - continue; - } - - $referenceFields[$bundleName][] = $fieldDefinition->getName(); - } - } - - return $referenceFields; - } - - /** - * Loads all entities with a reference to the given term. - * - * @param \Drupal\taxonomy\TermInterface $term - * The term to find references to. - * - * @return \Drupal\Core\Entity\EntityInterface[] - * All entities referencing this term. - */ - private function loadReferencingEntities(TermInterface $term) { - $referenceFields = $this->findTermReferenceFields(); - - $referencingEntities = []; - - foreach ($referenceFields as $entityType => $bundles) { - foreach ($bundles as $bundle) { - foreach ($bundle as $fieldName) { - $entities = $this->entityTypeManager->getStorage($entityType) - ->loadByProperties([$fieldName => $term->id()]); - $referencingEntities = array_merge($referencingEntities, $entities); - } - } - } - - return $referencingEntities; - } - } diff --git a/term_merge.info.yml b/term_merge.info.yml index 143e81b..85c2984 100644 --- a/term_merge.info.yml +++ b/term_merge.info.yml @@ -5,3 +5,4 @@ type: module dependencies: - drupal:taxonomy + - term_reference_change:term_reference_change diff --git a/term_merge.services.yml b/term_merge.services.yml index 4a4354c..430c8c6 100644 --- a/term_merge.services.yml +++ b/term_merge.services.yml @@ -1,4 +1,4 @@ services: term_merge.term_merger: class: Drupal\term_merge\TermMerger - arguments: ['@entity_type.manager', '@entity_type.bundle.info', '@entity_field.manager'] + arguments: ['@entity_type.manager', '@term_reference_change.migrator']