5 * Contains \Drupal\Tests\Core\Entity\EntityResolverManagerTest.
8 namespace Drupal\Tests\Core\Entity;
10 use Drupal\Core\Entity\Entity;
11 use Drupal\Core\Entity\EntityInterface;
12 use Drupal\Core\Entity\EntityResolverManager;
13 use Drupal\Core\Form\FormBase;
14 use Drupal\Core\Form\FormInterface;
15 use Drupal\Core\Form\FormStateInterface;
16 use Drupal\Tests\UnitTestCase;
17 use Symfony\Component\Routing\Route;
20 * @coversDefaultClass \Drupal\Core\Entity\EntityResolverManager
23 class EntityResolverManagerTest extends UnitTestCase {
26 * The tested entity resolver manager.
28 * @var \Drupal\Core\Entity\EntityResolverManager
30 protected $entityResolverManager;
33 * The mocked entity manager.
35 * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
37 protected $entityManager;
40 * The mocked class resolver.
42 * @var \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
44 protected $classResolver;
47 * The mocked dependency injection container.
49 * @var \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
56 * @covers ::__construct
58 protected function setUp() {
59 $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
60 $this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
61 $this->classResolver = $this->getClassResolverStub();
63 $this->entityResolverManager = new EntityResolverManager($this->entityManager, $this->classResolver);
67 * Tests setRouteOptions() with no parameter.
69 * We don't have any entity type involved, so we don't need any upcasting.
71 * @covers ::setRouteOptions
72 * @covers ::getControllerClass
74 * @dataProvider providerTestSetRouteOptionsWithStandardRoute
76 public function testSetRouteOptionsWithStandardRoute($controller) {
77 $route = new Route('/example', [
78 '_controller' => $controller,
81 $defaults = $route->getDefaults();
82 $this->entityResolverManager->setRouteOptions($route);
83 $this->assertEquals($defaults, $route->getDefaults());
84 $this->assertEmpty($route->getOption('parameters'));
88 * Data provider for testSetRouteOptionsWithStandardRoute.
90 public function providerTestSetRouteOptionsWithStandardRoute() {
92 ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethod'],
93 ['Drupal\Tests\Core\Entity\test_function_controller'],
98 * Tests setRouteOptions() with a controller with a non entity argument.
100 * @covers ::setRouteOptions
101 * @covers ::getControllerClass
103 * @dataProvider providerTestSetRouteOptionsWithStandardRouteWithArgument
105 public function testSetRouteOptionsWithStandardRouteWithArgument($controller) {
106 $route = new Route('/example/{argument}', [
107 '_controller' => $controller,
108 'argument' => 'test',
111 $defaults = $route->getDefaults();
112 $this->entityResolverManager->setRouteOptions($route);
113 $this->assertEquals($defaults, $route->getDefaults());
114 $this->assertEmpty($route->getOption('parameters'));
118 * Data provider for testSetRouteOptionsWithStandardRouteWithArgument.
120 public function providerTestSetRouteOptionsWithStandardRouteWithArgument() {
122 ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethodWithArgument'],
123 ['Drupal\Tests\Core\Entity\test_function_controller_with_argument'],
128 * Tests setRouteOptions() with a _content default.
130 * @covers ::setRouteOptions
131 * @covers ::getControllerClass
133 * @dataProvider providerTestSetRouteOptionsWithContentController
135 public function testSetRouteOptionsWithContentController($controller) {
136 $route = new Route('/example/{argument}', [
137 '_controller' => $controller,
138 'argument' => 'test',
141 $defaults = $route->getDefaults();
142 $this->entityResolverManager->setRouteOptions($route);
143 $this->assertEquals($defaults, $route->getDefaults());
144 $this->assertEmpty($route->getOption('parameters'));
148 * Data provider for testSetRouteOptionsWithContentController.
150 public function providerTestSetRouteOptionsWithContentController() {
152 ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethodWithArgument'],
153 ['Drupal\Tests\Core\Entity\test_function_controller_with_argument'],
158 * Tests setRouteOptions() with an entity type parameter.
160 * @covers ::setRouteOptions
161 * @covers ::getControllerClass
162 * @covers ::getEntityTypes
163 * @covers ::setParametersFromReflection
165 * @dataProvider providerTestSetRouteOptionsWithEntityTypeNoUpcasting
167 public function testSetRouteOptionsWithEntityTypeNoUpcasting($controller) {
168 $this->setupEntityTypes();
170 $route = new Route('/example/{entity_test}', [
171 '_controller' => $controller,
174 $defaults = $route->getDefaults();
175 $this->entityResolverManager->setRouteOptions($route);
176 $this->assertEquals($defaults, $route->getDefaults());
177 $this->assertEmpty($route->getOption('parameters'));
181 * Data provider for testSetRouteOptionsWithEntityTypeNoUpcasting.
183 public function providerTestSetRouteOptionsWithEntityTypeNoUpcasting() {
185 ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerWithEntityNoUpcasting'],
186 ['Drupal\Tests\Core\Entity\test_function_controller_no_upcasting'],
191 * Tests setRouteOptions() with an entity type parameter, upcasting.
193 * @covers ::setRouteOptions
194 * @covers ::getControllerClass
195 * @covers ::getEntityTypes
196 * @covers ::setParametersFromReflection
198 * @dataProvider providerTestSetRouteOptionsWithEntityTypeUpcasting
200 public function testSetRouteOptionsWithEntityTypeUpcasting($controller) {
201 $this->setupEntityTypes();
203 $route = new Route('/example/{entity_test}', [
204 '_controller' => $controller,
207 $defaults = $route->getDefaults();
208 $this->entityResolverManager->setRouteOptions($route);
209 $this->assertEquals($defaults, $route->getDefaults());
210 $parameters = $route->getOption('parameters');
211 $this->assertEquals(['entity_test' => ['type' => 'entity:entity_test']], $parameters);
215 * Data provider for testSetRouteOptionsWithEntityTypeUpcasting.
217 public function providerTestSetRouteOptionsWithEntityTypeUpcasting() {
219 ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerWithEntityUpcasting'],
220 ['Drupal\Tests\Core\Entity\test_function_controller_entity_upcasting'],
225 * Tests setRouteOptions() with an entity type parameter form.
227 * @covers ::setRouteOptions
228 * @covers ::getControllerClass
229 * @covers ::getEntityTypes
230 * @covers ::setParametersFromReflection
232 public function testSetRouteOptionsWithEntityFormUpcasting() {
233 $this->setupEntityTypes();
235 $route = new Route('/example/{entity_test}', [
236 '_form' => 'Drupal\Tests\Core\Entity\BasicForm',
239 $defaults = $route->getDefaults();
240 $this->entityResolverManager->setRouteOptions($route);
241 $this->assertEquals($defaults, $route->getDefaults());
242 $parameters = $route->getOption('parameters');
243 $this->assertEquals(['entity_test' => ['type' => 'entity:entity_test']], $parameters);
247 * Tests setRouteOptions() with entity form upcasting, no create method.
249 * @covers ::setRouteOptions
250 * @covers ::getControllerClass
251 * @covers ::getEntityTypes
252 * @covers ::setParametersFromReflection
254 public function testSetRouteOptionsWithEntityUpcastingNoCreate() {
255 $this->setupEntityTypes();
257 $route = new Route('/example/{entity_test}', [
258 '_form' => 'Drupal\Tests\Core\Entity\BasicFormNoContainerInjectionInterface',
261 $defaults = $route->getDefaults();
262 $this->entityResolverManager->setRouteOptions($route);
263 $this->assertEquals($defaults, $route->getDefaults());
264 $parameters = $route->getOption('parameters');
265 $this->assertEquals(['entity_test' => ['type' => 'entity:entity_test']], $parameters);
269 * Tests setRouteOptions() with an form parameter without interface.
271 * @covers ::setRouteOptions
272 * @covers ::getControllerClass
273 * @covers ::getEntityTypes
274 * @covers ::setParametersFromReflection
276 public function testSetRouteOptionsWithEntityFormNoUpcasting() {
277 $this->setupEntityTypes();
279 $route = new Route('/example/{entity_test}', [
280 '_form' => 'Drupal\Tests\Core\Entity\BasicFormNoUpcasting',
283 $defaults = $route->getDefaults();
284 $this->entityResolverManager->setRouteOptions($route);
285 $this->assertEquals($defaults, $route->getDefaults());
286 $this->assertEmpty($route->getOption('parameters'));
290 * Tests setRouteOptions() with an _entity_view route.
292 * @covers ::setRouteOptions
293 * @covers ::getControllerClass
294 * @covers ::getEntityTypes
295 * @covers ::setParametersFromReflection
296 * @covers ::setParametersFromEntityInformation
298 public function testSetRouteOptionsWithEntityViewRouteAndManualParameters() {
299 $this->setupEntityTypes();
300 $route = new Route('/example/{foo}',
302 '_entity_view' => 'entity_test.view',
308 'type' => 'entity:entity_test',
314 $defaults = $route->getDefaults();
315 $this->entityResolverManager->setRouteOptions($route);
316 $this->assertEquals($defaults, $route->getDefaults());
317 $parameters = $route->getOption('parameters');
318 $this->assertEquals(['foo' => ['type' => 'entity:entity_test']], $parameters);
322 * Tests setRouteOptions() with an _entity_view route.
324 * @covers ::setRouteOptions
325 * @covers ::getControllerClass
326 * @covers ::getEntityTypes
327 * @covers ::setParametersFromReflection
328 * @covers ::setParametersFromEntityInformation
330 public function testSetRouteOptionsWithEntityViewRoute() {
331 $this->setupEntityTypes();
332 $route = new Route('/example/{entity_test}', [
333 '_entity_view' => 'entity_test.view',
336 $defaults = $route->getDefaults();
337 $this->entityResolverManager->setRouteOptions($route);
338 $this->assertEquals($defaults, $route->getDefaults());
339 $parameters = $route->getOption('parameters');
340 $this->assertEquals(['entity_test' => ['type' => 'entity:entity_test']], $parameters);
344 * Tests setRouteOptions() with an _entity_list route.
346 * @covers ::setRouteOptions
347 * @covers ::getControllerClass
348 * @covers ::getEntityTypes
349 * @covers ::setParametersFromReflection
350 * @covers ::setParametersFromEntityInformation
352 public function testSetRouteOptionsWithEntityListRoute() {
353 $this->setupEntityTypes();
354 $route = new Route('/example/{entity_test}', [
355 '_entity_list' => 'entity_test',
358 $defaults = $route->getDefaults();
359 $this->entityResolverManager->setRouteOptions($route);
360 $this->assertEquals($defaults, $route->getDefaults());
361 $parameters = $route->getOption('parameters');
362 $this->assertNull($parameters);
366 * Tests setRouteOptions() with an _entity_form route.
368 * @covers ::setRouteOptions
369 * @covers ::getControllerClass
370 * @covers ::getEntityTypes
371 * @covers ::setParametersFromReflection
372 * @covers ::setParametersFromEntityInformation
374 public function testSetRouteOptionsWithEntityFormRoute() {
375 $this->setupEntityTypes();
376 $route = new Route('/example/{entity_test}', [
377 '_entity_form' => 'entity_test.edit',
380 $defaults = $route->getDefaults();
381 $this->entityResolverManager->setRouteOptions($route);
382 $this->assertEquals($defaults, $route->getDefaults());
383 $parameters = $route->getOption('parameters');
384 $this->assertEquals(['entity_test' => ['type' => 'entity:entity_test']], $parameters);
388 * Tests an _entity_form route where a non-entity parameter is first.
390 * The {argument} preceding {entity_test} in route path, is upcasting with a
391 * custom param converter.
393 * @covers ::setRouteOptions
394 * @covers ::getControllerClass
395 * @covers ::getEntityTypes
396 * @covers ::setParametersFromReflection
397 * @covers ::setParametersFromEntityInformation
399 public function testSetRouteOptionsWithEntityFormRouteAndArgument() {
400 $this->setupEntityTypes();
401 $route = new Route('/example/{argument}/{entity_test}', [
402 '_entity_form' => 'entity_test.edit',
404 // Add {argument} parameter configuration. In this case {argument} is
405 // upcasted by a custom param converter 'argument_type'.
406 $route->setOption('parameters', ['argument' => ['type' => 'argument_type']]);
408 $defaults = $route->getDefaults();
409 $this->entityResolverManager->setRouteOptions($route);
410 $this->assertEquals($defaults, $route->getDefaults());
411 $parameters = $route->getOption('parameters');
413 'argument' => ['type' => 'argument_type'],
414 'entity_test' => ['type' => 'entity:entity_test'],
416 $this->assertEquals($expect, $parameters);
420 * Tests setRouteOptions() with an _entity_form route for an add form.
422 * @covers ::setRouteOptions
423 * @covers ::getControllerClass
424 * @covers ::getEntityTypes
425 * @covers ::setParametersFromReflection
426 * @covers ::setParametersFromEntityInformation
428 public function testSetRouteOptionsWithEntityAddFormRoute() {
429 $this->setupEntityTypes();
430 $route = new Route('/example/add', [
431 '_entity_form' => 'entity_test.add',
434 $defaults = $route->getDefaults();
435 $this->entityResolverManager->setRouteOptions($route);
436 $this->assertEquals($defaults, $route->getDefaults());
437 $this->assertFalse($route->hasOption('parameters'));
441 * Creates the entity manager mock returning entity type objects.
443 protected function setupEntityTypes() {
444 $definition = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
445 $definition->expects($this->any())
447 ->will($this->returnValue('Drupal\Tests\Core\Entity\SimpleTestEntity'));
448 $definition->expects($this->any())
449 ->method('isRevisionable')
451 $revisionable_definition = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
452 $revisionable_definition->expects($this->any())
454 ->will($this->returnValue('Drupal\Tests\Core\Entity\SimpleTestEntity'));
455 $revisionable_definition->expects($this->any())
456 ->method('isRevisionable')
458 $this->entityManager->expects($this->any())
459 ->method('getDefinitions')
460 ->will($this->returnValue([
461 'entity_test' => $definition,
462 'entity_test_rev' => $revisionable_definition,
464 $this->entityManager->expects($this->any())
465 ->method('getDefinition')
466 ->will($this->returnCallback(function ($entity_type) use ($definition, $revisionable_definition) {
467 if ($entity_type == 'entity_test') {
470 elseif ($entity_type === 'entity_test_rev') {
471 return $revisionable_definition;
482 * A class containing all kind of different controller methods.
484 class BasicControllerClass {
486 public function exampleControllerMethod() {
489 public function exampleControllerMethodWithArgument($argument) {
492 public function exampleControllerWithEntityNoUpcasting($entity_test) {
495 public function exampleControllerWithEntityUpcasting(EntityInterface $entity_test) {
503 class SimpleTestEntity extends Entity {
508 * A basic form with a passed entity with an interface.
512 class BasicForm extends FormBase {
517 public function getFormId() {
523 public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity_test = NULL) {
529 public function submitForm(array &$form, FormStateInterface $form_state) {
535 * A basic form with a passed entity without an interface.
537 class BasicFormNoUpcasting extends FormBase {
542 public function getFormId() {
548 public function buildForm(array $form, FormStateInterface $form_state, $entity_test = NULL) {
554 public function submitForm(array &$form, FormStateInterface $form_state) {
559 class BasicFormNoContainerInjectionInterface implements FormInterface {
564 public function getFormId() {
570 public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity_test = NULL) {
576 public function validateForm(array &$form, FormStateInterface $form_state) {
582 public function submitForm(array &$form, FormStateInterface $form_state) {
587 function test_function_controller() {
590 function test_function_controller_with_argument($argument) {
593 function test_function_controller_no_upcasting($entity_test) {
596 function test_function_controller_entity_upcasting(EntityInterface $entity_test) {