class ReferenceMigrator in Term reference change 8
Migrates references from one taxonomy term to the other.
Hierarchy
- class \Drupal\term_reference_change\ReferenceMigrator
Expanded class hierarchy of ReferenceMigrator
1 file declares its use of ReferenceMigrator
- ReferenceMigratorTest.php in tests/
src/ Kernel/ ReferenceMigratorTest.php
1 string reference to 'ReferenceMigrator'
1 service uses ReferenceMigrator
File
- src/
ReferenceMigrator.php, line 12
Namespace
Drupal\term_reference_changeView source
class ReferenceMigrator {
/**
* The reference finder.
*
* @var \Drupal\term_reference_change\ReferenceFinderInterface
*/
private $referenceFinder;
/**
* ReferenceMigrator constructor.
*
* @param \Drupal\term_reference_change\ReferenceFinderInterface $referenceFinder
* The reference finder service.
*/
public function __construct(ReferenceFinderInterface $referenceFinder) {
$this->referenceFinder = $referenceFinder;
}
/**
* Updates the term reference on all entities from the source to the target.
*
* @param \Drupal\taxonomy\TermInterface $sourceTerm
* The term to migrate away from.
* @param \Drupal\taxonomy\TermInterface $targetTerm
* The term to migrate to.
* @param array[] $limit
* List of entity ids keyed by their entity type to limit the migration to.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function migrateReference(TermInterface $sourceTerm, TermInterface $targetTerm, array $limit = []) {
$referenceFieldNames = $this
->findTermReferenceFieldNames(array_keys($limit));
$referencingEntities = $this->referenceFinder
->findReferencesFor($sourceTerm);
foreach ($referencingEntities as $entityType => $entities) {
if ($this
->entityTypeShouldBeSkipped($entityType, $limit)) {
continue;
}
foreach ($entities as $entity) {
if ($this
->entityShouldBeSkipped($entity, $limit)) {
continue;
}
$this
->updateReferencingEntity($sourceTerm, $targetTerm, $referenceFieldNames, $entity);
}
}
}
/**
* Finds all names of term reference fields.
*
* @param string[] $limitToEntityTypes
* The entity types to limit to. If left empty, all types are allowed.
*
* @return string[]
* Array of entity reference field names for fields that reference taxonomy
* terms.
*/
private function findTermReferenceFieldNames(array $limitToEntityTypes = []) {
$fieldNames = [];
foreach ($this->referenceFinder
->findTermReferenceFields() as $entityType => $bundle) {
if (!empty($limitToEntityTypes) && !in_array($entityType, $limitToEntityTypes)) {
continue;
}
foreach ($bundle as $fieldsInBundle) {
$fieldNames = array_merge($fieldNames, $fieldsInBundle);
}
}
return $fieldNames;
}
/**
* Determines if an entity should be skipped or not.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to check.
* @param array[] $limit
* The entity keys keyed by their entity id used to determine if the given
* entity should be skipped.
*
* @return bool
* TRUE if the entity should be skipped, FALSE otherwise.
*/
private function entityShouldBeSkipped(EntityInterface $entity, array $limit) {
if (empty($limit)) {
return FALSE;
}
$entityTypeId = $entity
->getEntityTypeId();
if ($this
->entityTypeShouldBeSkipped($entityTypeId, $limit)) {
return TRUE;
}
return !in_array($entity
->id(), $limit[$entityTypeId]);
}
/**
* Determines if an entire entity type should be skipped or not.
*
* @param string $entityType
* The entity to check.
* @param array[] $limit
* The entity keys keyed by their entity id used to determine if the given
* entity should be skipped.
*
* @return bool
* TRUE if the entity should be skipped, FALSE otherwise.
*/
private function entityTypeShouldBeSkipped($entityType, array $limit) {
if (empty($limit)) {
return FALSE;
}
if (isset($limit[$entityType])) {
return FALSE;
}
return TRUE;
}
/**
* Changes the reference of an entity from the source term to the target term.
*
* @param \Drupal\taxonomy\TermInterface $sourceTerm
* The term to migrate from.
* @param \Drupal\taxonomy\TermInterface $targetTerm
* The term to migrate to.
* @param string[] $referenceFieldNames
* Names of possible entityReference fields.
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity to update.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
private function updateReferencingEntity(TermInterface $sourceTerm, TermInterface $targetTerm, array $referenceFieldNames, FieldableEntityInterface $entity) {
foreach ($referenceFieldNames as $fieldName) {
$value = [];
if (!$entity
->hasField($fieldName)) {
continue;
}
$values = $entity->{$fieldName}
->getValue();
if (empty($values)) {
continue;
}
$referenceUpdated = FALSE;
foreach ($values as &$value) {
if ($value['target_id'] !== $sourceTerm
->id()) {
continue;
}
$referenceUpdated = TRUE;
$value['target_id'] = $targetTerm
->id();
}
if (!$referenceUpdated) {
continue;
}
$entity->{$fieldName}
->setValue($this
->removeDuplicates($values));
$entity
->save();
}
}
/**
* Removes duplicate references from the values array.
*
* @param array $values
* The values array.
*
* @return array
* The values array without duplicates.
*/
private function removeDuplicates(array $values) {
$unique = [];
foreach ($values as $id => $value) {
if (isset($unique[$value['target_id']])) {
unset($values[$id]);
continue;
}
$unique[$value['target_id']] = $value['target_id'];
}
return array_values($values);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ReferenceMigrator:: |
private | property | The reference finder. | |
ReferenceMigrator:: |
private | function | Determines if an entity should be skipped or not. | |
ReferenceMigrator:: |
private | function | Determines if an entire entity type should be skipped or not. | |
ReferenceMigrator:: |
private | function | Finds all names of term reference fields. | |
ReferenceMigrator:: |
public | function | Updates the term reference on all entities from the source to the target. | |
ReferenceMigrator:: |
private | function | Removes duplicate references from the values array. | |
ReferenceMigrator:: |
private | function | Changes the reference of an entity from the source term to the target term. | |
ReferenceMigrator:: |
public | function | ReferenceMigrator constructor. |