diff --git a/core/modules/content_moderation/config/install/system.action.moderation_state_change_archived.yml b/core/modules/content_moderation/config/install/system.action.moderation_state_change_archived.yml index 9c02b32a5c..5d0f4e4358 100644 --- a/core/modules/content_moderation/config/install/system.action.moderation_state_change_archived.yml +++ b/core/modules/content_moderation/config/install/system.action.moderation_state_change_archived.yml @@ -6,7 +6,7 @@ dependencies: module: - content_moderation id: moderation_state_change_archived -label: 'Change moderation state to Published' +label: 'Change moderation state to Archived' type: node plugin: 'moderation_state_change:editorial-archived' configuration: { } diff --git a/core/modules/content_moderation/config/install/system.action.moderation_state_change_publihsed.yml b/core/modules/content_moderation/config/install/system.action.moderation_state_change_publihsed.yml deleted file mode 100644 index 2643e86234..0000000000 --- a/core/modules/content_moderation/config/install/system.action.moderation_state_change_publihsed.yml +++ /dev/null @@ -1,12 +0,0 @@ -langcode: en -status: true -dependencies: - config: - - workflows.workflow.editorial - module: - - content_moderation -id: moderation_state_change_publihsed -label: 'Change moderation state to Published' -type: node -plugin: 'moderation_state_change:editorial-published' -configuration: { } diff --git a/core/modules/content_moderation/config/schema/content_moderation.schema.yml b/core/modules/content_moderation/config/schema/content_moderation.schema.yml index d48ffe439f..ad3ec684f2 100644 --- a/core/modules/content_moderation/config/schema/content_moderation.schema.yml +++ b/core/modules/content_moderation/config/schema/content_moderation.schema.yml @@ -33,3 +33,16 @@ workflow.type_settings.content_moderation: sequence: type: string label: 'Bundle ID' + +# @todo make this schema dynamic. +action.configuration.moderation_state_change_archived: + type: action_configuration_default + label: 'Change moderation state to Archived' + +action.configuration.moderation_state_change_draft: + type: action_configuration_default + label: 'Change moderation state to Draft' + +action.configuration.moderation_state_change_published: + type: action_configuration_default + label: 'Change moderation state to Published' diff --git a/core/modules/content_moderation/src/Plugin/Action/ModerationStateChange.php b/core/modules/content_moderation/src/Plugin/Action/ModerationStateChange.php index 33dedc25c5..1920597ea4 100644 --- a/core/modules/content_moderation/src/Plugin/Action/ModerationStateChange.php +++ b/core/modules/content_moderation/src/Plugin/Action/ModerationStateChange.php @@ -3,11 +3,9 @@ namespace Drupal\content_moderation\Plugin\Action; use Drupal\content_moderation\ModerationInformationInterface; -use Drupal\content_moderation\StateTransitionValidationInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Action\ActionBase; use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,7 +15,7 @@ * * @Action( * id = "moderation_state_change", - * deriver = "\Drupal\content_moderation\Plugin\Derivative\ModerationStateChangeDeriver" + * deriver = "\Drupal\content_moderation\Plugin\Derivative\ModerationStateChangeDeriver" * ) */ class ModerationStateChange extends ActionBase implements ContainerFactoryPluginInterface { @@ -30,20 +28,6 @@ class ModerationStateChange extends ActionBase implements ContainerFactoryPlugin protected $moderationInfo; /** - * The state transitions validator. - * - * @var \Drupal\content_moderation\StateTransitionValidation - */ - protected $validation; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** * Moderation state change constructor. * * @param array $configuration @@ -54,16 +38,10 @@ class ModerationStateChange extends ActionBase implements ContainerFactoryPlugin * The plugin implementation definition. * @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info * The moderation info service. - * @param \Drupal\content_moderation\StateTransitionValidationInterface $validation - * The state transitions validator. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, ModerationInformationInterface $moderation_info, StateTransitionValidationInterface $validation, EntityTypeManagerInterface $entityTypeManager) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, ModerationInformationInterface $moderation_info) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->moderationInfo = $moderation_info; - $this->validation = $validation; - $this->entityTypeManager = $entityTypeManager; } /** @@ -72,9 +50,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, - $container->get('content_moderation.moderation_information'), - $container->get('content_moderation.state_transition_validation'), - $container->get('entity_type.manager') + $container->get('content_moderation.moderation_information') ); } @@ -82,19 +58,8 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function execute(ContentEntityInterface $entity = NULL) { - $entity = $this->loadLatestRevision($entity); - $entity->moderation_state->value = $this->pluginDefinition['state']; - $violations = $entity->validate(); - - if (($moderation_violations = $violations->getByField('moderation_state')) && count($moderation_violations)) { - /** @var \Symfony\Component\Validator\ConstraintViolation $violation */ - foreach ($moderation_violations as $violation) { - drupal_set_message($violation->getMessage(), 'error'); - } - return; - } $entity->save(); } @@ -115,18 +80,31 @@ protected function loadLatestRevision(ContentEntityInterface $entity) { * {@inheritdoc} */ public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\Core\Entity\ContentEntityInterface $object */ - if ($object && !$this->moderationInfo->isModeratedEntity($object)) { - return $return_as_object ? AccessResult::forbidden("The entity is not moderated.") : FALSE; + if (!$object) { + $result = AccessResult::forbidden('Not a valid entity.'); + return $return_as_object ? $result : $result->isAllowed(); + } + if ($workflow = $this->moderationInfo->getWorkflowForEntity($object)) { + if ($workflow->id() !== $this->pluginDefinition['workflow']) { + $result = AccessResult::forbidden('Not a valid workflow.'); + $result->addCacheableDependency($object); + $result->addCacheableDependency($workflow); + return $return_as_object ? $result : $result->isAllowed(); + } + } + else { + $result = AccessResult::forbidden('The entity is not moderated.'); + $result->addCacheableDependency($object); + return $return_as_object ? $result : $result->isAllowed(); } $object = $this->loadLatestRevision($object); - /** @var \Drupal\workflows\WorkflowInterface $workflow */ - $workflow = $this->entityTypeManager - ->getStorage('workflow') - ->load($this->pluginDefinition['workflow']); - $from = $workflow->getTypePlugin()->getState($object->moderation_state->value); + // Let content moderation do its job. + $access = $object->access('update', $account, TRUE); - $result = AccessResult::allowedIf($from->canTransitionTo($this->pluginDefinition['state'])); + $from = $workflow->getTypePlugin()->getState($object->moderation_state->value); + // Make sure we can make the transition. + $result = AccessResult::allowedIf($from->canTransitionTo($this->pluginDefinition['state'])) + ->andIf($access); return $return_as_object ? $result : $result->isAllowed(); }