/** * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { $this->derivatives = []; foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) { if ($this->moderationInfo->canModerateEntitiesOfEntityType($entity_type)) { $bundle_id = $entity_type->getBundleEntityType(); $this->derivatives["{$bundle_id}.moderation_tab"] = ['route_name' => "entity.{$bundle_id}.moderation", 'title' => $this->t('Manage moderation'), 'base_route' => "entity.{$bundle_id}.edit_form", 'weight' => 30] + $base_plugin_definition; } } $latest_version_entities = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $type) { return $this->moderationInfo->canModerateEntitiesOfEntityType($type) && $type->hasLinkTemplate('latest-version'); }); foreach ($latest_version_entities as $entity_type_id => $entity_type) { $this->derivatives["{$entity_type_id}.latest_version_tab"] = ['route_name' => "entity.{$entity_type_id}.latest_version", 'title' => $this->t('Latest version'), 'base_route' => "entity.{$entity_type_id}.canonical", 'weight' => 1] + $base_plugin_definition; } return $this->derivatives; }
/** * Alters the table and field information from hook_views_data(). * * @param array $data * An array of all information about Views tables and fields, collected from * hook_views_data(), passed by reference. * * @see hook_views_data() */ public function alterViewsData(array &$data) { $entity_types_with_moderation = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $type) { return $this->moderationInformation->canModerateEntitiesOfEntityType($type); }); foreach ($entity_types_with_moderation as $type) { $data[$type->getRevisionTable()]['latest_revision'] = ['title' => t('Is Latest Revision'), 'help' => t('Restrict the view to only revisions that are the latest revision of their entity.'), 'filter' => ['id' => 'latest_revision']]; } }
/** * {@inheritdoc} */ public function convert($value, $definition, $name, array $defaults) { $entity = parent::convert($value, $definition, $name, $defaults); if ($entity && $this->moderationInformation->isModeratedEntity($entity) && !$this->moderationInformation->isLatestRevision($entity)) { $entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults); $latest_revision = $this->moderationInformation->getLatestRevision($entity_type_id, $value); // If the entity type is translatable, ensure we return the proper // translation object for the current context. if ($latest_revision instanceof EntityInterface && $entity instanceof TranslatableInterface) { $latest_revision = $this->entityManager->getTranslationFromContext($latest_revision, NULL, array('operation' => 'entity_upcast')); } if ($latest_revision->isRevisionTranslationAffected()) { $entity = $latest_revision; } } return $entity; }
/** * 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) { $type = $form_object->getEntity()->getEntityType(); if ($this->moderationInfo->canModerateEntitiesOfEntityType($type)) { $this->entityTypeManager->getHandler($type->getBundleOf(), 'moderation')->enforceRevisionsBundleFormAlter($form, $form_state, $form_id); } } elseif ($form_object instanceof ContentEntityFormInterface) { $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'][] = [EntityTypeInfo::class, 'bundleFormRedirect']; } } }
/** * Act on entities being assembled before rendering. * * This is a hook bridge. * * @see hook_entity_view() * @see EntityFieldManagerInterface::getExtraFields() */ public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { if (!$this->moderationInfo->isModeratedEntity($entity)) { return; } if (!$this->moderationInfo->isLatestRevision($entity)) { return; } /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if ($entity->isDefaultRevision()) { return; } $component = $display->getComponent('content_moderation_control'); if ($component) { $build['content_moderation_control'] = $this->formBuilder->getForm(EntityModerationForm::class, $entity); $build['content_moderation_control']['#weight'] = $component['weight']; } }
/** * Determines if this entity is being moderated for the first time. * * If the previous version of the entity has no moderation state, we assume * that means it predates the presence of moderation states. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity being moderated. * * @return bool * TRUE if this is the entity's first time being moderated, FALSE otherwise. */ protected function isFirstTimeModeration(EntityInterface $entity) { $original_entity = $this->moderationInformation->getLatestRevision($entity->getEntityTypeId(), $entity->id()); $original_id = $original_entity->moderation_state->target_id; return !($entity->moderation_state->target_id && $original_entity && $original_id); }
/** * {@inheritdoc} */ public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { $result = parent::access($object, $account, TRUE)->andif(AccessResult::forbiddenIf($this->moderationInfo->isModeratedEntity($object))->addCacheableDependency($object)); return $return_as_object ? $result : $result->isAllowed(); }
/** * Checks that there is a forward revision available. * * This checker assumes the presence of an '_entity_access' requirement key * in the same form as used by EntityAccessCheck. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The parametrized route. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. * * @see \Drupal\Core\Entity\EntityAccessCheck */ public function access(Route $route, RouteMatchInterface $route_match) { // This tab should not show up unless there's a reason to show it. $entity = $this->loadEntity($route, $route_match); return $this->moderationInfo->hasForwardRevision($entity) ? AccessResult::allowed()->addCacheableDependency($entity) : AccessResult::forbidden()->addCacheableDependency($entity); }