You are here

class ConfigEntityRevisionsEntityTypeInfo in Config Entity Revisions 8.2

Class ConfigEntityRevisionsEntityTypeInfo.

@package Drupal\config_entity_revisions

Hierarchy

Expanded class hierarchy of ConfigEntityRevisionsEntityTypeInfo

1 string reference to 'ConfigEntityRevisionsEntityTypeInfo'
config_entity_revisions.services.yml in ./config_entity_revisions.services.yml
config_entity_revisions.services.yml
1 service uses ConfigEntityRevisionsEntityTypeInfo
Drupal\content_moderation\EntityTypeInfo in ./config_entity_revisions.services.yml
\Drupal\config_entity_revisions\ConfigEntityRevisionsEntityTypeInfo

File

src/ConfigEntityRevisionsEntityTypeInfo.php, line 18

Namespace

Drupal\config_entity_revisions
View source
class ConfigEntityRevisionsEntityTypeInfo extends EntityTypeInfo {

  /**
   * Adds Moderation configuration to appropriate entity types.
   *
   * We add moderation to the config entities so that the moderation state
   * handler gets used.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
   *   The master entity type list to alter.
   *
   * @see hook_entity_type_alter()
   */
  public function entityTypeAlter(array &$entity_types) {
    foreach ($entity_types as $entity_type_id => $entity_type) {
      $traitsUsed = class_uses($entity_type
        ->getClass());
      if (!empty($traitsUsed['Drupal\\config_entity_revisions\\ConfigEntityRevisionsConfigEntityTrait'])) {
        $entity_types[$entity_type_id] = $this
          ->addModerationToEntityTypes($entity_type);
      }
    }
    parent::entityTypeAlter($entity_types);
  }

  /**
   * Modifies an entity definition to include moderation support.
   *
   * This primarily just means an extra handler. A Generic one is provided,
   * but individual entity types can provide their own as appropriate.
   *
   * Note that this function name ends in 's' to avoid having an incompatible
   * declaration with the one in content moderation.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $type
   *   The content entity definition to modify.
   *
   * @return \Drupal\Core\Entity\EntityTypeInterface
   *   The modified content entity definition.
   */
  protected function addModerationToEntityTypes(EntityTypeInterface $type) {
    if (!$type
      ->hasHandlerClass('moderation')) {
      $handler_class = !empty($this->moderationHandlers[$type
        ->id()]) ? $this->moderationHandlers[$type
        ->id()] : ConfigEntityRevisionsModerationHandler::class;
      $type
        ->setHandlerClass('moderation', $handler_class);
    }
    if (!$type
      ->hasLinkTemplate('latest-version') && $type
      ->hasLinkTemplate('canonical')) {
      $type
        ->setLinkTemplate('latest-version', $type
        ->getLinkTemplate('canonical') . '/latest');
    }
    $providers = $type
      ->getRouteProviderClasses() ?: [];
    if (empty($providers['moderation'])) {
      $providers['moderation'] = EntityModerationRouteProvider::class;
      $type
        ->setHandlerClass('route_provider', $providers);
    }
    return $type;
  }

  /**
   * Replaces the entity form entity object with a proper revision object.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity being edited.
   * @param string $operation
   *   The entity form operation.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @see hook_entity_prepare_form()
   */
  public function entityPrepareForm(EntityInterface $entity, $operation, FormStateInterface $form_state) {
    if (!$entity instanceof ConfigEntityRevisionsConfigEntityContainerInterface) {
      parent::entityPrepareForm($entity, $operation, $form_state);
      return;
    }

    /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
    $form_object = $form_state
      ->getFormObject();
    if (!($this
      ->isModeratedEntityEditForm($form_object) && !$entity
      ->isNew())) {
      return;
    }

    // Generate a proper revision object for the current entity. This allows
    // to correctly handle translatable entities having pending revisions.

    /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
    $storage = $this->entityTypeManager
      ->getStorage($entity
      ->getEntityTypeId());

    /** @var \Drupal\Core\Entity\ContentEntityInterface $new_revision */
    $new_revision = $storage
      ->createRevision($entity, FALSE);

    // Restore the revision ID as other modules may expect to find it still
    // populated. This will reset the "new revision" flag, however the entity
    // object will be marked as a new revision again on submit.
    // @see \Drupal\Core\Entity\ContentEntityForm::buildEntity()
    $revision_key = $new_revision
      ->getEntityType()
      ->getKey('revision');
    $new_revision
      ->set($revision_key, $new_revision
      ->getLoadedRevisionId());
    $form_object
      ->setEntity($new_revision);
  }

