EntityOperations.php
Same filename in this branch
Same filename in other branches
- 9 core/modules/content_moderation/src/EntityOperations.php
- 9 core/modules/workspaces/src/EntityOperations.php
- 9 core/modules/views/src/Plugin/views/field/EntityOperations.php
- 8.9.x core/modules/content_moderation/src/EntityOperations.php
- 8.9.x core/modules/workspaces/src/EntityOperations.php
- 8.9.x core/modules/views/src/Plugin/views/field/EntityOperations.php
- 11.x core/modules/content_moderation/src/EntityOperations.php
- 11.x core/modules/workspaces/src/EntityOperations.php
- 11.x core/modules/views/src/Plugin/views/field/EntityOperations.php
Namespace
Drupal\content_moderationFile
-
core/
modules/ content_moderation/ src/ EntityOperations.php
View source
<?php
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\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;
/**
* Defines a class for reacting to entity events.
*
* @internal
*/
class EntityOperations implements ContainerInjectionInterface {
/**
* The Moderation Information service.
*
* @var \Drupal\content_moderation\ModerationInformationInterface
*/
protected $moderationInfo;
/**
* The Entity Type Manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The Form Builder service.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* The entity bundle information service.
*
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected $bundleInfo;
/**
* The router builder service.
*
* @var \Drupal\Core\Routing\RouteBuilderInterface
*/
protected $routerBuilder;
/**
* Constructs a new EntityOperations object.
*
* @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info
* Moderation information service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager service.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* 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, RouteBuilderInterface $router_builder) {
$this->moderationInfo = $moderation_info;
$this->entityTypeManager = $entity_type_manager;
$this->formBuilder = $form_builder;
$this->bundleInfo = $bundle_info;
$this->routerBuilder = $router_builder;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('content_moderation.moderation_information'), $container->get('entity_type.manager'), $container->get('form_builder'), $container->get('entity_type.bundle.info'), $container->get('router.builder'));
}
/**
* Acts on an entity and set published status based on the moderation state.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being saved.
*
* @see hook_entity_presave()
*/
public function entityPresave(EntityInterface $entity) {
if (!$this->moderationInfo
->isModeratedEntity($entity)) {
return;
}
if ($entity->moderation_state->value) {
$workflow = $this->moderationInfo
->getWorkflowForEntity($entity);
/** @var \Drupal\content_moderation\ContentModerationState $current_state */
$current_state = $workflow->getTypePlugin()
->getState($entity->moderation_state->value);
// This entity is default if it is new, the default revision, or the
// default revision is not published.
$update_default_revision = $entity->isNew() || $current_state->isDefaultRevisionState() || !$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());
}
}
/**
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity that was just saved.
*
* @see hook_entity_insert()
*/
public function entityInsert(EntityInterface $entity) {
if ($this->moderationInfo
->isModeratedEntity($entity)) {
$this->updateOrCreateFromEntity($entity);
}
}
/**
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity that was just saved.
*
* @see hook_entity_update()
*/
public function entityUpdate(EntityInterface $entity) {
if ($this->moderationInfo
->isModeratedEntity($entity)) {
$this->updateOrCreateFromEntity($entity);
}
elseif ($entity instanceof Workflow && $entity->getTypePlugin()
->getPluginId() == 'content_moderation') {
$this->routerBuilder
->setRebuildNeeded();
}
}
/**
* Creates or updates the moderation state of an entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to update or create a moderation state for.
*/
protected function updateOrCreateFromEntity(EntityInterface $entity) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$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) {
$content_moderation_state = $storage->create([
'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();
}
// Sync translations.
if ($entity->getEntityType()
->hasKey('langcode')) {
$entity_langcode = $entity->language()
->getId();
if ($entity->isDefaultTranslation()) {
$content_moderation_state->langcode = $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 */
if (!$moderation_state) {
$moderation_state = $workflow->getTypePlugin()
->getInitialState($entity)
->id();
}
$content_moderation_state->set('content_entity_revision_id', $entity_revision_id);
$content_moderation_state->set('moderation_state', $moderation_state);
ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state);
}
/**
* @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 entity revision being deleted.
*
* @see hook_entity_revision_delete()
*/
public function entityRevisionDelete(EntityInterface $entity) {
if ($content_moderation_state = ContentModerationStateEntity::loadFromModeratedEntity($entity)) {
if ($content_moderation_state->isDefaultRevision()) {
$content_moderation_state->delete();
}
else {
$this->entityTypeManager
->getStorage('content_moderation_state')
->deleteRevision($content_moderation_state->getRevisionId());
}
}
}
/**
* @param \Drupal\Core\Entity\EntityInterface $translation
* The entity translation being deleted.
*
* @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()
*/
public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
if (!$this->moderationInfo
->isModeratedEntity($entity)) {
return;
}
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;
}
// 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;
}
if (!$entity->isLatestRevision() && !$entity->isLatestTranslationAffectedRevision()) {
return;
}
$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;
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
EntityOperations | Defines a class for reacting to entity events. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.