diff --git a/src/ModerationInformation.php b/src/ModerationInformation.php index 73817bd..9f5726b 100644 --- a/src/ModerationInformation.php +++ b/src/ModerationInformation.php @@ -173,26 +173,29 @@ class ModerationInformation implements ModerationInformationInterface { /** * {@inheritdoc} + * + * @todo Make this more performant. */ public function getDefaultRevisionId($entity_type_id, $entity_id) { - if ($storage = $this->entityTypeManager->getStorage($entity_type_id)) { - $revision_ids = $storage->getQuery() - ->condition($this->entityTypeManager->getDefinition($entity_type_id)->getKey('id'), $entity_id) - ->sort($this->entityTypeManager->getDefinition($entity_type_id)->getKey('revision'), 'DESC') - ->range(0, 1) - ->execute(); - if ($revision_ids) { - $revision_id = array_keys($revision_ids)[0]; - return $revision_id; - } + $storage = $this->entityTypeManager->getStorage($entity_type_id); + $entity = $storage->load($entity_id); + if ($entity) { + return $entity->getRevisionId(); } } /** * {@inheritdoc} + * + * @todo There may be a more perfomant way of doing this that doesn't + * require loading the full entity revision. */ public function isLatestRevision(ContentEntityInterface $entity) { - return $entity->getRevisionId() == $this->getLatestRevisionId($entity->getEntityTypeId(), $entity->id()); + $revision = $this->getLatestRevision($entity->getEntityTypeId(), $entity->id()); + if (!$revision) { + return FALSE; + } + return $revision->getRevisionId() == $entity->getRevisionId(); } /** diff --git a/src/Plugin/Action/ModerationOptOutPublishNode.php b/src/Plugin/Action/ModerationOptOutPublishNode.php new file mode 100644 index 0000000..68e65bf --- /dev/null +++ b/src/Plugin/Action/ModerationOptOutPublishNode.php @@ -0,0 +1,60 @@ +moderationInfo = $mod_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('workbench_moderation.moderation_information') + ); + } + + /** + * {@inheritdoc} + */ + public function execute($entity = NULL) { + if ($entity && $this->moderationInfo->isModeratableEntity($entity)) { + drupal_set_message($this->t('One or more entities were skipped as they are under moderation and may not be directly published or unpublished.')); + return; + } + + parent::execute($entity); + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + $result = parent::access($object, $account, TRUE) + ->andif(AccessResult::forbiddenIf($this->moderationInfo->isModeratableEntity($object))->addCacheableDependency($object)); + + return $return_as_object ? $result : $result->isAllowed(); + } +} diff --git a/src/Plugin/Action/ModerationOptOutUnpublishNode.php b/src/Plugin/Action/ModerationOptOutUnpublishNode.php new file mode 100644 index 0000000..627cb6e --- /dev/null +++ b/src/Plugin/Action/ModerationOptOutUnpublishNode.php @@ -0,0 +1,60 @@ +moderationInfo = $mod_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('workbench_moderation.moderation_information') + ); + } + + /** + * {@inheritdoc} + */ + public function execute($entity = NULL) { + if ($entity && $this->moderationInfo->isModeratableEntity($entity)) { + drupal_set_message($this->t('One or more entities were skipped as they are under moderation and may not be directly published or unpublished.')); + return; + } + + parent::execute($entity); + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + $result = parent::access($object, $account, TRUE) + ->andif(AccessResult::forbiddenIf($this->moderationInfo->isModeratableEntity($object))->addCacheableDependency($object)); + + return $return_as_object ? $result : $result->isAllowed(); + } +} diff --git a/workbench_moderation.module b/workbench_moderation.module index 67d7405..3c11487 100644 --- a/workbench_moderation.module +++ b/workbench_moderation.module @@ -17,6 +17,10 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\node\NodeInterface; +use Drupal\node\Plugin\Action\PublishNode; +use Drupal\node\Plugin\Action\UnpublishNode; +use Drupal\workbench_moderation\Plugin\Action\ModerationOptOutPublishNode; +use Drupal\workbench_moderation\Plugin\Action\ModerationOptOutUnpublishNode; use Drupal\workbench_moderation\Plugin\Menu\EditTab; /** @@ -194,6 +198,23 @@ function workbench_moderation_theme($existing, $type, $theme, $path) { } /** + * Implements hook_action_info_alter(). + */ +function workbench_moderation_action_info_alter(&$definitions) { + + // The publish/unpublish actions are not valid on moderated entities. So swap + // their implementations out for alternates that will become a no-op on a + // moderated node. If another module has already swapped out those classes, + // though, we'll be polite and do nothing. + if (isset($definitions['node_publish_action']['class']) && $definitions['node_publish_action']['class'] == PublishNode::class) { + $definitions['node_publish_action']['class'] = ModerationOptOutPublishNode::class; + } + if (isset($definitions['node_unpublish_action']['class']) && $definitions['node_unpublish_action']['class'] == UnpublishNode::class) { + $definitions['node_unpublish_action']['class'] = ModerationOptOutUnpublishNode::class; + } +} + +/** * Implements hook_views_data_alter(). */ function workbench_moderation_views_data_alter(array &$data) {