Issue #2596095 by tstoeckler, bojanz, dawehner: Provide a route provider for add-form of entities
parent
ffa6d37e49
commit
71bdc7bb54
|
@ -7,7 +7,9 @@
|
|||
|
||||
namespace Drupal\Core\Entity\Controller;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
|
@ -19,6 +21,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
* Provides generic entity title callbacks for use in routing.
|
||||
*
|
||||
* It provides:
|
||||
* - An add title callback for entities without bundles.
|
||||
* - An add title callback for entities with bundles.
|
||||
* - A view title callback.
|
||||
* - An edit title callback.
|
||||
* - A delete title callback.
|
||||
|
@ -30,20 +34,40 @@ class EntityController implements ContainerInjectionInterface {
|
|||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity type bundle info.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* The entity repository.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityRepositoryInterface
|
||||
*/
|
||||
protected $entityRepository;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityController.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
* The entity type bundle info.
|
||||
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
|
||||
* The entity repository.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
|
||||
$this->entityManager = $entity_manager;
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, TranslationInterface $string_translation) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityTypeBundleInfo = $entity_type_bundle_info;
|
||||
$this->entityRepository = $entity_repository;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
|
@ -52,11 +76,56 @@ class EntityController implements ContainerInjectionInterface {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_type.bundle.info'),
|
||||
$container->get('entity.repository'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a generic add title callback for entities without bundles.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID.
|
||||
*
|
||||
* @return string
|
||||
* The title for the entity add page.
|
||||
*/
|
||||
public function addTitle($entity_type_id) {
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
return $this->t('Add @entity-type', ['@entity-type' => $entity_type->getLowercaseLabel()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a generic add title callback for entities with bundles.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The route match.
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID.
|
||||
* @param string $bundle_parameter
|
||||
* The name of the route parameter that holds the bundle.
|
||||
*
|
||||
* @return string
|
||||
* The title for the entity add page, if the bundle was found.
|
||||
*/
|
||||
public function addBundleTitle(RouteMatchInterface $route_match, $entity_type_id, $bundle_parameter) {
|
||||
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
|
||||
// If the entity has bundle entities, the parameter might have been upcasted
|
||||
// so fetch the raw parameter.
|
||||
$bundle = $route_match->getRawParameter($bundle_parameter);
|
||||
if ((count($bundles) > 1) && isset($bundles[$bundle])) {
|
||||
return $this->t('Add @bundle', ['@bundle' => $bundles[$bundle]['label']]);
|
||||
}
|
||||
// If the entity supports bundles generally, but only has a single bundle,
|
||||
// the bundle is probably something like 'Default' so that it preferable to
|
||||
// use the entity type label.
|
||||
else {
|
||||
return $this->addTitle($entity_type_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a generic title callback for a single entity.
|
||||
*
|
||||
|
@ -65,8 +134,8 @@ class EntityController implements ContainerInjectionInterface {
|
|||
* @param \Drupal\Core\Entity\EntityInterface $_entity
|
||||
* (optional) An entity, passed in directly from the request attributes.
|
||||
*
|
||||
* @return string
|
||||
* The title for the entity view page.
|
||||
* @return string|null
|
||||
* The title for the entity view page, if an entity was found.
|
||||
*/
|
||||
public function title(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
|
||||
if ($entity = $this->doGetEntity($route_match, $_entity)) {
|
||||
|
@ -82,8 +151,8 @@ class EntityController implements ContainerInjectionInterface {
|
|||
* @param \Drupal\Core\Entity\EntityInterface $_entity
|
||||
* (optional) An entity, passed in directly from the request attributes.
|
||||
*
|
||||
* @return string
|
||||
* The title for the entity edit page.
|
||||
* @return string|null
|
||||
* The title for the entity edit page, if an entity was found.
|
||||
*/
|
||||
public function editTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
|
||||
if ($entity = $this->doGetEntity($route_match, $_entity)) {
|
||||
|
@ -101,7 +170,7 @@ class EntityController implements ContainerInjectionInterface {
|
|||
* set in \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer.
|
||||
*
|
||||
* @return string
|
||||
* The title for the delete entity page.
|
||||
* The title for the entity delete page.
|
||||
*/
|
||||
public function deleteTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
|
||||
if ($entity = $this->doGetEntity($route_match, $_entity)) {
|
||||
|
@ -135,8 +204,8 @@ class EntityController implements ContainerInjectionInterface {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ($entity) {
|
||||
return $this->entityManager->getTranslationFromContext($entity);
|
||||
if (isset($entity)) {
|
||||
return $this->entityRepository->getTranslationFromContext($entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,16 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
*/
|
||||
class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAddFormRoute(EntityTypeInterface $entity_type) {
|
||||
if ($route = parent::getAddFormRoute($entity_type)) {
|
||||
$route->setOption('_admin_route', TRUE);
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
namespace Drupal\Core\Entity\Routing;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\Entity\Controller\EntityController;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
@ -31,20 +34,30 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* Constructs a new DefaultHtmlRouteProvider.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
||||
* The entity field manager.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager) {
|
||||
$this->entityManager = $entity_manager;
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,7 +65,8 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$container->get('entity.manager')
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_field.manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -64,14 +78,18 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
|
||||
$entity_type_id = $entity_type->id();
|
||||
|
||||
if ($edit_route = $this->getEditFormRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.edit_form", $edit_route);
|
||||
if ($add_route = $this->getAddFormRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.add_form", $add_route);
|
||||
}
|
||||
|
||||
if ($canonical_route = $this->getCanonicalRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.canonical", $canonical_route);
|
||||
}
|
||||
|
||||
if ($edit_route = $this->getEditFormRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.edit_form", $edit_route);
|
||||
}
|
||||
|
||||
if ($delete_route = $this->getDeleteFormRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.delete_form", $delete_route);
|
||||
}
|
||||
|
@ -79,6 +97,78 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the add-form route.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\Route|null
|
||||
* The generated route, if available.
|
||||
*/
|
||||
protected function getAddFormRoute(EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->hasLinkTemplate('add-form')) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
$route = new Route($entity_type->getLinkTemplate('add-form'));
|
||||
// Use the add form handler, if available, otherwise default.
|
||||
$operation = 'default';
|
||||
if ($entity_type->getFormClass('add')) {
|
||||
$operation = 'add';
|
||||
}
|
||||
$route->setDefaults([
|
||||
'_entity_form' => "{$entity_type_id}.{$operation}",
|
||||
'entity_type_id' => $entity_type_id,
|
||||
]);
|
||||
|
||||
// If the entity has bundles, we can provide a bundle-specific title
|
||||
// and access requirements.
|
||||
if ($bundle_key = $entity_type->getKey('bundle')) {
|
||||
$route->setDefault('_title_callback', EntityController::class . '::addBundleTitle');
|
||||
// If the bundles are entities themselves, we can add parameter
|
||||
// information to the route options.
|
||||
if ($bundle_entity_type_id = $entity_type->getBundleEntityType()) {
|
||||
$bundle_entity_type = $this->entityTypeManager->getDefinition($bundle_entity_type_id);
|
||||
|
||||
$route
|
||||
// The title callback uses the value of the bundle parameter to
|
||||
// fetch the respective bundle at runtime.
|
||||
->setDefault('bundle_parameter', $bundle_entity_type_id)
|
||||
->setRequirement('_entity_create_access', "{$entity_type_id}:{$bundle_entity_type_id}");
|
||||
|
||||
// Entity types with serial IDs can specify this in their route
|
||||
// requirements, improving the matching process.
|
||||
if ($this->getEntityTypeIdKeyType($bundle_entity_type) === 'integer') {
|
||||
$route->setRequirement($entity_type_id, '\d+');
|
||||
}
|
||||
|
||||
$bundle_entity_parameter = ['type' => 'entity:' . $bundle_entity_type_id];
|
||||
if ($bundle_entity_type instanceof ConfigEntityTypeInterface) {
|
||||
// The add page might be displayed on an admin path. Even then, we
|
||||
// need to load configuration overrides so that, for example, the
|
||||
// bundle label gets translated correctly.
|
||||
// @see \Drupal\Core\ParamConverter\AdminPathConfigEntityConverter
|
||||
$bundle_entity_parameter['with_config_overrides'] = TRUE;
|
||||
}
|
||||
$route->setOption('parameters', [$bundle_entity_type_id => $bundle_entity_parameter]);
|
||||
}
|
||||
else {
|
||||
// If the bundles are not entities, the bundle key is used as the
|
||||
// route parameter name directly.
|
||||
$route
|
||||
->setDefault('bundle_parameter', $bundle_key)
|
||||
->setRequirement('_entity_create_access', "{$entity_type_id}:{$bundle_key}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$route
|
||||
->setDefault('_title_callback', EntityController::class . '::addTitle')
|
||||
->setRequirement('_entity_create_access', $entity_type_id);
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the canonical route.
|
||||
*
|
||||
|
@ -195,7 +285,7 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
return NULL;
|
||||
}
|
||||
|
||||
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type->id());
|
||||
$field_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type->id());
|
||||
return $field_storage_definitions[$entity_type->getKey('id')]->getType();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Drupal\entity_test\Entity;
|
|||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_mul/add",
|
||||
* "canonical" = "/entity_test_mul/manage/{entity_test_mul}",
|
||||
* "edit-form" = "/entity_test_mul/manage/{entity_test_mul}/edit",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul/{entity_test_mul}",
|
||||
|
|
|
@ -42,6 +42,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
|||
* "langcode" = "langcode"
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_mul_changed/add",
|
||||
* "canonical" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}",
|
||||
* "edit-form" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}/edit",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul_changed/{entity_test_mul_changed}",
|
||||
|
|
|
@ -41,6 +41,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
* "default_langcode" = "custom_default_langcode_key",
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_mul_langcode_key/add",
|
||||
* "canonical" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}",
|
||||
* "edit-form" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}/edit",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mul_langcode_key/{entity_test_mul_langcode_key}",
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace Drupal\entity_test\Entity;
|
|||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_mulrev/add",
|
||||
* "canonical" = "/entity_test_mulrev/manage/{entity_test_mulrev}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mulrev/{entity_test_mulrev}",
|
||||
* "edit-form" = "/entity_test_mulrev/manage/{entity_test_mulrev}/edit",
|
||||
|
|
|
@ -43,6 +43,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
|||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_mulrev_changed/add",
|
||||
* "canonical" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_mulrev_changed/{entity_test_mulrev_changed}",
|
||||
* "edit-form" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}/edit",
|
||||
|
|
|
@ -42,6 +42,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
|||
* "langcode" = "langcode",
|
||||
* },
|
||||
* links = {
|
||||
* "add-form" = "/entity_test_rev/add",
|
||||
* "canonical" = "/entity_test_rev/manage/{entity_test_rev}",
|
||||
* "delete-form" = "/entity_test/delete/entity_test_rev/{entity_test_rev}",
|
||||
* "edit-form" = "/entity_test_rev/manage/{entity_test_rev}/edit",
|
||||
|
|
|
@ -30,7 +30,6 @@ class EntityTestRoutes {
|
|||
array('_entity_form' => "$entity_type_id.default"),
|
||||
array('_permission' => 'administer entity_test content')
|
||||
);
|
||||
|
||||
$routes["entity.$entity_type_id.admin_form"] = new Route(
|
||||
"$entity_type_id/structure/{bundle}",
|
||||
array('_controller' => '\Drupal\entity_test\Controller\EntityTestController::testAdmin'),
|
||||
|
|
|
@ -7,13 +7,16 @@
|
|||
|
||||
namespace Drupal\Tests\Core\Entity\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
|
@ -22,24 +25,203 @@ use Symfony\Component\Routing\Route;
|
|||
*/
|
||||
class DefaultHtmlRouteProviderTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type manager prophecy used in the test.
|
||||
*
|
||||
* @var \Prophecy\Prophecy\ProphecyInterface|\Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager prophecy used in the test.
|
||||
*
|
||||
* @var \Prophecy\Prophecy\ProphecyInterface|\Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The HTML route provider used in the test.
|
||||
*
|
||||
* @var \Drupal\Tests\Core\Entity\Routing\TestDefaultHtmlRouteProvider
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
|
||||
|
||||
$this->routeProvider = new TestDefaultHtmlRouteProvider($this->entityTypeManager->reveal(), $this->entityFieldManager->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getAddFormRoute
|
||||
* @dataProvider providerTestGetAddFormRoute
|
||||
*/
|
||||
public function testGetAddFormRoute(Route $expected = NULL, EntityTypeInterface $entity_type, EntityTypeInterface $bundle_entity_type = NULL, FieldStorageDefinitionInterface $field_storage_definition = NULL) {
|
||||
if ($bundle_entity_type) {
|
||||
$this->entityTypeManager->getDefinition('the_bundle_entity_type_id')->willReturn($bundle_entity_type);
|
||||
|
||||
if ($field_storage_definition) {
|
||||
$this->entityFieldManager->getFieldStorageDefinitions('the_bundle_entity_type_id')
|
||||
->willReturn(['id' => $field_storage_definition]);
|
||||
}
|
||||
}
|
||||
|
||||
$route = $this->routeProvider->getAddFormRoute($entity_type);
|
||||
$this->assertEquals($expected, $route);
|
||||
}
|
||||
|
||||
public function providerTestGetAddFormRoute() {
|
||||
$data = [];
|
||||
|
||||
$entity_type1 = $this->getEntityType();
|
||||
$entity_type1->hasLinkTemplate('add-form')->willReturn(FALSE);
|
||||
$data['no_add_form_link_template'] = [NULL, $entity_type1->reveal()];
|
||||
|
||||
$entity_type2 = $this->getEntityType();
|
||||
$entity_type2->hasLinkTemplate('add-form')->willReturn(TRUE);
|
||||
$entity_type2->id()->willReturn('the_entity_type_id');
|
||||
$entity_type2->getLinkTemplate('add-form')->willReturn('/the/add/form/link/template');
|
||||
$entity_type2->getFormClass('add')->willReturn(NULL);
|
||||
$entity_type2->getKey('bundle')->willReturn(NULL);
|
||||
$route = (new Route('/the/add/form/link/template'))
|
||||
->setDefaults([
|
||||
'_entity_form' => 'the_entity_type_id.default',
|
||||
'entity_type_id' => 'the_entity_type_id',
|
||||
'_title_callback' => 'Drupal\Core\Entity\Controller\EntityController::addTitle',
|
||||
])
|
||||
->setRequirement('_entity_create_access', 'the_entity_type_id')
|
||||
;
|
||||
$data['no_add_form_no_bundle'] = [clone $route, $entity_type2->reveal()];
|
||||
|
||||
$entity_type3 = $this->getEntityType($entity_type2);
|
||||
$entity_type3->getFormClass('add')->willReturn('Drupal\Core\Entity\EntityForm');
|
||||
$route->setDefault('_entity_form', 'the_entity_type_id.add');
|
||||
$data['add_form_no_bundle'] = [clone $route, $entity_type3->reveal()];
|
||||
|
||||
$entity_type4 = $this->getEntityType($entity_type3);
|
||||
$entity_type4->getKey('bundle')->willReturn('the_bundle_key');
|
||||
$entity_type4->getBundleEntityType()->willReturn(NULL);
|
||||
$route
|
||||
->setDefault('_title_callback', 'Drupal\Core\Entity\Controller\EntityController::addBundleTitle')
|
||||
->setDefault('bundle_parameter', 'the_bundle_key')
|
||||
->setRequirement('_entity_create_access', 'the_entity_type_id:the_bundle_key');
|
||||
$data['add_form_bundle_static'] = [clone $route, $entity_type4->reveal()];
|
||||
|
||||
$entity_type5 = $this->getEntityType($entity_type4);
|
||||
$entity_type5->getBundleEntityType()->willReturn('the_bundle_entity_type_id');
|
||||
$bundle_entity_type = $this->getEntityType();
|
||||
$bundle_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
$route
|
||||
->setDefault('bundle_parameter', 'the_bundle_entity_type_id')
|
||||
->setRequirement('_entity_create_access', 'the_entity_type_id:the_bundle_entity_type_id')
|
||||
->setOption('parameters', ['the_bundle_entity_type_id' => [
|
||||
'type' => 'entity:the_bundle_entity_type_id',
|
||||
]]);
|
||||
$data['add_form_bundle_entity_id_key_type_null'] = [clone $route, $entity_type5->reveal(), $bundle_entity_type->reveal()];
|
||||
|
||||
$entity_type6 = $this->getEntityType($entity_type5);
|
||||
$bundle_entity_type = $this->getEntityType();
|
||||
$bundle_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getType()->willReturn('integer');
|
||||
$route->setRequirement('the_entity_type_id', '\d+');
|
||||
$data['add_form_bundle_entity_id_key_type_integer'] = [clone $route, $entity_type6->reveal(), $bundle_entity_type->reveal(), $field_storage_definition->reveal()];
|
||||
|
||||
$entity_type7 = $this->getEntityType($entity_type6);
|
||||
$bundle_entity_type = $this->prophesize(ConfigEntityTypeInterface::class);
|
||||
$bundle_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$route
|
||||
// Unset the 'the_entity_type_id' requirement.
|
||||
->setRequirements(['_entity_create_access' => $route->getRequirement('_entity_create_access')])
|
||||
->setOption('parameters', ['the_bundle_entity_type_id' => [
|
||||
'type' => 'entity:the_bundle_entity_type_id',
|
||||
'with_config_overrides' => TRUE,
|
||||
]]);
|
||||
$data['add_form_bundle_entity_id_key_type_integer'] = [clone $route, $entity_type7->reveal(), $bundle_entity_type->reveal(), $field_storage_definition->reveal()];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getCanonicalRoute
|
||||
* @dataProvider providerTestGetCanonicalRoute
|
||||
*/
|
||||
public function testGetCanonicalRoute(Route $expected = NULL, EntityTypeInterface $entity_type, FieldStorageDefinitionInterface $field_storage_definition = NULL) {
|
||||
if ($field_storage_definition) {
|
||||
$this->entityFieldManager->getFieldStorageDefinitions($entity_type->id())
|
||||
->willReturn([$entity_type->getKey('id') => $field_storage_definition]);
|
||||
}
|
||||
|
||||
$route = $this->routeProvider->getCanonicalRoute($entity_type);
|
||||
$this->assertEquals($expected, $route);
|
||||
}
|
||||
|
||||
public function providerTestGetCanonicalRoute() {
|
||||
$data = [];
|
||||
|
||||
$entity_type1 = $this->getEntityType();
|
||||
$entity_type1->hasLinkTemplate('canonical')->willReturn(FALSE);
|
||||
$data['no_canonical_link_template'] = [NULL, $entity_type1->reveal()];
|
||||
|
||||
$entity_type2 = $this->getEntityType();;
|
||||
$entity_type2->hasLinkTemplate('canonical')->willReturn(TRUE);
|
||||
$entity_type2->hasViewBuilderClass()->willReturn(FALSE);
|
||||
$data['no_view_builder'] = [NULL, $entity_type2->reveal()];
|
||||
|
||||
$entity_type3 = $this->getEntityType($entity_type2);
|
||||
$entity_type3->hasViewBuilderClass()->willReturn(TRUE);
|
||||
$entity_type3->id()->willReturn('the_entity_type_id');
|
||||
$entity_type3->getLinkTemplate('canonical')->willReturn('/the/canonical/link/template');
|
||||
$entity_type3->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
$route = (new Route('/the/canonical/link/template'))
|
||||
->setDefaults([
|
||||
'_entity_view' => 'the_entity_type_id.full',
|
||||
'_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title',
|
||||
])
|
||||
->setRequirements([
|
||||
'_entity_access' => 'the_entity_type_id.view',
|
||||
])
|
||||
->setOptions([
|
||||
'parameters' => [
|
||||
'the_entity_type_id' => [
|
||||
'type' => 'entity:the_entity_type_id',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$data['id_key_type_null'] = [clone $route, $entity_type3->reveal()];
|
||||
|
||||
$entity_type4 = $this->getEntityType($entity_type3);
|
||||
$entity_type4->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$entity_type4->getKey('id')->willReturn('id');
|
||||
$route->setRequirement('the_entity_type_id', '\d+');
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getType()->willReturn('integer');
|
||||
$data['id_key_type_integer'] = [clone $route, $entity_type4->reveal(), $field_storage_definition->reveal()];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getEntityTypeIdKeyType
|
||||
*/
|
||||
public function testGetEntityTypeIdKeyType() {
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$route_provider = new TestDefaultHtmlRouteProvider($entity_manager->reveal());
|
||||
|
||||
$entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$entity_type_id = 'the_entity_type_id';
|
||||
$entity_type->id()->willReturn($entity_type_id);
|
||||
$entity_type->id()->willReturn('the_entity_type_id');
|
||||
$entity_type->getKey('id')->willReturn('id');
|
||||
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getType()->willReturn('integer');
|
||||
$entity_manager->getFieldStorageDefinitions($entity_type_id)->willReturn(['id' => $field_storage_definition]);
|
||||
$this->entityFieldManager->getFieldStorageDefinitions('the_entity_type_id')->willReturn(['id' => $field_storage_definition]);
|
||||
|
||||
$type = $route_provider->getEntityTypeIdKeyType($entity_type->reveal());
|
||||
$type = $this->routeProvider->getEntityTypeIdKeyType($entity_type->reveal());
|
||||
$this->assertSame('integer', $type);
|
||||
}
|
||||
|
||||
|
@ -47,98 +229,28 @@ class DefaultHtmlRouteProviderTest extends UnitTestCase {
|
|||
* @covers ::getEntityTypeIdKeyType
|
||||
*/
|
||||
public function testGetEntityTypeIdKeyTypeNotFieldable() {
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$route_provider = new TestDefaultHtmlRouteProvider($entity_manager->reveal());
|
||||
|
||||
$entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
$entity_manager->getFieldStorageDefinitions(Argument::any())->shouldNotBeCalled();
|
||||
$this->entityFieldManager->getFieldStorageDefinitions(Argument::any())->shouldNotBeCalled();
|
||||
|
||||
$type = $route_provider->getEntityTypeIdKeyType($entity_type->reveal());
|
||||
$type = $this->routeProvider->getEntityTypeIdKeyType($entity_type->reveal());
|
||||
$this->assertNull($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getCanonicalRoute
|
||||
* @dataProvider providerTestGetCanonicalRoute
|
||||
* @param \Prophecy\Prophecy\ObjectProphecy $base_entity_type
|
||||
* @return \Prophecy\Prophecy\ObjectProphecy
|
||||
*/
|
||||
public function testGetCanonicalRoute($entity_type_prophecy, $expected, $field_storage_definition = NULL) {
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$route_provider = new TestDefaultHtmlRouteProvider($entity_manager->reveal());
|
||||
$entity_type = $entity_type_prophecy->reveal();
|
||||
|
||||
if ($field_storage_definition) {
|
||||
$entity_manager->getFieldStorageDefinitions($entity_type->id())
|
||||
->willReturn([$entity_type->getKey('id') => $field_storage_definition]);
|
||||
protected function getEntityType(ObjectProphecy $base_entity_type = NULL) {
|
||||
$entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
if ($base_entity_type) {
|
||||
foreach ($base_entity_type->getMethodProphecies() as $method => $prophecies) {
|
||||
foreach ($prophecies as $prophecy) {
|
||||
$entity_type->addMethodProphecy(clone $prophecy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$route = $route_provider->getCanonicalRoute($entity_type);
|
||||
$this->assertEquals($expected, $route);
|
||||
}
|
||||
|
||||
public function providerTestGetCanonicalRoute() {
|
||||
$data = [];
|
||||
|
||||
$entity_type1 = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type1->hasLinkTemplate('canonical')->willReturn(FALSE);
|
||||
$data['no_canonical_link_template'] = [$entity_type1, NULL];
|
||||
|
||||
$entity_type2 = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type2->hasLinkTemplate('canonical')->willReturn(TRUE);
|
||||
$entity_type2->hasViewBuilderClass()->willReturn(FALSE);
|
||||
$data['no_view_builder'] = [$entity_type2, NULL];
|
||||
|
||||
$entity_type3 = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type3->hasLinkTemplate('canonical')->willReturn(TRUE);
|
||||
$entity_type3->hasViewBuilderClass()->willReturn(TRUE);
|
||||
$entity_type3->id()->willReturn('the_entity_type_id');
|
||||
$entity_type3->getLinkTemplate('canonical')->willReturn('/the/canonical/link/template');
|
||||
$entity_type3->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
$route3 = (new Route('/the/canonical/link/template'))
|
||||
->setDefaults([
|
||||
'_entity_view' => 'the_entity_type_id.full',
|
||||
'_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title',
|
||||
])
|
||||
->setRequirements([
|
||||
'_entity_access' => 'the_entity_type_id.view',
|
||||
])
|
||||
->setOptions([
|
||||
'parameters' => [
|
||||
'the_entity_type_id' => [
|
||||
'type' => 'entity:the_entity_type_id',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$data['id_key_type_null'] = [$entity_type3, $route3];
|
||||
|
||||
$entity_type4 = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type4->hasLinkTemplate('canonical')->willReturn(TRUE);
|
||||
$entity_type4->hasViewBuilderClass()->willReturn(TRUE);
|
||||
$entity_type4->id()->willReturn('the_entity_type_id');
|
||||
$entity_type4->getLinkTemplate('canonical')->willReturn('/the/canonical/link/template');
|
||||
$entity_type4->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$entity_type4->getKey('id')->willReturn('id');
|
||||
$route4 = (new Route('/the/canonical/link/template'))
|
||||
->setDefaults([
|
||||
'_entity_view' => 'the_entity_type_id.full',
|
||||
'_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title',
|
||||
])
|
||||
->setRequirements([
|
||||
'_entity_access' => 'the_entity_type_id.view',
|
||||
'the_entity_type_id' => '\d+',
|
||||
])
|
||||
->setOptions([
|
||||
'parameters' => [
|
||||
'the_entity_type_id' => [
|
||||
'type' => 'entity:the_entity_type_id',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getType()->willReturn('integer');
|
||||
$data['id_key_type_integer'] = [$entity_type4, $route4, $field_storage_definition];
|
||||
|
||||
return $data;
|
||||
return $entity_type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -148,6 +260,9 @@ class TestDefaultHtmlRouteProvider extends DefaultHtmlRouteProvider {
|
|||
public function getEntityTypeIdKeyType(EntityTypeInterface $entity_type) {
|
||||
return parent::getEntityTypeIdKeyType($entity_type);
|
||||
}
|
||||
public function getAddFormRoute(EntityTypeInterface $entity_type) {
|
||||
return parent::getAddFormRoute($entity_type);
|
||||
}
|
||||
public function getCanonicalRoute(EntityTypeInterface $entity_type) {
|
||||
return parent::getCanonicalRoute($entity_type);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue