X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Fcontent_moderation%2Fsrc%2FEntityOperations.php;fp=web%2Fcore%2Fmodules%2Fcontent_moderation%2Fsrc%2FEntityOperations.php;h=a7fcf7e8d925564688513fc409c42631850f2330;hp=3f66100581bdc5280ff8329a069656d62a88b005;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hpb=aea91e65e895364e460983b890e295aa5d5540a5 diff --git a/web/core/modules/content_moderation/src/EntityOperations.php b/web/core/modules/content_moderation/src/EntityOperations.php index 3f6610058..a7fcf7e8d 100644 --- a/web/core/modules/content_moderation/src/EntityOperations.php +++ b/web/core/modules/content_moderation/src/EntityOperations.php @@ -3,19 +3,20 @@ namespace Drupal\content_moderation; use Drupal\content_moderation\Entity\ContentModerationState as ContentModerationStateEntity; +use Drupal\content_moderation\Entity\ContentModerationStateInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; -use Drupal\Core\TypedData\TranslatableInterface; use Drupal\content_moderation\Form\EntityModerationForm; -use Drupal\workflows\WorkflowInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a class for reacting to entity events. + * + * @internal */ class EntityOperations implements ContainerInjectionInterface { @@ -40,13 +41,6 @@ class EntityOperations implements ContainerInjectionInterface { */ protected $formBuilder; - /** - * The Revision Tracker service. - * - * @var \Drupal\content_moderation\RevisionTrackerInterface - */ - protected $tracker; - /** * The entity bundle information service. * @@ -63,16 +57,13 @@ class EntityOperations implements ContainerInjectionInterface { * Entity type manager service. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder. - * @param \Drupal\content_moderation\RevisionTrackerInterface $tracker - * The revision tracker. * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info * The entity bundle information service. */ - public function __construct(ModerationInformationInterface $moderation_info, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder, RevisionTrackerInterface $tracker, EntityTypeBundleInfoInterface $bundle_info) { + public function __construct(ModerationInformationInterface $moderation_info, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder, EntityTypeBundleInfoInterface $bundle_info) { $this->moderationInfo = $moderation_info; $this->entityTypeManager = $entity_type_manager; $this->formBuilder = $form_builder; - $this->tracker = $tracker; $this->bundleInfo = $bundle_info; } @@ -84,7 +75,6 @@ class EntityOperations implements ContainerInjectionInterface { $container->get('content_moderation.moderation_information'), $container->get('entity_type.manager'), $container->get('form_builder'), - $container->get('content_moderation.revision_tracker'), $container->get('entity_type.bundle.info') ); } @@ -94,6 +84,8 @@ class EntityOperations implements ContainerInjectionInterface { * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity being saved. + * + * @see hook_entity_presave() */ public function entityPresave(EntityInterface $entity) { if (!$this->moderationInfo->isModeratedEntity($entity)) { @@ -103,23 +95,24 @@ class EntityOperations implements ContainerInjectionInterface { if ($entity->moderation_state->value) { $workflow = $this->moderationInfo->getWorkflowForEntity($entity); /** @var \Drupal\content_moderation\ContentModerationState $current_state */ - $current_state = $workflow->getState($entity->moderation_state->value); + $current_state = $workflow->getTypePlugin() + ->getState($entity->moderation_state->value); // This entity is default if it is new, a new translation, the default // revision, or the default revision is not published. $update_default_revision = $entity->isNew() || $entity->isNewTranslation() || $current_state->isDefaultRevisionState() - || !$this->isDefaultRevisionPublished($entity, $workflow); + || !$this->moderationInfo->isDefaultRevisionPublished($entity); // Fire per-entity-type logic for handling the save process. - $this->entityTypeManager->getHandler($entity->getEntityTypeId(), 'moderation')->onPresave($entity, $update_default_revision, $current_state->isPublishedState()); + $this->entityTypeManager + ->getHandler($entity->getEntityTypeId(), 'moderation') + ->onPresave($entity, $update_default_revision, $current_state->isPublishedState()); } } /** - * Hook bridge. - * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity that was just saved. * @@ -128,13 +121,10 @@ class EntityOperations implements ContainerInjectionInterface { public function entityInsert(EntityInterface $entity) { if ($this->moderationInfo->isModeratedEntity($entity)) { $this->updateOrCreateFromEntity($entity); - $this->setLatestRevision($entity); } } /** - * Hook bridge. - * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity that was just saved. * @@ -143,7 +133,6 @@ class EntityOperations implements ContainerInjectionInterface { public function entityUpdate(EntityInterface $entity) { if ($this->moderationInfo->isModeratedEntity($entity)) { $this->updateOrCreateFromEntity($entity); - $this->setLatestRevision($entity); } } @@ -154,31 +143,19 @@ class EntityOperations implements ContainerInjectionInterface { * The entity to update or create a moderation state for. */ protected function updateOrCreateFromEntity(EntityInterface $entity) { - $moderation_state = $entity->moderation_state->value; - $workflow = $this->moderationInfo->getWorkflowForEntity($entity); /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ - if (!$moderation_state) { - $moderation_state = $workflow->getTypePlugin()->getInitialState($workflow, $entity)->id(); - } - - // @todo what if $entity->moderation_state is null at this point? - $entity_type_id = $entity->getEntityTypeId(); - $entity_id = $entity->id(); $entity_revision_id = $entity->getRevisionId(); + $workflow = $this->moderationInfo->getWorkflowForEntity($entity); + $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); - $storage = $this->entityTypeManager->getStorage('content_moderation_state'); - $entities = $storage->loadByProperties([ - 'content_entity_type_id' => $entity_type_id, - 'content_entity_id' => $entity_id, - 'workflow' => $workflow->id(), - ]); - - /** @var \Drupal\content_moderation\ContentModerationStateInterface $content_moderation_state */ - $content_moderation_state = reset($entities); if (!($content_moderation_state instanceof ContentModerationStateInterface)) { + $storage = $this->entityTypeManager->getStorage('content_moderation_state'); $content_moderation_state = $storage->create([ - 'content_entity_type_id' => $entity_type_id, - 'content_entity_id' => $entity_id, + 'content_entity_type_id' => $entity->getEntityTypeId(), + 'content_entity_id' => $entity->id(), + // Make sure that the moderation state entity has the same language code + // as the moderated entity. + 'langcode' => $entity->language()->getId(), ]); $content_moderation_state->workflow->target_id = $workflow->id(); } @@ -200,31 +177,69 @@ class EntityOperations implements ContainerInjectionInterface { } // Create the ContentModerationState entity for the inserted entity. + $moderation_state = $entity->moderation_state->value; + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + if (!$moderation_state) { + $moderation_state = $workflow->getTypePlugin()->getInitialState($entity)->id(); + } + + // @todo what if $entity->moderation_state is null at this point? $content_moderation_state->set('content_entity_revision_id', $entity_revision_id); $content_moderation_state->set('moderation_state', $moderation_state); ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state); } /** - * Set the latest revision. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity being deleted. * + * @see hook_entity_delete() + */ + public function entityDelete(EntityInterface $entity) { + $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); + if ($content_moderation_state) { + $content_moderation_state->delete(); + } + } + + /** * @param \Drupal\Core\Entity\EntityInterface $entity - * The content entity to create content_moderation_state entity for. + * The entity revision being deleted. + * + * @see hook_entity_revision_delete() */ - protected function setLatestRevision(EntityInterface $entity) { + public function entityRevisionDelete(EntityInterface $entity) { /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ - $this->tracker->setLatestRevision( - $entity->getEntityTypeId(), - $entity->id(), - $entity->language()->getId(), - $entity->getRevisionId() - ); + if (!$entity->isDefaultRevision()) { + $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); + if ($content_moderation_state) { + $this->entityTypeManager + ->getStorage('content_moderation_state') + ->deleteRevision($content_moderation_state->getRevisionId()); + } + } } /** - * Act on entities being assembled before rendering. + * @param \Drupal\Core\Entity\EntityInterface $translation + * The entity translation being deleted. * - * This is a hook bridge. + * @see hook_entity_translation_delete() + */ + public function entityTranslationDelete(EntityInterface $translation) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $translation */ + if (!$translation->isDefaultTranslation()) { + $langcode = $translation->language()->getId(); + $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($translation); + if ($content_moderation_state && $content_moderation_state->hasTranslation($langcode)) { + $content_moderation_state->removeTranslation($langcode); + ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state); + } + } + } + + /** + * Act on entities being assembled before rendering. * * @see hook_entity_view() * @see EntityFieldManagerInterface::getExtraFields() @@ -239,46 +254,18 @@ class EntityOperations implements ContainerInjectionInterface { if ($this->moderationInfo->isLiveRevision($entity)) { return; } + // Don't display the moderation form when when: + // - The revision is not translation affected. + // - There are more than one translation languages. + // - The entity has pending revisions. + if (!$this->moderationInfo->isPendingRevisionAllowed($entity)) { + 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']; } } - /** - * Check if the default revision for the given entity is published. - * - * The default revision is the same as the entity retrieved by "default" from - * the storage handler. If the entity is translated, check if any of the - * translations are published. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being saved. - * @param \Drupal\workflows\WorkflowInterface $workflow - * The workflow being applied to the entity. - * - * @return bool - * TRUE if the default revision is published. FALSE otherwise. - */ - protected function isDefaultRevisionPublished(EntityInterface $entity, WorkflowInterface $workflow) { - $default_revision = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id()); - - // Ensure we are checking all translations of the default revision. - if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) { - // Loop through each language that has a translation. - foreach ($default_revision->getTranslationLanguages() as $language) { - // Load the translated revision. - $language_revision = $default_revision->getTranslation($language->getId()); - // Return TRUE if a translation with a published state is found. - if ($workflow->getState($language_revision->moderation_state->value)->isPublishedState()) { - return TRUE; - } - } - } - - return $workflow->getState($default_revision->moderation_state->value)->isPublishedState(); - } - }