diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml index f58db9ef919773091c6d3511c3c836f961a6fa0b..73d84bc4dfce736c26a3e7379babba21a93c4647 100644 --- a/core/config/schema/core.entity.schema.yml +++ b/core/config/schema/core.entity.schema.yml @@ -374,3 +374,8 @@ block.settings.field_block:*:*: mapping: formatter: type: field_formatter + +# Schema for entity actions. +action.configuration.entity:*:*: + type: action_configuration_default + label: 'Entity action' diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityActionDeriverBase.php b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityActionDeriverBase.php new file mode 100644 index 0000000000000000000000000000000000000000..29159c2931115cde69ed587dd81b4ccb0a389a17 --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityActionDeriverBase.php @@ -0,0 +1,89 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static($container->get('entity_type.manager')); + } + + /** + * Indicates whether the deriver can be used for the provided entity type. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * + * @return bool + * TRUE if the entity type can be used, FALSE otherwise. + */ + abstract protected function isApplicable(EntityTypeInterface $entity_type); + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + if (empty($this->derivatives)) { + $definitions = []; + foreach ($this->getApplicableEntityTypes() as $entity_type_id => $entity_type) { + $definition = $base_plugin_definition; + $definition['type'] = $entity_type_id; + $definition['label'] = sprintf('%s %s', $base_plugin_definition['action_label'], $entity_type->getSingularLabel()); + $definitions[$entity_type_id] = $definition; + } + $this->derivatives = $definitions; + } + + return parent::getDerivativeDefinitions($base_plugin_definition); + } + + /** + * Gets a list of applicable entity types. + * + * The list consists of all entity types which match the conditions for the + * given deriver. + * For example, if the action applies to entities that are publishable, + * this method will find all entity types that are publishable. + * + * @return \Drupal\Core\Entity\EntityTypeInterface[] + * The applicable entity types, keyed by entity type ID. + */ + protected function getApplicableEntityTypes() { + $entity_types = $this->entityTypeManager->getDefinitions(); + $entity_types = array_filter($entity_types, function (EntityTypeInterface $entity_type) { + return $this->isApplicable($entity_type); + }); + + return $entity_types; + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityChangedActionDeriver.php b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityChangedActionDeriver.php new file mode 100644 index 0000000000000000000000000000000000000000..2df090b0d918038f64de695e3183bbec79b92f4a --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityChangedActionDeriver.php @@ -0,0 +1,22 @@ +entityClassImplements(EntityChangedInterface::class); + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityPublishedActionDeriver.php b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityPublishedActionDeriver.php new file mode 100644 index 0000000000000000000000000000000000000000..05548eeba81d07cfb76130d2d95505639f2bfac1 --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/Derivative/EntityPublishedActionDeriver.php @@ -0,0 +1,23 @@ +entityClassImplements(EntityPublishedInterface::class); + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/EntityActionBase.php b/core/lib/Drupal/Core/Action/Plugin/Action/EntityActionBase.php new file mode 100644 index 0000000000000000000000000000000000000000..262402490329d0df0a208121a80b124ca2e17ab0 --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/EntityActionBase.php @@ -0,0 +1,62 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $module_name = $this->entityTypeManager + ->getDefinition($this->getPluginDefinition()['type']) + ->getProvider(); + return ['module' => [$module_name]]; + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/PublishAction.php b/core/lib/Drupal/Core/Action/Plugin/Action/PublishAction.php new file mode 100644 index 0000000000000000000000000000000000000000..8d0cf756b47c308abab7c88e2f2c6bd55754a7ec --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/PublishAction.php @@ -0,0 +1,38 @@ +setPublished()->save(); + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + $key = $object->getEntityType()->getKey('published'); + + /** @var \Drupal\Core\Entity\EntityInterface $object */ + $result = $object->access('update', $account, TRUE) + ->andIf($object->$key->access('edit', $account, TRUE)); + + return $return_as_object ? $result : $result->isAllowed(); + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/SaveAction.php b/core/lib/Drupal/Core/Action/Plugin/Action/SaveAction.php new file mode 100644 index 0000000000000000000000000000000000000000..fc63e5c16e3bd16a1597547c7aed0295b82884c4 --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/SaveAction.php @@ -0,0 +1,79 @@ +time = $time; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager'), + $container->get('datetime.time') + ); + } + + /** + * {@inheritdoc} + */ + public function execute($entity = NULL) { + $entity->setChangedTime($this->time->getRequestTime())->save(); + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + // It's not necessary to check the changed field access here, because + // Drupal\Core\Field\ChangedFieldItemList would anyway return 'not allowed'. + // Also changing the changed field value is only a workaround to trigger an + // entity resave. Without a field change, this would not be possible. + /** @var \Drupal\Core\Entity\EntityInterface $object */ + return $object->access('update', $account, $return_as_object); + } + +} diff --git a/core/lib/Drupal/Core/Action/Plugin/Action/UnpublishAction.php b/core/lib/Drupal/Core/Action/Plugin/Action/UnpublishAction.php new file mode 100644 index 0000000000000000000000000000000000000000..bb3f6c2d98e772124c2598cb7f0dfdc2d787a967 --- /dev/null +++ b/core/lib/Drupal/Core/Action/Plugin/Action/UnpublishAction.php @@ -0,0 +1,38 @@ +setUnpublished()->save(); + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + $key = $object->getEntityType()->getKey('published'); + + /** @var \Drupal\Core\Entity\EntityInterface $object */ + $result = $object->access('update', $account, TRUE) + ->andIf($object->$key->access('edit', $account, TRUE)); + + return $return_as_object ? $result : $result->isAllowed(); + } + +} diff --git a/core/modules/action/migrations/d6_action.yml b/core/modules/action/migrations/d6_action.yml index 592ed1805d9ad323398979d91cdd775f990a7b23..38b7fb9a2c59575eded33b9924f950f01f09518a 100644 --- a/core/modules/action/migrations/d6_action.yml +++ b/core/modules/action/migrations/d6_action.yml @@ -23,6 +23,12 @@ process: imagecache_flush_action: 0 imagecache_generate_all_action: 0 imagecache_generate_action: 0 + comment_publish_action: entity:publish_action:comment + comment_unpublish_action: entity:unpublish_action:comment + comment_save_action: entity:save_action:comment + node_publish_action: entity:publish_action:node + node_unpublish_action: entity:unpublish_action:node + node_save_action: entity:save_action:node bypass: true - plugin: skip_on_empty diff --git a/core/modules/action/migrations/d7_action.yml b/core/modules/action/migrations/d7_action.yml index 03b869af183530ecb9aed977dec0dfc8cd22cfa2..ccafcaf0b3480364ca15594ef9a984ee896376ef 100644 --- a/core/modules/action/migrations/d7_action.yml +++ b/core/modules/action/migrations/d7_action.yml @@ -20,6 +20,12 @@ process: system_send_email_action: action_send_email_action system_message_action: action_message_action system_block_ip_action: 0 + comment_publish_action: entity:publish_action:comment + comment_unpublish_action: entity:unpublish_action:comment + comment_save_action: entity:save_action:comment + node_publish_action: entity:publish_action:node + node_unpublish_action: entity:unpublish_action:node + node_save_action: entity:save_action:node bypass: true - plugin: skip_on_empty diff --git a/core/modules/comment/config/install/system.action.comment_publish_action.yml b/core/modules/comment/config/install/system.action.comment_publish_action.yml index 8fbd48d349dce719ea7f3f7f3ef38ca08d3f3679..7a47b2d9e6b14531c008f3038e1504a8550879f8 100644 --- a/core/modules/comment/config/install/system.action.comment_publish_action.yml +++ b/core/modules/comment/config/install/system.action.comment_publish_action.yml @@ -6,5 +6,5 @@ dependencies: id: comment_publish_action label: 'Publish comment' type: comment -plugin: comment_publish_action +plugin: entity:publish_action:comment configuration: { } diff --git a/core/modules/comment/config/install/system.action.comment_save_action.yml b/core/modules/comment/config/install/system.action.comment_save_action.yml index 640d2811cd5e14a1a232721615d362428ee51365..614cf4b6815abd981b12a94ad7db1596bfca0244 100644 --- a/core/modules/comment/config/install/system.action.comment_save_action.yml +++ b/core/modules/comment/config/install/system.action.comment_save_action.yml @@ -6,5 +6,5 @@ dependencies: id: comment_save_action label: 'Save comment' type: comment -plugin: comment_save_action +plugin: entity:save_action:comment configuration: { } diff --git a/core/modules/comment/config/install/system.action.comment_unpublish_action.yml b/core/modules/comment/config/install/system.action.comment_unpublish_action.yml index 99902e8be3976febe64e9385975fcc0d5f9923c8..a1800b4a8ca28e1e7d22eca5cae06d8db826b628 100644 --- a/core/modules/comment/config/install/system.action.comment_unpublish_action.yml +++ b/core/modules/comment/config/install/system.action.comment_unpublish_action.yml @@ -6,5 +6,5 @@ dependencies: id: comment_unpublish_action label: 'Unpublish comment' type: comment -plugin: comment_unpublish_action +plugin: entity:unpublish_action:comment configuration: { } diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml index e4a5b75d4af36e159812897b8c9af7d01f0a4b2e..c29088b1a97376482e47e5e3a1b0623c21a8920a 100644 --- a/core/modules/comment/config/schema/comment.schema.yml +++ b/core/modules/comment/config/schema/comment.schema.yml @@ -15,10 +15,14 @@ field.widget.settings.comment_default: type: mapping label: 'Comment display format settings' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.comment_publish_action: type: action_configuration_default label: 'Publish comment configuration' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.comment_save_action: type: action_configuration_default label: 'Save comment configuration' @@ -34,6 +38,8 @@ action.configuration.comment_unpublish_by_keyword_action: type: string label: 'Keyword' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.comment_unpublish_action: type: action_configuration_default label: 'Unpublish comment configuration' diff --git a/core/modules/comment/src/Plugin/Action/PublishComment.php b/core/modules/comment/src/Plugin/Action/PublishComment.php index 14f5605c74bacd48747cd68f3b74606ca643bb4d..9aa1e4aa6481b8dc444aad6aa28e095c5b923182 100644 --- a/core/modules/comment/src/Plugin/Action/PublishComment.php +++ b/core/modules/comment/src/Plugin/Action/PublishComment.php @@ -2,37 +2,32 @@ namespace Drupal\comment\Plugin\Action; -use Drupal\Core\Action\ActionBase; -use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Action\Plugin\Action\PublishAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Publishes a comment. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\PublishAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "comment_publish_action", * label = @Translation("Publish comment"), * type = "comment" * ) */ -class PublishComment extends ActionBase { - - /** - * {@inheritdoc} - */ - public function execute($comment = NULL) { - $comment->setPublished(TRUE); - $comment->save(); - } +class PublishComment extends PublishAction { /** * {@inheritdoc} */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\comment\CommentInterface $object */ - $result = $object->status->access('edit', $account, TRUE) - ->andIf($object->access('update', $account, TRUE)); - - return $return_as_object ? $result : $result->isAllowed(); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); + @trigger_error(__NAMESPACE__ . '\PublishComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/comment/src/Plugin/Action/SaveComment.php b/core/modules/comment/src/Plugin/Action/SaveComment.php index fdab65d234c9daa3eef0988884f062816e678a6f..c197112e4f0b64a225d69215925c206155f274a4 100644 --- a/core/modules/comment/src/Plugin/Action/SaveComment.php +++ b/core/modules/comment/src/Plugin/Action/SaveComment.php @@ -2,33 +2,33 @@ namespace Drupal\comment\Plugin\Action; -use Drupal\Core\Action\ActionBase; -use Drupal\Core\Session\AccountInterface; +use Drupal\Component\Datetime\TimeInterface; +use Drupal\Core\Action\Plugin\Action\SaveAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Saves a comment. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\SaveAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "comment_save_action", * label = @Translation("Save comment"), * type = "comment" * ) */ -class SaveComment extends ActionBase { - - /** - * {@inheritdoc} - */ - public function execute($comment = NULL) { - $comment->save(); - } +class SaveComment extends SaveAction { /** * {@inheritdoc} */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\comment\CommentInterface $object */ - return $object->access('update', $account, $return_as_object); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $time); + @trigger_error(__NAMESPACE__ . '\SaveComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/comment/src/Plugin/Action/UnpublishComment.php b/core/modules/comment/src/Plugin/Action/UnpublishComment.php index 6accccc83407caa81112c6f49b6ada2055bb7992..7e867c04538dfc6375d5a2fe6bc52ec392721e82 100644 --- a/core/modules/comment/src/Plugin/Action/UnpublishComment.php +++ b/core/modules/comment/src/Plugin/Action/UnpublishComment.php @@ -2,37 +2,32 @@ namespace Drupal\comment\Plugin\Action; -use Drupal\Core\Action\ActionBase; -use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Action\Plugin\Action\UnpublishAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Unpublishes a comment. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\UnpublishAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "comment_unpublish_action", * label = @Translation("Unpublish comment"), * type = "comment" * ) */ -class UnpublishComment extends ActionBase { - - /** - * {@inheritdoc} - */ - public function execute($comment = NULL) { - $comment->setPublished(FALSE); - $comment->save(); - } +class UnpublishComment extends UnpublishAction { /** * {@inheritdoc} */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\comment\CommentInterface $object */ - $result = $object->status->access('edit', $account, TRUE) - ->andIf($object->access('update', $account, TRUE)); - - return $return_as_object ? $result : $result->isAllowed(); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); + @trigger_error(__NAMESPACE__ . '\UnpublishComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/comment/tests/src/Functional/CommentActionsTest.php b/core/modules/comment/tests/src/Functional/CommentActionsTest.php index 79786fcc0525e623dc04f62b3d2110ab2d6d8e34..326749b7c03c956aa2ed90a3f33a1983b30bc38d 100644 --- a/core/modules/comment/tests/src/Functional/CommentActionsTest.php +++ b/core/modules/comment/tests/src/Functional/CommentActionsTest.php @@ -32,7 +32,7 @@ public function testCommentPublishUnpublishActions() { $action = Action::load('comment_unpublish_action'); $action->execute([$comment]); $this->assertTrue($comment->isPublished() === FALSE, 'Comment was unpublished'); - + $this->assertArraySubset(['module' => ['comment']], $action->getDependencies()); // Publish a comment. $action = Action::load('comment_publish_action'); $action->execute([$comment]); diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module index 5a7af0e2c9e2c2640dae1590bb8e58a23dc3fdd0..2ae1e0da3a0a4870986e98401cf37947cf328277 100644 --- a/core/modules/content_moderation/content_moderation.module +++ b/core/modules/content_moderation/content_moderation.module @@ -8,8 +8,8 @@ use Drupal\content_moderation\EntityOperations; use Drupal\content_moderation\EntityTypeInfo; use Drupal\content_moderation\ContentPreprocess; -use Drupal\content_moderation\Plugin\Action\ModerationOptOutPublishNode; -use Drupal\content_moderation\Plugin\Action\ModerationOptOutUnpublishNode; +use Drupal\content_moderation\Plugin\Action\ModerationOptOutPublish; +use Drupal\content_moderation\Plugin\Action\ModerationOptOutUnpublish; use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; @@ -21,8 +21,8 @@ use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\workflows\WorkflowInterface; -use Drupal\node\Plugin\Action\PublishNode; -use Drupal\node\Plugin\Action\UnpublishNode; +use Drupal\Core\Action\Plugin\Action\PublishAction; +use Drupal\Core\Action\Plugin\Action\UnpublishAction; use Drupal\workflows\Entity\Workflow; /** @@ -227,13 +227,15 @@ function content_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, + // moderated entity. 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; + foreach ($definitions as &$definition) { + if ($definition['id'] === 'entity:publish_action' && $definition['class'] == PublishAction::class) { + $definition['class'] = ModerationOptOutPublish::class; + } + if ($definition['id'] === 'entity:unpublish_action' && $definition['class'] == UnpublishAction::class) { + $definition['class'] = ModerationOptOutUnpublish::class; + } } } diff --git a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublish.php b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublish.php new file mode 100644 index 0000000000000000000000000000000000000000..6a707e852fdcb844e50e1b650bc8a06ce15997b7 --- /dev/null +++ b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublish.php @@ -0,0 +1,84 @@ +moderationInfo = $moderation_info; + $this->bundleInfo = $bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager'), + $container->get('content_moderation.moderation_information'), + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function access($entity, AccountInterface $account = NULL, $return_as_object = FALSE) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + if ($entity && $this->moderationInfo->isModeratedEntity($entity)) { + $bundle_info = $this->bundleInfo->getBundleInfo($entity->getEntityTypeId()); + $bundle_label = $bundle_info[$entity->bundle()]['label']; + drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly published.", ['@bundle' => $bundle_label, '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning'); + $result = AccessResult::forbidden(); + return $return_as_object ? $result : $result->isAllowed(); + } + return parent::access($entity, $account, $return_as_object); + } + +} diff --git a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublishNode.php b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublishNode.php index b2d85335aacd64964efcf6022ddd94f408bd78bc..e1c5ce9978a3268788e210bcfffdab58c0753f18 100644 --- a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublishNode.php +++ b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutPublishNode.php @@ -2,65 +2,28 @@ namespace Drupal\content_moderation\Plugin\Action; -use Drupal\Core\Access\AccessResult; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Session\AccountInterface; -use Drupal\node\Plugin\Action\PublishNode; use Drupal\content_moderation\ModerationInformationInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Alternate action plugin that can opt-out of modifying moderated entities. * - * @see \Drupal\node\Plugin\Action\PublishNode + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\content_moderation\Plugin\Action\ModerationOptOutPublish + * instead. + * + * @see \Drupal\content_moderation\Plugin\Action\ModerationOptOutPublish + * @see https://www.drupal.org/node/2919303 */ -class ModerationOptOutPublishNode extends PublishNode implements ContainerFactoryPluginInterface { - - /** - * Moderation information service. - * - * @var \Drupal\content_moderation\ModerationInformationInterface - */ - protected $moderationInfo; - - /** - * ModerationOptOutPublishNode constructor. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info - * The moderation information service. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, ModerationInformationInterface $moderation_info) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->moderationInfo = $moderation_info; - } - - /** - * {@inheritdoc} - */ - 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') - ); - } +class ModerationOptOutPublishNode extends ModerationOptOutPublish { /** * {@inheritdoc} */ - public function access($entity, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\node\NodeInterface $entity */ - if ($entity && $this->moderationInfo->isModeratedEntity($entity)) { - drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly published.", ['@bundle' => node_get_type_label($entity), '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning'); - $result = AccessResult::forbidden(); - return $return_as_object ? $result : $result->isAllowed(); - } - return parent::access($entity, $account, $return_as_object); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $moderation_info, $bundle_info); + @trigger_error(__NAMESPACE__ . '\ModerationOptOutPublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\content_moderation\Plugin\Action\ModerationOptOutPublish instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublish.php b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublish.php new file mode 100644 index 0000000000000000000000000000000000000000..5a46b3e34122db6e849233ead8dde1850ef5896f --- /dev/null +++ b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublish.php @@ -0,0 +1,84 @@ +moderationInfo = $moderation_info; + $this->bundleInfo = $bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager'), + $container->get('content_moderation.moderation_information'), + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function access($entity, AccountInterface $account = NULL, $return_as_object = FALSE) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + if ($entity && $this->moderationInfo->isModeratedEntity($entity)) { + $bundle_info = $this->bundleInfo->getBundleInfo($entity->getEntityTypeId()); + $bundle_label = $bundle_info[$entity->bundle()]['label']; + drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly unpublished.", ['@bundle' => $bundle_label, '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning'); + $result = AccessResult::forbidden(); + return $return_as_object ? $result : $result->isAllowed(); + } + return parent::access($entity, $account, $return_as_object); + } + +} diff --git a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublishNode.php b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublishNode.php index ee36169468d57e8baaeb86fb36a5a33f666811bb..d76d3f18326470c27e261c0fc7bfc1e012aaa834 100644 --- a/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublishNode.php +++ b/core/modules/content_moderation/src/Plugin/Action/ModerationOptOutUnpublishNode.php @@ -2,65 +2,28 @@ namespace Drupal\content_moderation\Plugin\Action; -use Drupal\Core\Access\AccessResult; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Session\AccountInterface; -use Drupal\node\Plugin\Action\UnpublishNode; use Drupal\content_moderation\ModerationInformationInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Alternate action plugin that can opt-out of modifying moderated entities. * - * @see \Drupal\node\Plugin\Action\UnpublishNode + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\content_moderation\Plugin\Action\ModerationOptOutUnpublish + * instead. + * + * @see \Drupal\content_moderation\Plugin\Action\ModerationOptOutPublish + * @see https://www.drupal.org/node/2919303 */ -class ModerationOptOutUnpublishNode extends UnpublishNode implements ContainerFactoryPluginInterface { - - /** - * Moderation information service. - * - * @var \Drupal\content_moderation\ModerationInformationInterface - */ - protected $moderationInfo; - - /** - * ModerationOptOutUnpublishNode constructor. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info - * The moderation information service. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, ModerationInformationInterface $moderation_info) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->moderationInfo = $moderation_info; - } - - /** - * {@inheritdoc} - */ - 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') - ); - } +class ModerationOptOutUnpublishNode extends ModerationOptOutUnpublish { /** * {@inheritdoc} */ - public function access($entity, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\node\NodeInterface $entity */ - if ($entity && $this->moderationInfo->isModeratedEntity($entity)) { - drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly unpublished.", ['@bundle' => node_get_type_label($entity), '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning'); - $result = AccessResult::forbidden(); - return $return_as_object ? $result : $result->isAllowed(); - } - return parent::access($entity, $account, $return_as_object); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $moderation_info, $bundle_info); + @trigger_error(__NAMESPACE__ . '\ModerationOptOutUnpublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\content_moderation\Plugin\Action\ModerationOptOutUnpublish instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/node/config/install/system.action.node_publish_action.yml b/core/modules/node/config/install/system.action.node_publish_action.yml index 20ed19b6390891831cd435268c39c2793135603e..3e139bbe6ace5dad987c0bb8335699f824a28c32 100644 --- a/core/modules/node/config/install/system.action.node_publish_action.yml +++ b/core/modules/node/config/install/system.action.node_publish_action.yml @@ -6,5 +6,5 @@ dependencies: id: node_publish_action label: 'Publish content' type: node -plugin: node_publish_action +plugin: entity:publish_action:node configuration: { } diff --git a/core/modules/node/config/install/system.action.node_save_action.yml b/core/modules/node/config/install/system.action.node_save_action.yml index 887ff43d05a6a31f1e25a0daf3c3eb7c5b6ff58f..1759c35ae26953eccc26825066f93ecf8b1caec6 100644 --- a/core/modules/node/config/install/system.action.node_save_action.yml +++ b/core/modules/node/config/install/system.action.node_save_action.yml @@ -6,5 +6,5 @@ dependencies: id: node_save_action label: 'Save content' type: node -plugin: node_save_action +plugin: entity:save_action:node configuration: { } diff --git a/core/modules/node/config/install/system.action.node_unpublish_action.yml b/core/modules/node/config/install/system.action.node_unpublish_action.yml index 1e778c0dca572a0f8ae48044ccce610c2cdb041a..0d5e35e9c8230c43f724d4d2abaf89c22b94ca42 100644 --- a/core/modules/node/config/install/system.action.node_unpublish_action.yml +++ b/core/modules/node/config/install/system.action.node_unpublish_action.yml @@ -6,5 +6,5 @@ dependencies: id: node_unpublish_action label: 'Unpublish content' type: node -plugin: node_unpublish_action +plugin: entity:unpublish_action:node configuration: { } diff --git a/core/modules/node/config/schema/node.schema.yml b/core/modules/node/config/schema/node.schema.yml index 11a93c531048c0976eb707fc32b0fcb340361569..50b3f3e5ba5e27f25a75cab7e2c4fed1f5992ac8 100644 --- a/core/modules/node/config/schema/node.schema.yml +++ b/core/modules/node/config/schema/node.schema.yml @@ -62,14 +62,20 @@ action.configuration.node_promote_action: type: action_configuration_default label: 'Promote selected content from front page configuration' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.node_publish_action: type: action_configuration_default label: 'Publish selected content configuration' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.node_unpublish_action: type: action_configuration_default label: 'Unpublish selected content configuration' +# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. +# @see https://www.drupal.org/node/2919303 action.configuration.node_save_action: type: action_configuration_default label: 'Save content configuration' diff --git a/core/modules/node/src/Plugin/Action/PublishNode.php b/core/modules/node/src/Plugin/Action/PublishNode.php index 2fa8c019ff3be89b693fb9789b4acf4b92958d5b..adecc7de885da827ff0628cf88b43603da478bc2 100644 --- a/core/modules/node/src/Plugin/Action/PublishNode.php +++ b/core/modules/node/src/Plugin/Action/PublishNode.php @@ -2,25 +2,32 @@ namespace Drupal\node\Plugin\Action; -use Drupal\Core\Field\FieldUpdateActionBase; -use Drupal\node\NodeInterface; +use Drupal\Core\Action\Plugin\Action\PublishAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Publishes a node. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\PublishAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "node_publish_action", * label = @Translation("Publish selected content"), * type = "node" * ) */ -class PublishNode extends FieldUpdateActionBase { +class PublishNode extends PublishAction { /** * {@inheritdoc} */ - protected function getFieldsToUpdate() { - return ['status' => NodeInterface::PUBLISHED]; + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); + @trigger_error(__NAMESPACE__ . '\PublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/node/src/Plugin/Action/SaveNode.php b/core/modules/node/src/Plugin/Action/SaveNode.php index e358fef36c986411b52f66134e03bceb8e7be5aa..d9eea0c921de624a723220a977e0985bdfec104f 100644 --- a/core/modules/node/src/Plugin/Action/SaveNode.php +++ b/core/modules/node/src/Plugin/Action/SaveNode.php @@ -2,36 +2,33 @@ namespace Drupal\node\Plugin\Action; -use Drupal\Core\Action\ActionBase; -use Drupal\Core\Session\AccountInterface; +use Drupal\Component\Datetime\TimeInterface; +use Drupal\Core\Action\Plugin\Action\SaveAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Provides an action that can save any entity. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\SaveAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "node_save_action", * label = @Translation("Save content"), * type = "node" * ) */ -class SaveNode extends ActionBase { - - /** - * {@inheritdoc} - */ - public function execute($entity = NULL) { - // We need to change at least one value, otherwise the changed timestamp - // will not be updated. - $entity->changed = 0; - $entity->save(); - } +class SaveNode extends SaveAction { /** * {@inheritdoc} */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - /** @var \Drupal\node\NodeInterface $object */ - return $object->access('update', $account, $return_as_object); + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $time); + @trigger_error(__NAMESPACE__ . '\SaveNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/node/src/Plugin/Action/UnpublishNode.php b/core/modules/node/src/Plugin/Action/UnpublishNode.php index 7c286e2fc4b930f4c6c3f93fe1f39ac1828815b8..bb188d7009727c08d0f2c9b620cf7e935d3444a1 100644 --- a/core/modules/node/src/Plugin/Action/UnpublishNode.php +++ b/core/modules/node/src/Plugin/Action/UnpublishNode.php @@ -2,25 +2,32 @@ namespace Drupal\node\Plugin\Action; -use Drupal\Core\Field\FieldUpdateActionBase; -use Drupal\node\NodeInterface; +use Drupal\Core\Action\Plugin\Action\UnpublishAction; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Unpublishes a node. * + * @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0. + * Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. + * + * @see \Drupal\Core\Action\Plugin\Action\UnpublishAction + * @see https://www.drupal.org/node/2919303 + * * @Action( * id = "node_unpublish_action", * label = @Translation("Unpublish selected content"), * type = "node" * ) */ -class UnpublishNode extends FieldUpdateActionBase { +class UnpublishNode extends UnpublishAction { /** * {@inheritdoc} */ - protected function getFieldsToUpdate() { - return ['status' => NodeInterface::NOT_PUBLISHED]; + public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); + @trigger_error(__NAMESPACE__ . '\UnpublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED); } } diff --git a/core/modules/system/system.post_update.php b/core/modules/system/system.post_update.php index eb11a19f93fcaf69cc12ea275280bf6ec578aced..da13077de8b7d735946aa9b11d61800262dc9a6e 100644 --- a/core/modules/system/system.post_update.php +++ b/core/modules/system/system.post_update.php @@ -88,3 +88,26 @@ function system_post_update_field_type_plugins() { function system_post_update_field_formatter_entity_schema() { // Empty post-update hook. } + +/** + * Change plugin IDs of actions. + */ +function system_post_update_change_action_plugins() { + $old_new_action_id_map = [ + 'comment_publish_action' => 'entity:publish_action:comment', + 'comment_unpublish_action' => 'entity:unpublish_action:comment', + 'comment_save_action' => 'entity:save_action:comment', + 'node_publish_action' => 'entity:publish_action:node', + 'node_unpublish_action' => 'entity:unpublish_action:node', + 'node_save_action' => 'entity:save_action:node', + ]; + + /** @var \Drupal\system\Entity\Action[] $actions */ + $actions = \Drupal::entityTypeManager()->getStorage('action')->loadMultiple(); + foreach ($actions as $action) { + if (isset($old_new_action_id_map[$action->getPlugin()->getPluginId()])) { + $action->setPlugin($old_new_action_id_map[$action->getPlugin()->getPluginId()]); + $action->save(); + } + } +} diff --git a/core/modules/system/tests/src/Functional/Update/UpdateActionsWithEntityPluginsTest.php b/core/modules/system/tests/src/Functional/Update/UpdateActionsWithEntityPluginsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4094d00313d8e8b7af69fa1371828d3a27bc79fc --- /dev/null +++ b/core/modules/system/tests/src/Functional/Update/UpdateActionsWithEntityPluginsTest.php @@ -0,0 +1,56 @@ +databaseDumpFiles = [__DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz']; + } + + /** + * Tests upgrading comment and node actions to generic entity ones. + * + * @see system_post_update_change_action_plugins() + */ + public function testUpdateActionsWithEntityPlugins() { + $old_new_action_id_map = [ + 'comment_publish_action' => ['comment_publish_action', 'entity:publish_action:comment'], + 'comment_unpublish_action' => ['comment_unpublish_action', 'entity:unpublish_action:comment'], + 'comment_save_action' => ['comment_save_action', 'entity:save_action:comment'], + 'node_publish_action' => ['node_publish_action', 'entity:publish_action:node'], + 'node_unpublish_action' => ['node_unpublish_action', 'entity:unpublish_action:node'], + 'node_save_action' => ['node_save_action', 'entity:save_action:node'], + ]; + + foreach ($old_new_action_id_map as $key => list($before, $after)) { + $config = \Drupal::configFactory()->get('system.action.' . $key); + $this->assertSame($before, $config->get('plugin')); + } + + $this->runUpdates(); + + foreach ($old_new_action_id_map as $key => list($before, $after)) { + /** @var \Drupal\system\Entity\Action $action */ + $action = Action::load($key); + $this->assertSame($after, $action->getPlugin()->getPluginId()); + $config = \Drupal::configFactory()->get('system.action.' . $key); + $this->assertSame($after, $config->get('plugin')); + + // Check that the type the action is based on will be a module dependency. + $this->assertArraySubset(['module' => [$action->getPluginDefinition()['type']]], $action->getDependencies()); + } + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Action/PublishActionTest.php b/core/tests/Drupal/KernelTests/Core/Action/PublishActionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..04bf1c053e39ccb044c59362306b8bac3936456e --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Action/PublishActionTest.php @@ -0,0 +1,80 @@ +installEntitySchema('entity_test_mulrevpub'); + } + + /** + * @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver::getDerivativeDefinitions + */ + public function testGetDerivativeDefinitions() { + $deriver = new EntityPublishedActionDeriver(\Drupal::entityTypeManager()); + $this->assertArraySubset([ + 'entity_test_mulrevpub' => [ + 'type' => 'entity_test_mulrevpub', + 'label' => 'Save test entity - revisions, data table, and published interface', + 'action_label' => 'Save', + ], + ], $deriver->getDerivativeDefinitions([ + 'action_label' => 'Save', + ])); + } + + /** + * @covers \Drupal\Core\Action\Plugin\Action\PublishAction::execute + */ + public function testPublishAction() { + $entity = EntityTestMulRevPub::create(['name' => 'test']); + $entity->setUnpublished()->save(); + + $action = Action::create([ + 'id' => 'entity_publish_action', + 'plugin' => 'entity:publish_action:entity_test_mulrevpub', + ]); + $action->save(); + $this->assertFalse($entity->isPublished()); + $action->execute([$entity]); + $this->assertTrue($entity->isPublished()); + $this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies()); + } + + /** + * @covers \Drupal\Core\Action\Plugin\Action\UnpublishAction::execute + */ + public function testUnpublishAction() { + $entity = EntityTestMulRevPub::create(['name' => 'test']); + $entity->setPublished()->save(); + + $action = Action::create([ + 'id' => 'entity_unpublish_action', + 'plugin' => 'entity:unpublish_action:entity_test_mulrevpub', + ]); + $action->save(); + $this->assertTrue($entity->isPublished()); + $action->execute([$entity]); + $this->assertFalse($entity->isPublished()); + $this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies()); + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Action/SaveActionTest.php b/core/tests/Drupal/KernelTests/Core/Action/SaveActionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..118f5428d8cbb96333f8336c07975f6de6c5c43f --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Action/SaveActionTest.php @@ -0,0 +1,62 @@ +installEntitySchema('entity_test_mul_changed'); + } + + /** + * @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver::getDerivativeDefinitions + */ + public function testGetDerivativeDefinitions() { + $deriver = new EntityChangedActionDeriver(\Drupal::entityTypeManager()); + $this->assertArraySubset([ + 'entity_test_mul_changed' => [ + 'type' => 'entity_test_mul_changed', + 'label' => 'Save test entity - data table', + 'action_label' => 'Save', + ], + ], $deriver->getDerivativeDefinitions([ + 'action_label' => 'Save', + ])); + } + + /** + * @covers \Drupal\Core\Action\Plugin\Action\SaveAction::execute + */ + public function testSaveAction() { + $entity = EntityTestMulChanged::create(['name' => 'test']); + $entity->save(); + $saved_time = $entity->getChangedTime(); + + $action = Action::create([ + 'id' => 'entity_save_action', + 'plugin' => 'entity:save_action:entity_test_mul_changed', + ]); + $action->save(); + $action->execute([$entity]); + $this->assertNotSame($saved_time, $entity->getChangedTime()); + $this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies()); + } + +} diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index 9ec5430697dc59051c5a85ca717343461aa2daa9..2eecec9756f53f972f83a07546ee7fafe5c063ce 100644 --- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -135,6 +135,12 @@ public static function getSkippedDeprecations() { 'drupal_get_message() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Messenger\MessengerInterface::all() or \Drupal\Core\Messenger\MessengerInterface::messagesByType() instead. See https://www.drupal.org/node/2774931', 'Adding or retrieving messages prior to the container being initialized was deprecated in Drupal 8.5.0 and this functionality will be removed before Drupal 9.0.0. Please report this usage at https://www.drupal.org/node/2928994.', 'The "serializer.normalizer.file_entity.hal" normalizer service is deprecated: it is obsolete, it only remains available for backwards compatibility.', + 'Drupal\comment\Plugin\Action\PublishComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. See https://www.drupal.org/node/2919303.', + 'Drupal\comment\Plugin\Action\SaveComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. See https://www.drupal.org/node/2919303.', + 'Drupal\comment\Plugin\Action\UnpublishComment is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. See https://www.drupal.org/node/2919303.', + 'Drupal\node\Plugin\Action\PublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. See https://www.drupal.org/node/2919303.', + 'Drupal\node\Plugin\Action\SaveNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. See https://www.drupal.org/node/2919303.', + 'Drupal\node\Plugin\Action\UnpublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. See https://www.drupal.org/node/2919303.', ]; }