You are here

class TermMerger in Term Merge 8

Implements TermMergerInterface to provide a term merger service.

Hierarchy

Expanded class hierarchy of TermMerger

2 files declare their use of TermMerger
TermMergerNodeCrudTest.php in tests/src/Kernel/TermMergerNodeCrudTest.php
TermMergerTermCrudTest.php in tests/src/Kernel/TermMergerTermCrudTest.php
1 string reference to 'TermMerger'
term_merge.services.yml in ./term_merge.services.yml
term_merge.services.yml
1 service uses TermMerger
term_merge.term_merger in ./term_merge.services.yml
Drupal\term_merge\TermMerger

File

src/TermMerger.php, line 13

Namespace

Drupal\term_merge
View source
class TermMerger implements TermMergerInterface {

  /**
   * The taxonomy term storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private $termStorage;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  private $entityTypeManager;

  /**
   * The term reference migration service.
   *
   * @var \Drupal\term_reference_change\ReferenceMigrator
   */
  private $migrator;

  /**
   * The event dispatcher.
   *
   * @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
   */
  private $dispatcher;

  /**
   * TermMerger constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager service.
   * @param \Drupal\term_reference_change\ReferenceMigrator $migrator
   *   The reference migration service.
   * @param \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher $dispatcher
   *   The event dispatcher.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager, ReferenceMigrator $migrator, ContainerAwareEventDispatcher $dispatcher) {
    $this->entityTypeManager = $entityTypeManager;
    $this->termStorage = $this->entityTypeManager
      ->getStorage('taxonomy_term');
    $this->migrator = $migrator;
    $this->dispatcher = $dispatcher;
  }

  /**
   * {@inheritdoc}
   */
  public function mergeIntoNewTerm(array $termsToMerge, $newTermLabel) {
    $this
      ->validateTerms($termsToMerge);
    $firstTerm = reset($termsToMerge);
    $values = [
      'name' => $newTermLabel,
      'vid' => $firstTerm
        ->bundle(),
    ];

    /** @var \Drupal\taxonomy\TermInterface $newTerm */
    $newTerm = $this->termStorage
      ->create($values);
    $this
      ->mergeIntoTerm($termsToMerge, $newTerm);
    return $newTerm;
  }

  /**
   * {@inheritdoc}
   */
  public function mergeIntoTerm(array $termsToMerge, TermInterface $targetTerm) {
    $this
      ->validateTerms($termsToMerge);

    // We have to save the term to make sure we've got an id to reference.
    if ($targetTerm
      ->isNew()) {
      $targetTerm
        ->save();
    }
    $firstTerm = reset($termsToMerge);
    if ($firstTerm
      ->bundle() !== $targetTerm
      ->bundle()) {
      throw new \RuntimeException('The target term must be in the same vocabulary as the terms being merged');
    }
    $this
      ->migrateReferences($termsToMerge, $targetTerm);
    $event = new TermsMergedEvent($termsToMerge, $targetTerm);
    $event = $this->dispatcher
      ->dispatch(TermMergeEventNames::TERMS_MERGED, $event);
    $this->termStorage
      ->delete($termsToMerge);
  }

  /**
   * Asserts that all passed in terms are valid.
   *
   * @param \Drupal\taxonomy\TermInterface[] $termsToAssert
   *   The array to assert.
   */
  private function validateTerms(array $termsToAssert) {
    $this
      ->assertTermsNotEmpty($termsToAssert);
    $this
      ->assertAllTermsHaveSameVocabulary($termsToAssert);
  }

  /**
   * Asserts that all terms have the same vocabulary.
   *
   * @param \Drupal\taxonomy\TermInterface[] $termsToAssert
   *   The array to assert.
   */
  private function assertAllTermsHaveSameVocabulary(array $termsToAssert) {
    $vocabulary = '';
    foreach ($termsToAssert as $term) {
      if (empty($vocabulary)) {
        $vocabulary = $term
          ->bundle();
      }
      if ($vocabulary !== $term
        ->bundle()) {
        throw new \RuntimeException('Only merges within the same vocabulary are supported');
      }
    }
  }

  /**
   * Asserts that the termsToAssert variable is not empty.
   *
   * @param \Drupal\taxonomy\TermInterface[] $termsToAssert
   *   The array to assert.
   */
  private function assertTermsNotEmpty(array $termsToAssert) {
    if (empty($termsToAssert)) {
      throw new \RuntimeException('You must provide at least 1 term');
    }
  }

  /**
   * Updates the term references on all entities referencing multiple terms.
   *
   * @param \Drupal\taxonomy\TermInterface[] $fromTerms
   *   The terms to migrate away from.
   * @param \Drupal\taxonomy\TermInterface $toTerm
   *   The term to migrate to.
   */
  private function migrateReferences(array $fromTerms, TermInterface $toTerm) {
    foreach ($fromTerms as $fromTerm) {
      $this->migrator
        ->migrateReference($fromTerm, $toTerm);
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
TermMerger::$dispatcher private property The event dispatcher.
TermMerger::$entityTypeManager private property The entity type manager.
TermMerger::$migrator private property The term reference migration service.
TermMerger::$termStorage private property The taxonomy term storage.
TermMerger::assertAllTermsHaveSameVocabulary private function Asserts that all terms have the same vocabulary.
TermMerger::assertTermsNotEmpty private function Asserts that the termsToAssert variable is not empty.
TermMerger::mergeIntoNewTerm public function Merges two or more terms into a new term. Overrides TermMergerInterface::mergeIntoNewTerm
TermMerger::mergeIntoTerm public function Merges one or more terms into an existing term. Overrides TermMergerInterface::mergeIntoTerm
TermMerger::migrateReferences private function Updates the term references on all entities referencing multiple terms.
TermMerger::validateTerms private function Asserts that all passed in terms are valid.
TermMerger::__construct public function TermMerger constructor.