EntitySchemaSubscriber.php 6.51 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
<?php

namespace Drupal\workspaces\EventSubscriber;

use Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface;
use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface;
use Drupal\Core\Entity\EntityTypeEventSubscriberTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeListenerInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\workspaces\WorkspaceManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Defines a class for listening to entity schema changes.
 */
class EntitySchemaSubscriber implements EntityTypeListenerInterface, EventSubscriberInterface {

  use EntityTypeEventSubscriberTrait;
  use StringTranslationTrait;

  /**
   * The definition update manager.
   *
   * @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
   */
  protected $entityDefinitionUpdateManager;

  /**
   * The last installed schema definitions.
   *
   * @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
   */
  protected $entityLastInstalledSchemaRepository;

  /**
   * The workspace manager.
   *
   * @var \Drupal\workspaces\WorkspaceManagerInterface
   */
  protected $workspaceManager;

  /**
   * Constructs a new EntitySchemaSubscriber.
   *
   * @param \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $entityDefinitionUpdateManager
   *   Definition update manager.
   * @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entityLastInstalledSchemaRepository
   *   Last definitions.
   * @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
   *   The workspace manager.
   */
  public function __construct(EntityDefinitionUpdateManagerInterface $entityDefinitionUpdateManager, EntityLastInstalledSchemaRepositoryInterface $entityLastInstalledSchemaRepository, WorkspaceManagerInterface $workspace_manager) {
    $this->entityDefinitionUpdateManager = $entityDefinitionUpdateManager;
    $this->entityLastInstalledSchemaRepository = $entityLastInstalledSchemaRepository;
    $this->workspaceManager = $workspace_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return static::getEntityTypeEvents();
  }

  /**
   * {@inheritdoc}
   */
  public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
71 72 73 74 75 76 77 78 79 80 81 82
    // If the entity type is supported by Workspaces, add the revision metadata
    // field.
    if ($this->workspaceManager->isEntityTypeSupported($entity_type)) {
      $this->addRevisionMetadataField($entity_type);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function onFieldableEntityTypeCreate(EntityTypeInterface $entity_type, array $field_storage_definitions) {
    $this->onEntityTypeCreate($entity_type);
83 84 85 86 87 88 89 90 91
  }

  /**
   * {@inheritdoc}
   */
  public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original) {
    // If the entity type is now supported by Workspaces, add the revision
    // metadata field.
    if ($this->workspaceManager->isEntityTypeSupported($entity_type) && !$this->workspaceManager->isEntityTypeSupported($original)) {
92
      $this->addRevisionMetadataField($entity_type);
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    }

    // If the entity type is no longer supported by Workspaces, remove the
    // revision metadata field.
    if ($this->workspaceManager->isEntityTypeSupported($original) && !$this->workspaceManager->isEntityTypeSupported($entity_type)) {
      $revision_metadata_keys = $original->get('revision_metadata_keys');
      $field_storage_definition = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type->id())[$revision_metadata_keys['workspace']];
      $this->entityDefinitionUpdateManager->uninstallFieldStorageDefinition($field_storage_definition);

      $revision_metadata_keys = $entity_type->get('revision_metadata_keys');
      unset($revision_metadata_keys['workspace']);
      $entity_type->set('revision_metadata_keys', $revision_metadata_keys);

      // We are only removing a revision metadata key so we don't need to go
      // through the entity update process.
      $this->entityLastInstalledSchemaRepository->setLastInstalledDefinition($entity_type);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function onFieldableEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original, array $field_storage_definitions, array $original_field_storage_definitions, array &$sandbox = NULL) {
    $this->onEntityTypeUpdate($entity_type, $original);
  }

  /**
   * {@inheritdoc}
   */
  public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
    // Nothing to do here.
  }

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  /**
   * Adds the 'workspace' revision metadata field to an entity type.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type that has been installed or updated.
   */
  protected function addRevisionMetadataField(EntityTypeInterface $entity_type) {
    $revision_metadata_keys = $entity_type->get('revision_metadata_keys');

    if (!isset($revision_metadata_keys['workspace'])) {
      // Bail out if there's an existing field called 'workspace'.
      if ($this->entityDefinitionUpdateManager->getFieldStorageDefinition('workspace', $entity_type->id())) {
        throw new \RuntimeException("An existing 'workspace' field was found for the '{$entity_type->id()}' entity type. Set the 'workspace' revision metadata key to use a different field name and run this update function again.");
      }

      $revision_metadata_keys['workspace'] = 'workspace';
      $entity_type->set('revision_metadata_keys', $revision_metadata_keys);

      // We are only adding a revision metadata key so we don't need to go
      // through the entity update process.
      $this->entityLastInstalledSchemaRepository->setLastInstalledDefinition($entity_type);
    }

    $this->entityDefinitionUpdateManager->installFieldStorageDefinition($revision_metadata_keys['workspace'], $entity_type->id(), 'workspaces', $this->getWorkspaceFieldDefinition());
  }

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
  /**
   * Gets the base field definition for the 'workspace' revision metadata field.
   *
   * @return \Drupal\Core\Field\BaseFieldDefinition
   *   The base field definition.
   */
  protected function getWorkspaceFieldDefinition() {
    return BaseFieldDefinition::create('entity_reference')
      ->setLabel($this->t('Workspace'))
      ->setDescription($this->t('Indicates the workspace that this revision belongs to.'))
      ->setSetting('target_type', 'workspace')
      ->setInternal(TRUE)
      ->setTranslatable(FALSE)
      ->setRevisionable(TRUE);
  }

}