Chris@0: moderationInfo = $moderation_info; Chris@0: $this->entityTypeManager = $entity_type_manager; Chris@0: $this->formBuilder = $form_builder; Chris@0: $this->bundleInfo = $bundle_info; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function create(ContainerInterface $container) { Chris@0: return new static( Chris@0: $container->get('content_moderation.moderation_information'), Chris@0: $container->get('entity_type.manager'), Chris@0: $container->get('form_builder'), Chris@0: $container->get('entity_type.bundle.info') Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Acts on an entity and set published status based on the moderation state. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity being saved. Chris@0: * Chris@0: * @see hook_entity_presave() Chris@0: */ Chris@0: public function entityPresave(EntityInterface $entity) { Chris@0: if (!$this->moderationInfo->isModeratedEntity($entity)) { Chris@0: return; Chris@0: } Chris@0: Chris@0: if ($entity->moderation_state->value) { Chris@0: $workflow = $this->moderationInfo->getWorkflowForEntity($entity); Chris@0: /** @var \Drupal\content_moderation\ContentModerationState $current_state */ Chris@0: $current_state = $workflow->getTypePlugin() Chris@0: ->getState($entity->moderation_state->value); Chris@0: Chris@0: // This entity is default if it is new, a new translation, the default Chris@0: // revision, or the default revision is not published. Chris@0: $update_default_revision = $entity->isNew() Chris@0: || $entity->isNewTranslation() Chris@0: || $current_state->isDefaultRevisionState() Chris@0: || !$this->moderationInfo->isDefaultRevisionPublished($entity); Chris@0: Chris@0: // Fire per-entity-type logic for handling the save process. Chris@0: $this->entityTypeManager Chris@0: ->getHandler($entity->getEntityTypeId(), 'moderation') Chris@0: ->onPresave($entity, $update_default_revision, $current_state->isPublishedState()); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity that was just saved. Chris@0: * Chris@0: * @see hook_entity_insert() Chris@0: */ Chris@0: public function entityInsert(EntityInterface $entity) { Chris@0: if ($this->moderationInfo->isModeratedEntity($entity)) { Chris@0: $this->updateOrCreateFromEntity($entity); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity that was just saved. Chris@0: * Chris@0: * @see hook_entity_update() Chris@0: */ Chris@0: public function entityUpdate(EntityInterface $entity) { Chris@0: if ($this->moderationInfo->isModeratedEntity($entity)) { Chris@0: $this->updateOrCreateFromEntity($entity); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Creates or updates the moderation state of an entity. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity to update or create a moderation state for. Chris@0: */ Chris@0: protected function updateOrCreateFromEntity(EntityInterface $entity) { Chris@0: /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ Chris@0: $entity_revision_id = $entity->getRevisionId(); Chris@0: $workflow = $this->moderationInfo->getWorkflowForEntity($entity); Chris@0: $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); Chris@0: Chris@0: if (!($content_moderation_state instanceof ContentModerationStateInterface)) { Chris@0: $storage = $this->entityTypeManager->getStorage('content_moderation_state'); Chris@0: $content_moderation_state = $storage->create([ Chris@0: 'content_entity_type_id' => $entity->getEntityTypeId(), Chris@0: 'content_entity_id' => $entity->id(), Chris@0: // Make sure that the moderation state entity has the same language code Chris@0: // as the moderated entity. Chris@0: 'langcode' => $entity->language()->getId(), Chris@0: ]); Chris@0: $content_moderation_state->workflow->target_id = $workflow->id(); Chris@0: } Chris@0: elseif ($content_moderation_state->content_entity_revision_id->value != $entity_revision_id) { Chris@0: // If a new revision of the content has been created, add a new content Chris@0: // moderation state revision. Chris@0: $content_moderation_state->setNewRevision(TRUE); Chris@0: } Chris@0: Chris@0: // Sync translations. Chris@0: if ($entity->getEntityType()->hasKey('langcode')) { Chris@0: $entity_langcode = $entity->language()->getId(); Chris@0: if (!$content_moderation_state->hasTranslation($entity_langcode)) { Chris@0: $content_moderation_state->addTranslation($entity_langcode); Chris@0: } Chris@0: if ($content_moderation_state->language()->getId() !== $entity_langcode) { Chris@0: $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode); Chris@0: } Chris@0: } Chris@0: Chris@0: // Create the ContentModerationState entity for the inserted entity. Chris@0: $moderation_state = $entity->moderation_state->value; Chris@0: /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ Chris@0: if (!$moderation_state) { Chris@0: $moderation_state = $workflow->getTypePlugin()->getInitialState($entity)->id(); Chris@0: } Chris@0: Chris@0: // @todo what if $entity->moderation_state is null at this point? Chris@0: $content_moderation_state->set('content_entity_revision_id', $entity_revision_id); Chris@0: $content_moderation_state->set('moderation_state', $moderation_state); Chris@0: ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity being deleted. Chris@0: * Chris@0: * @see hook_entity_delete() Chris@0: */ Chris@0: public function entityDelete(EntityInterface $entity) { Chris@0: $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); Chris@0: if ($content_moderation_state) { Chris@0: $content_moderation_state->delete(); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity revision being deleted. Chris@0: * Chris@0: * @see hook_entity_revision_delete() Chris@0: */ Chris@0: public function entityRevisionDelete(EntityInterface $entity) { Chris@0: /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ Chris@0: if (!$entity->isDefaultRevision()) { Chris@0: $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity); Chris@0: if ($content_moderation_state) { Chris@0: $this->entityTypeManager Chris@0: ->getStorage('content_moderation_state') Chris@0: ->deleteRevision($content_moderation_state->getRevisionId()); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param \Drupal\Core\Entity\EntityInterface $translation Chris@0: * The entity translation being deleted. Chris@0: * Chris@0: * @see hook_entity_translation_delete() Chris@0: */ Chris@0: public function entityTranslationDelete(EntityInterface $translation) { Chris@0: /** @var \Drupal\Core\Entity\ContentEntityInterface $translation */ Chris@0: if (!$translation->isDefaultTranslation()) { Chris@0: $langcode = $translation->language()->getId(); Chris@0: $content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($translation); Chris@0: if ($content_moderation_state && $content_moderation_state->hasTranslation($langcode)) { Chris@0: $content_moderation_state->removeTranslation($langcode); Chris@0: ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Act on entities being assembled before rendering. Chris@0: * Chris@0: * @see hook_entity_view() Chris@0: * @see EntityFieldManagerInterface::getExtraFields() Chris@0: */ Chris@0: public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { Chris@0: if (!$this->moderationInfo->isModeratedEntity($entity)) { Chris@0: return; Chris@0: } Chris@0: if (!$this->moderationInfo->isLatestRevision($entity)) { Chris@0: return; Chris@0: } Chris@0: if ($this->moderationInfo->isLiveRevision($entity)) { Chris@0: return; Chris@0: } Chris@0: // Don't display the moderation form when when: Chris@0: // - The revision is not translation affected. Chris@0: // - There are more than one translation languages. Chris@0: // - The entity has pending revisions. Chris@0: if (!$this->moderationInfo->isPendingRevisionAllowed($entity)) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $component = $display->getComponent('content_moderation_control'); Chris@0: if ($component) { Chris@0: $build['content_moderation_control'] = $this->formBuilder->getForm(EntityModerationForm::class, $entity); Chris@0: } Chris@0: } Chris@0: Chris@0: }