use Drupal\content_moderation\Entity\ContentModerationState as ContentModerationStateEntity;
use Drupal\content_moderation\Entity\ContentModerationStateInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\content_moderation\Form\EntityModerationForm;
+use Drupal\Core\Routing\RouteBuilderInterface;
+use Drupal\workflows\Entity\Workflow;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
*/
protected $bundleInfo;
+ /**
+ * The router builder service.
+ *
+ * @var \Drupal\Core\Routing\RouteBuilderInterface
+ */
+ protected $routerBuilder;
+
/**
* Constructs a new EntityOperations object.
*
* The form builder.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info
* The entity bundle information service.
+ * @param \Drupal\Core\Routing\RouteBuilderInterface $router_builder
+ * The router builder service.
*/
- public function __construct(ModerationInformationInterface $moderation_info, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder, EntityTypeBundleInfoInterface $bundle_info) {
+ public function __construct(ModerationInformationInterface $moderation_info, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder, EntityTypeBundleInfoInterface $bundle_info, RouteBuilderInterface $router_builder) {
$this->moderationInfo = $moderation_info;
$this->entityTypeManager = $entity_type_manager;
$this->formBuilder = $form_builder;
$this->bundleInfo = $bundle_info;
+ $this->routerBuilder = $router_builder;
}
/**
$container->get('content_moderation.moderation_information'),
$container->get('entity_type.manager'),
$container->get('form_builder'),
- $container->get('entity_type.bundle.info')
+ $container->get('entity_type.bundle.info'),
+ $container->get('router.builder')
);
}
$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.
+ // This entity is default if it is new, the default revision, or the
+ // default revision is not published.
$update_default_revision = $entity->isNew()
- || $entity->isNewTranslation()
|| $current_state->isDefaultRevisionState()
|| !$this->moderationInfo->isDefaultRevisionPublished($entity);
if ($this->moderationInfo->isModeratedEntity($entity)) {
$this->updateOrCreateFromEntity($entity);
}
+ // When updating workflow settings for Content Moderation, we need to
+ // rebuild routes as we may be enabling new entity types and the related
+ // entity forms.
+ elseif ($entity instanceof Workflow && $entity->getTypePlugin()->getPluginId() == 'content_moderation') {
+ $this->routerBuilder->setRebuildNeeded();
+ }
}
/**
$entity_revision_id = $entity->getRevisionId();
$workflow = $this->moderationInfo->getWorkflowForEntity($entity);
$content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity);
+ /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
+ $storage = $this->entityTypeManager->getStorage('content_moderation_state');
if (!($content_moderation_state instanceof ContentModerationStateInterface)) {
- $storage = $this->entityTypeManager->getStorage('content_moderation_state');
$content_moderation_state = $storage->create([
'content_entity_type_id' => $entity->getEntityTypeId(),
'content_entity_id' => $entity->id(),
]);
$content_moderation_state->workflow->target_id = $workflow->id();
}
- elseif ($content_moderation_state->content_entity_revision_id->value != $entity_revision_id) {
- // If a new revision of the content has been created, add a new content
- // moderation state revision.
- $content_moderation_state->setNewRevision(TRUE);
- }
// Sync translations.
if ($entity->getEntityType()->hasKey('langcode')) {
$entity_langcode = $entity->language()->getId();
- if (!$content_moderation_state->hasTranslation($entity_langcode)) {
- $content_moderation_state->addTranslation($entity_langcode);
+ if ($entity->isDefaultTranslation()) {
+ $content_moderation_state->langcode = $entity_langcode;
}
- if ($content_moderation_state->language()->getId() !== $entity_langcode) {
- $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode);
+ else {
+ if (!$content_moderation_state->hasTranslation($entity_langcode)) {
+ $content_moderation_state->addTranslation($entity_langcode);
+ }
+ if ($content_moderation_state->language()->getId() !== $entity_langcode) {
+ $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode);
+ }
}
}
+ // If a new revision of the content has been created, add a new content
+ // moderation state revision.
+ if (!$content_moderation_state->isNew() && $content_moderation_state->content_entity_revision_id->value != $entity_revision_id) {
+ $content_moderation_state = $storage->createRevision($content_moderation_state, $entity->isDefaultRevision());
+ }
+
// Create the ContentModerationState entity for the inserted entity.
$moderation_state = $entity->moderation_state->value;
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$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);
* @see EntityFieldManagerInterface::getExtraFields()
*/
public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
+ /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
if (!$this->moderationInfo->isModeratedEntity($entity)) {
return;
}
- if (!$this->moderationInfo->isLatestRevision($entity)) {
+ if (isset($entity->in_preview) && $entity->in_preview) {
+ return;
+ }
+ // If the component is not defined for this display, we have nothing to do.
+ if (!$display->getComponent('content_moderation_control')) {
return;
}
- if ($this->moderationInfo->isLiveRevision($entity)) {
+ // The moderation form should be displayed only when viewing the latest
+ // (translation-affecting) revision, unless it was created as published
+ // default revision.
+ if (($entity->isDefaultRevision() || $entity->wasDefaultRevision()) && $this->isPublished($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)) {
+ if (!$entity->isLatestRevision() && !$entity->isLatestTranslationAffectedRevision()) {
return;
}
- $component = $display->getComponent('content_moderation_control');
- if ($component) {
- $build['content_moderation_control'] = $this->formBuilder->getForm(EntityModerationForm::class, $entity);
+ $build['content_moderation_control'] = $this->formBuilder->getForm(EntityModerationForm::class, $entity);
+ }
+
+ /**
+ * Checks if the entity is published.
+ *
+ * This method is optimized to not have to unnecessarily load the moderation
+ * state and workflow if it is not required.
+ *
+ * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+ * The entity to check.
+ *
+ * @return bool
+ * TRUE if the entity is published, FALSE otherwise.
+ */
+ protected function isPublished(ContentEntityInterface $entity) {
+ // If the entity implements EntityPublishedInterface directly, check that
+ // first, otherwise fall back to check through the workflow state.
+ if ($entity instanceof EntityPublishedInterface) {
+ return $entity->isPublished();
+ }
+ if ($moderation_state = $entity->get('moderation_state')->value) {
+ $workflow = $this->moderationInfo->getWorkflowForEntity($entity);
+ return $workflow->getTypePlugin()->getState($moderation_state)->isPublishedState();
}
+ return FALSE;
}
}