  /**
   * Alters bundle forms to enforce revision handling.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param string $form_id
   *   The form id.
   *
   * @see hook_form_alter()
   */
  public function formAlter(array &$form, FormStateInterface $form_state, $form_id) {
    $form_object = $form_state
      ->getFormObject();
    if ($form_object instanceof BundleEntityFormBase) {
      $config_entity_type = $form_object
        ->getEntity()
        ->getEntityType();
      $bundle_of = $config_entity_type
        ->getBundleOf();
      if ($bundle_of && ($bundle_of_entity_type = $this->entityTypeManager
        ->getDefinition($bundle_of)) && $this->moderationInfo
        ->canModerateEntitiesOfEntityType($bundle_of_entity_type)) {
        $this->entityTypeManager
          ->getHandler($config_entity_type
          ->getBundleOf(), 'moderation')
          ->enforceRevisionsBundleFormAlter($form, $form_state, $form_id);
      }
    }
    elseif ($this
      ->isModeratedEntityEditForm($form_object)) {

      /** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */

      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
      $entity = $form_object
        ->getEntity();
      if ($this->moderationInfo
        ->isModeratedEntity($entity)) {
        $this->entityTypeManager
          ->getHandler($entity
          ->getEntityTypeId(), 'moderation')
          ->enforceRevisionsEntityFormAlter($form, $form_state, $form_id);

        // Submit handler to redirect to the latest version, if available.
        $form['actions']['submit']['#submit'][] = [
          ConfigEntityRevisionsEntityTypeInfo::class,
          'bundleFormRedirect',
        ];

        // Move the 'moderation_state' field widget to the footer region, if
        // available.
        if (isset($form['footer'])) {
          $form['moderation_state']['#group'] = 'footer';
        }

        // If the publishing status exists in the meta region, replace it with
        // the current state instead.
        if (isset($form['meta']['published'])) {
          $form['meta']['published']['#markup'] = $this->moderationInfo
            ->getWorkflowForEntity($entity)
            ->getTypePlugin()
            ->getState($entity->moderation_state->value)
            ->label();
        }
      }
    }
  }

  /**
   * Whether this type of config entity has moderation enabled.
   *
   * @param string $entity
   *   The configuration entity.
   *
   * @return bool
   *   Whether the config entity type is moderated.
   */
  public function shouldModerateConfigEntity($entity) {
    if ($this->moderationInfo
      ->canModerateEntitiesOfEntityType($entity
      ->getEntityType())) {
      $bundles = $this->bundleInfo
        ->getBundleInfo('config_entity_revisions');
      $key = $entity
        ->getBundleName();
      return isset($bundles[$key]['workflow']);
    }
    return FALSE;
  }

  /**
   * Checks whether the specified form allows to edit a moderated entity.
   *
   * @param \Drupal\Core\Form\FormInterface $form_object
   *   The form object.
   *
   * @return bool
   *   TRUE if the form should get form moderation, FALSE otherwise.
   */
  protected function isModeratedEntityEditForm(FormInterface $form_object) {
    if ($form_object instanceof ConfigEntityRevisionsEditFormInterface && in_array($form_object
      ->getOperation(), [
      'edit',
      'default',
    ], TRUE)) {
      return $this
        ->shouldModerateConfigEntity($form_object
        ->getEntity());
    }
    return parent::isModeratedEntityEditForm($form_object);
  }

  /**
   * Returns an iterable list of entity names and bundle names under moderation.
   *
   * That is, this method returns a list of bundles that have Content
   * Moderation enabled on them.
   *
   * @return \Generator
   *   A generator, yielding a 2 element associative array:
   *   - entity: The machine name of an entity type, such as "node" or
   *     "block_content".
   *   - bundle: The machine name of a bundle, such as "page" or "article".
   */
  protected function getModeratedBundles() {
    $entity_types = array_filter($this->entityTypeManager
      ->getDefinitions(), [
      $this->moderationInfo,
      'canModerateEntitiesOfEntityType',
    ]);
    foreach ($entity_types as $type_name => $type) {
      foreach ($this->bundleInfo
        ->getBundleInfo($type_name) as $bundle_id => $bundle) {
        if ($this->moderationInfo
          ->shouldModerateEntitiesOfBundle($type, $bundle_id)) {
          (yield [
            'entity' => $type_name,
            'bundle' => $bundle_id,
          ]);
        }
      }
    }
  }

  /**
   * Redirect content entity edit forms on save, if there is a pending revision.
   *
   * When saving their changes, editors should see those changes displayed on
   * the next page.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public static function bundleFormRedirect(array &$form, FormStateInterface $form_state) {

    /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $entity = $form_state
      ->getFormObject()
      ->getEntity();
    if ($entity instanceof ConfigEntityRevisionsConfigEntityContainerInterface) {
      $entity = $entity
        ->revisionedEntity();
    }
    $moderation_info = \Drupal::getContainer()
      ->get('content_moderation.moderation_information');
    if ($moderation_info
      ->hasPendingRevision($entity) && $entity
      ->hasLinkTemplate('latest-version')) {
      $entity_type_id = $entity
        ->getEntityTypeId();
      $form_state
        ->setRedirect("entity.{$entity_type_id}.latest_version", [
        $entity_type_id => $entity
          ->id(),
      ]);
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConfigEntityRevisionsEntityTypeInfo::addModerationToEntityTypes protected function Modifies an entity definition to include moderation support.
ConfigEntityRevisionsEntityTypeInfo::bundleFormRedirect public static function Redirect content entity edit forms on save, if there is a pending revision.
ConfigEntityRevisionsEntityTypeInfo::entityPrepareForm public function Replaces the entity form entity object with a proper revision object.
ConfigEntityRevisionsEntityTypeInfo::entityTypeAlter public function Adds Moderation configuration to appropriate entity types.
ConfigEntityRevisionsEntityTypeInfo::formAlter public function Alters bundle forms to enforce revision handling.
ConfigEntityRevisionsEntityTypeInfo::getModeratedBundles protected function Returns an iterable list of entity names and bundle names under moderation.
ConfigEntityRevisionsEntityTypeInfo::isModeratedEntityEditForm protected function Checks whether the specified form allows to edit a moderated entity.
ConfigEntityRevisionsEntityTypeInfo::shouldModerateConfigEntity public function Whether this type of config entity has moderation enabled.