Issue #2808163 by amateescu, samuel.mortenson, dawehner: Support dynamic entity types in the EntityRevisionParamConverter
parent
53c6cc8a07
commit
d649b7f45a
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
/**
|
||||
* Provides a trait to replace dynamic entity types in routes.
|
||||
*/
|
||||
trait DynamicEntityTypeParamConverterTrait {
|
||||
|
||||
/**
|
||||
* Determines the entity type ID given a route definition and route defaults.
|
||||
*
|
||||
* @param mixed $definition
|
||||
* The parameter definition provided in the route options.
|
||||
* @param string $name
|
||||
* The name of the parameter.
|
||||
* @param array $defaults
|
||||
* The route defaults array.
|
||||
*
|
||||
* @return string
|
||||
* The entity type ID.
|
||||
*
|
||||
* @throws \Drupal\Core\ParamConverter\ParamNotConvertedException
|
||||
* Thrown when the dynamic entity type is not found in the route defaults.
|
||||
*/
|
||||
protected function getEntityTypeFromDefaults($definition, $name, array $defaults) {
|
||||
$type_part = strstr($definition['type'], ':');
|
||||
if (!$type_part) {
|
||||
throw new ParamNotConvertedException(sprintf('The type definition "%s" is invalid. The expected format is "entity_revision:<entity_type_id>".', $definition['type']));
|
||||
}
|
||||
$entity_type_id = substr($type_part, 1);
|
||||
|
||||
// If the entity type is dynamic, it will be pulled from the route defaults.
|
||||
if (strpos($entity_type_id, '{') === 0) {
|
||||
$entity_type_slug = substr($entity_type_id, 1, -1);
|
||||
if (!isset($defaults[$entity_type_slug])) {
|
||||
throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted because the "%s" parameter is missing.', $name, $entity_type_slug));
|
||||
}
|
||||
$entity_type_id = $defaults[$entity_type_slug];
|
||||
}
|
||||
return $entity_type_id;
|
||||
}
|
||||
|
||||
}
|
|
@ -67,7 +67,9 @@ use Symfony\Component\Routing\Route;
|
|||
* @see entities_revisions_translations
|
||||
*/
|
||||
class EntityConverter implements ParamConverterInterface {
|
||||
|
||||
use DeprecatedServicePropertyTrait;
|
||||
use DynamicEntityTypeParamConverterTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -236,36 +238,6 @@ class EntityConverter implements ParamConverterInterface {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the entity type ID given a route definition and route defaults.
|
||||
*
|
||||
* @param mixed $definition
|
||||
* The parameter definition provided in the route options.
|
||||
* @param string $name
|
||||
* The name of the parameter.
|
||||
* @param array $defaults
|
||||
* The route defaults array.
|
||||
*
|
||||
* @return string
|
||||
* The entity type ID.
|
||||
*
|
||||
* @throws \Drupal\Core\ParamConverter\ParamNotConvertedException
|
||||
* Thrown when the dynamic entity type is not found in the route defaults.
|
||||
*/
|
||||
protected function getEntityTypeFromDefaults($definition, $name, array $defaults) {
|
||||
$entity_type_id = substr($definition['type'], strlen('entity:'));
|
||||
|
||||
// If the entity type is dynamic, it will be pulled from the route defaults.
|
||||
if (strpos($entity_type_id, '{') === 0) {
|
||||
$entity_type_slug = substr($entity_type_id, 1, -1);
|
||||
if (!isset($defaults[$entity_type_slug])) {
|
||||
throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted because the "%s" parameter is missing', $name, $entity_type_slug));
|
||||
}
|
||||
$entity_type_id = $defaults[$entity_type_slug];
|
||||
}
|
||||
return $entity_type_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language manager instance.
|
||||
*
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\TranslatableInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
|
@ -25,6 +27,8 @@ use Symfony\Component\Routing\Route;
|
|||
*/
|
||||
class EntityRevisionParamConverter implements ParamConverterInterface {
|
||||
|
||||
use DynamicEntityTypeParamConverterTrait;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
|
@ -56,9 +60,16 @@ class EntityRevisionParamConverter implements ParamConverterInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
list (, $entity_type_id) = explode(':', $definition['type'], 2);
|
||||
$entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults);
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($value);
|
||||
return $this->entityRepository->getTranslationFromContext($entity);
|
||||
|
||||
// If the entity type is translatable, ensure we return the proper
|
||||
// translation object for the current context.
|
||||
if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) {
|
||||
$entity = $this->entityRepository->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -150,7 +150,7 @@ class EntityConverterTest extends UnitTestCase {
|
|||
* Tests the convert() method with an invalid dynamic entity type.
|
||||
*/
|
||||
public function testConvertWithInvalidDynamicEntityType() {
|
||||
$this->setExpectedException(ParamNotConvertedException::class, 'The "foo" parameter was not converted because the "invalid_id" parameter is missing');
|
||||
$this->setExpectedException(ParamNotConvertedException::class, 'The "foo" parameter was not converted because the "invalid_id" parameter is missing.');
|
||||
$this->entityConverter->convert('id', ['type' => 'entity:{invalid_id}'], 'foo', ['foo' => 'id']);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
namespace Drupal\Tests\Core\ParamConverter;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\ParamConverter\EntityRevisionParamConverter;
|
||||
use Drupal\Core\ParamConverter\ParamNotConvertedException;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
|
@ -19,7 +20,7 @@ class EntityRevisionParamConverterTest extends UnitTestCase {
|
|||
/**
|
||||
* The tested entity revision param converter.
|
||||
*
|
||||
* @var \Drupal\entity\ParamConverter\EntityRevisionParamConverter
|
||||
* @var \Drupal\Core\ParamConverter\EntityRevisionParamConverter
|
||||
*/
|
||||
protected $converter;
|
||||
|
||||
|
@ -62,22 +63,74 @@ class EntityRevisionParamConverterTest extends UnitTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests the convert() method.
|
||||
*
|
||||
* @dataProvider providerTestConvert
|
||||
*
|
||||
* @covers ::convert
|
||||
*/
|
||||
public function testConvert() {
|
||||
$entity = $this->prophesize(EntityInterface::class)->reveal();
|
||||
public function testConvert($value, array $definition, array $defaults, $expected_result) {
|
||||
$storage = $this->prophesize(EntityStorageInterface::class);
|
||||
$storage->loadRevision(1)->willReturn($entity);
|
||||
$storage->loadRevision('valid_id')->willReturn((object) ['revision_id' => 'valid_id']);
|
||||
$storage->loadRevision('invalid_id')->willReturn(NULL);
|
||||
|
||||
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$entity_type_manager->getStorage('test')->willReturn($storage->reveal());
|
||||
$entity_type_manager->getStorage('entity_test')->willReturn($storage->reveal());
|
||||
$entity_repository = $this->prophesize(EntityRepositoryInterface::class);
|
||||
$entity_repository->getTranslationFromContext($entity)->willReturn($entity);
|
||||
$converter = new EntityRevisionParamConverter($entity_type_manager->reveal(), $entity_repository->reveal());
|
||||
|
||||
$route = $this->getTestRoute();
|
||||
$result = $converter->convert(1, $route->getOption('parameters')['test_revision'], 'test_revision', ['test_revision' => 1]);
|
||||
$this->assertSame($entity, $result);
|
||||
$result = $converter->convert($value, $definition, 'test_revision', $defaults);
|
||||
$this->assertEquals($expected_result, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testConvert
|
||||
*/
|
||||
public function providerTestConvert() {
|
||||
$data = [];
|
||||
// Existing entity type.
|
||||
$data[] = ['valid_id', ['type' => 'entity_revision:entity_test'], ['test_revision' => 'valid_id'], (object) ['revision_id' => 'valid_id']];
|
||||
// Invalid ID.
|
||||
$data[] = ['invalid_id', ['type' => 'entity_revision:entity_test'], ['test_revision' => 'invalid_id'], NULL];
|
||||
// Entity type placeholder.
|
||||
$data[] = ['valid_id', ['type' => 'entity_revision:{entity_type}'], ['test_revision' => 'valid_id', 'entity_type' => 'entity_test'], (object) ['revision_id' => 'valid_id']];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the convert() method with an invalid entity type ID.
|
||||
*
|
||||
* @covers ::convert
|
||||
*/
|
||||
public function testConvertWithInvalidEntityType() {
|
||||
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$entity_type_manager->getStorage('invalid_entity_type_id')->willThrow(new InvalidPluginDefinitionException('invalid_entity_type_id'));
|
||||
$entity_repository = $this->prophesize(EntityRepositoryInterface::class);
|
||||
$converter = new EntityRevisionParamConverter($entity_type_manager->reveal(), $entity_repository->reveal());
|
||||
|
||||
$this->setExpectedException(InvalidPluginDefinitionException::class);
|
||||
$converter->convert('valid_id', ['type' => 'entity_revision:invalid_entity_type_id'], 'foo', ['foo' => 'valid_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the convert() method with an invalid dynamic entity type ID.
|
||||
*
|
||||
* @covers ::convert
|
||||
*/
|
||||
public function testConvertWithInvalidType() {
|
||||
$this->setExpectedException(ParamNotConvertedException::class, 'The type definition "entity_revision_{entity_type_id}" is invalid. The expected format is "entity_revision:<entity_type_id>".');
|
||||
$this->converter->convert('valid_id', ['type' => 'entity_revision_{entity_type_id}'], 'foo', ['foo' => 'valid_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the convert() method with an invalid dynamic entity type ID.
|
||||
*
|
||||
* @covers ::convert
|
||||
*/
|
||||
public function testConvertWithInvalidDynamicEntityType() {
|
||||
$this->setExpectedException(ParamNotConvertedException::class, 'The "foo" parameter was not converted because the "invalid_entity_type_id" parameter is missing.');
|
||||
$this->converter->convert('valid_id', ['type' => 'entity_revision:{invalid_entity_type_id}'], 'foo', ['foo' => 'valid_id']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue