Commit df209e95 authored by effulgentsia's avatar effulgentsia
Browse files

Issue #2924812 by Sam152, plach, Wim Leers, timmillwood, xjm: Deprecate...

Issue #2924812 by Sam152, plach, Wim Leers, timmillwood, xjm: Deprecate EntityRevisionConverter in content_moderation
parent 479aa4b1
services:
paramconverter.latest_revision:
class: Drupal\content_moderation\ParamConverter\EntityRevisionConverter
arguments: ['@entity.manager', '@content_moderation.moderation_information']
parent: paramconverter.entity
tags:
- { name: paramconverter, priority: 5 }
content_moderation.state_transition_validation:
......
......@@ -88,7 +88,7 @@ protected function getLatestVersionRoute(EntityTypeInterface $entity_type) {
->setOption('parameters', [
$entity_type_id => [
'type' => 'entity:' . $entity_type_id,
'load_pending_revision' => 1,
'load_latest_revision' => TRUE,
],
]);
......
......@@ -2,104 +2,29 @@
namespace Drupal\content_moderation\ParamConverter;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\ParamConverter\EntityConverter;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\content_moderation\ModerationInformationInterface;
use Symfony\Component\Routing\Route;
/**
* Defines a class for making sure the edit-route loads the current draft.
*
* @internal
* This class only exists to provide backwards compatibility with the
* load_pending_revision flag, the predecessor to load_latest_revision. The
* core entity converter now natively loads the latest revision of an entity
* when the load_latest_revision flag is present. This flag is also added
* automatically to all entity forms.
*/
class EntityRevisionConverter extends EntityConverter {
/**
* Moderation information service.
*
* @var \Drupal\content_moderation\ModerationInformationInterface
*/
protected $moderationInformation;
/**
* EntityRevisionConverter constructor.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager, needed by the parent class.
* @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info
* The moderation info utility service.
*/
public function __construct(EntityManagerInterface $entity_manager, ModerationInformationInterface $moderation_info) {
parent::__construct($entity_manager, \Drupal::languageManager());
$this->moderationInformation = $moderation_info;
}
/**
* {@inheritdoc}
*/
public function applies($definition, $name, Route $route) {
return $this->hasPendingRevisionFlag($definition) || $this->isEditFormPage($route);
}
/**
* Determines if the route definition includes a pending revision flag.
*
* This is a custom flag defined by the Content Moderation module to load
* pending revisions rather than the default revision on a given route.
*
* @param array $definition
* The parameter definition provided in the route options.
*
* @return bool
* TRUE if the pending revision flag is set, FALSE otherwise.
*/
protected function hasPendingRevisionFlag(array $definition) {
return (isset($definition['load_pending_revision']) && $definition['load_pending_revision']);
}
/**
* Determines if a given route is the edit-form for an entity.
*
* @param \Symfony\Component\Routing\Route $route
* The route definition.
*
* @return bool
* Returns TRUE if the route is the edit form of an entity, FALSE otherwise.
*/
protected function isEditFormPage(Route $route) {
if ($default = $route->getDefault('_entity_form')) {
// If no operation is provided, use 'default'.
$default .= '.default';
list($entity_type_id, $operation) = explode('.', $default);
if (!$this->entityManager->hasDefinition($entity_type_id)) {
return FALSE;
}
$entity_type = $this->entityManager->getDefinition($entity_type_id);
return in_array($operation, ['default', 'edit']) && $entity_type && $entity_type->isRevisionable();
}
}
/**
* {@inheritdoc}
*/
public function convert($value, $definition, $name, array $defaults) {
$entity = parent::convert($value, $definition, $name, $defaults);
if ($entity && $this->moderationInformation->isModeratedEntity($entity) && !$this->moderationInformation->isLatestRevision($entity)) {
$entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults);
$latest_revision = $this->moderationInformation->getLatestRevision($entity_type_id, $value);
if ($latest_revision instanceof EntityInterface) {
// If the entity type is translatable, ensure we return the proper
// translation object for the current context.
if ($entity instanceof TranslatableInterface) {
$latest_revision = $this->entityManager->getTranslationFromContext($latest_revision, NULL, ['operation' => 'entity_upcast']);
}
$entity = $latest_revision;
}
if (!empty($definition['load_pending_revision'])) {
@trigger_error('The load_pending_revision flag has been deprecated. You should use load_latest_revision instead.', E_USER_DEPRECATED);
$definition['load_latest_revision'] = TRUE;
}
return $entity;
return parent::convert($value, $definition, $name, $defaults);
}
}
......@@ -2,142 +2,63 @@
namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
/**
* @coversDefaultClass \Drupal\content_moderation\ParamConverter\EntityRevisionConverter
* @group content_moderation
* @group legacy
*/
class EntityRevisionConverterTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'user',
'entity_test',
'system',
'content_moderation',
'node',
'workflows',
];
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The router without access checks.
*
* @var \Symfony\Component\Routing\RouterInterface
*/
protected $router;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('entity_test');
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('node');
$this->installEntitySchema('user');
$this->installEntitySchema('content_moderation_state');
$this->installSchema('system', 'router');
$this->installSchema('system', 'sequences');
$this->installSchema('node', 'node_access');
$this->installConfig(['content_moderation']);
\Drupal::service('router.builder')->rebuild();
$this->entityTypeManager = $this->container->get('entity_type.manager');
$this->router = $this->container->get('router.no_access_checks');
}
/**
* @covers ::convert
* @expectedDeprecationMessage The load_pending_revision flag has been deprecated. You should use load_latest_revision instead.
*/
public function testConvertNonRevisionableEntityType() {
$entity_test = EntityTest::create([
'name' => 'test',
]);
$entity_test->save();
$result = $this->router->match('/entity_test/' . $entity_test->id());
$this->assertInstanceOf(EntityTest::class, $result['entity_test']);
$this->assertEquals($entity_test->getRevisionId(), $result['entity_test']->getRevisionId());
}
/**
* @covers ::applies
*/
public function testConvertNoEditFormHandler() {
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
$entity_test_rev = EntityTestRev::create([
'name' => 'Default Revision',
'moderation_state' => 'published',
]);
$entity_test_rev->save();
$entity_test_rev->name = 'Pending revision';
$entity_test_rev->moderation_state = 'draft';
$entity_test_rev->save();
// Ensure the entity type does not provide an explicit 'edit' form class.
$definition = $this->entityTypeManager->getDefinition($entity_test_rev->getEntityTypeId());
$this->assertNull($definition->getFormClass('edit'));
// Ensure the revision converter is invoked for the edit route.
$result = $this->router->match("/entity_test_rev/manage/{$entity_test_rev->id()}/edit");
$this->assertEquals($entity_test_rev->getRevisionId(), $result['entity_test_rev']->getRevisionId());
}
/**
* @covers ::convert
*/
public function testConvertWithRevisionableEntityType() {
$node_type = NodeType::create([
public function testDeprecatedLoadPendingRevisionFlag() {
NodeType::create([
'type' => 'article',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'article');
$workflow->save();
])->save();
$revision_ids = [];
$node = Node::create([
'title' => 'test',
'type' => 'article',
]);
$node->moderation_state->value = 'published';
$node->save();
$revision_ids[] = $node->getRevisionId();
$node->setNewRevision(TRUE);
$node->save();
$revision_ids[] = $node->getRevisionId();
$node->isDefaultRevision(FALSE);
$node->setNewRevision(TRUE);
$node->moderation_state->value = 'draft';
$node->save();
$revision_ids[] = $node->getRevisionId();
$result = $this->router->match('/node/' . $node->id() . '/edit');
$this->assertInstanceOf(Node::class, $result['node']);
$this->assertEquals($revision_ids[2], $result['node']->getRevisionId());
$this->assertFalse($result['node']->isDefaultRevision());
$converted = $this->container->get('paramconverter.latest_revision')->convert($node->id(), [
'load_pending_revision' => TRUE,
'type' => 'entity:node',
], 'node', []);
$this->assertEquals($converted->getLoadedRevisionId(), $node->getLoadedRevisionId());
}
}
......@@ -2,6 +2,7 @@
namespace Drupal\KernelTests\Core\ParamConverter;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestMulRev;
use Drupal\KernelTests\KernelTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
......@@ -41,6 +42,7 @@ protected function setUp() {
$this->installEntitySchema('user');
$this->installEntitySchema('entity_test_mulrev');
$this->installEntitySchema('entity_test');
$this->installConfig(['system', 'language']);
$this->converter = $this->container->get('paramconverter.entity');
......@@ -168,4 +170,19 @@ public function testOptimizedConvert() {
$this->assertEquals($entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
}
/**
* Test the latest revision flag and non-revisionable entities.
*/
public function testConvertNonRevisionableEntityType() {
$entity = EntityTest::create();
$entity->save();
$converted = $this->converter->convert(1, [
'load_latest_revision' => TRUE,
'type' => 'entity:entity_test',
], 'foo', []);
$this->assertEquals($entity->id(), $converted->id());
}
}
......@@ -520,6 +520,22 @@ public function setLatestRevisionFlagTestCases() {
],
],
],
'Entity form with no operation' => [
[
'_entity_form' => 'entity_test_rev'
],
[
'entity_test_rev' => [
'type' => 'entity:entity_test_rev',
],
],
[
'entity_test_rev' => [
'type' => 'entity:entity_test_rev',
'load_latest_revision' => TRUE,
],
],
],
'Multiple entity parameters on an entity form' => [
[
'_entity_form' => 'entity_test_rev.edit'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment