d2e5eae318af654615c5782cbe3711af7fa31f4e
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Entity / EntityResolverManagerTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\Core\Entity\EntityResolverManagerTest.
6  */
7
8 namespace Drupal\Tests\Core\Entity;
9
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;
18
19 /**
20  * @coversDefaultClass \Drupal\Core\Entity\EntityResolverManager
21  * @group Entity
22  */
23 class EntityResolverManagerTest extends UnitTestCase {
24
25   /**
26    * The tested entity resolver manager.
27    *
28    * @var \Drupal\Core\Entity\EntityResolverManager
29    */
30   protected $entityResolverManager;
31
32   /**
33    * The mocked entity manager.
34    *
35    * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
36    */
37   protected $entityManager;
38
39   /**
40    * The mocked class resolver.
41    *
42    * @var \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
43    */
44   protected $classResolver;
45
46   /**
47    * The mocked dependency injection container.
48    *
49    * @var \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
50    */
51   protected $container;
52
53   /**
54    * {@inheritdoc}
55    *
56    * @covers ::__construct
57    */
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();
62
63     $this->entityResolverManager = new EntityResolverManager($this->entityManager, $this->classResolver);
64   }
65
66   /**
67    * Tests setRouteOptions() with no parameter.
68    *
69    * We don't have any entity type involved, so we don't need any upcasting.
70    *
71    * @covers ::setRouteOptions
72    * @covers ::getControllerClass
73    *
74    * @dataProvider providerTestSetRouteOptionsWithStandardRoute
75    */
76   public function testSetRouteOptionsWithStandardRoute($controller) {
77     $route = new Route('/example', [
78       '_controller' => $controller,
79     ]);
80
81     $defaults = $route->getDefaults();
82     $this->entityResolverManager->setRouteOptions($route);
83     $this->assertEquals($defaults, $route->getDefaults());
84     $this->assertEmpty($route->getOption('parameters'));
85   }
86
87   /**
88    * Data provider for testSetRouteOptionsWithStandardRoute.
89    */
90   public function providerTestSetRouteOptionsWithStandardRoute() {
91     return [
92       ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethod'],
93       ['Drupal\Tests\Core\Entity\test_function_controller'],
94     ];
95   }
96
97   /**
98    * Tests setRouteOptions() with a controller with a non entity argument.
99    *
100    * @covers ::setRouteOptions
101    * @covers ::getControllerClass
102    *
103    * @dataProvider providerTestSetRouteOptionsWithStandardRouteWithArgument
104    */
105   public function testSetRouteOptionsWithStandardRouteWithArgument($controller) {
106     $route = new Route('/example/{argument}', [
107       '_controller' => $controller,
108       'argument' => 'test',
109     ]);
110
111     $defaults = $route->getDefaults();
112     $this->entityResolverManager->setRouteOptions($route);
113     $this->assertEquals($defaults, $route->getDefaults());
114     $this->assertEmpty($route->getOption('parameters'));
115   }
116
117   /**
118    * Data provider for testSetRouteOptionsWithStandardRouteWithArgument.
119    */
120   public function providerTestSetRouteOptionsWithStandardRouteWithArgument() {
121     return [
122       ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethodWithArgument'],
123       ['Drupal\Tests\Core\Entity\test_function_controller_with_argument'],
124     ];
125   }
126
127   /**
128    * Tests setRouteOptions() with a _content default.
129    *
130    * @covers ::setRouteOptions
131    * @covers ::getControllerClass
132    *
133    * @dataProvider providerTestSetRouteOptionsWithContentController
134    */
135   public function testSetRouteOptionsWithContentController($controller) {
136     $route = new Route('/example/{argument}', [
137       '_controller' => $controller,
138       'argument' => 'test',
139     ]);
140
141     $defaults = $route->getDefaults();
142     $this->entityResolverManager->setRouteOptions($route);
143     $this->assertEquals($defaults, $route->getDefaults());
144     $this->assertEmpty($route->getOption('parameters'));
145   }
146
147   /**
148    * Data provider for testSetRouteOptionsWithContentController.
149    */
150   public function providerTestSetRouteOptionsWithContentController() {
151     return [
152       ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerMethodWithArgument'],
153       ['Drupal\Tests\Core\Entity\test_function_controller_with_argument'],
154     ];
155   }
156
157   /**
158    * Tests setRouteOptions() with an entity type parameter.
159    *
160    * @covers ::setRouteOptions
161    * @covers ::getControllerClass
162    * @covers ::getEntityTypes
163    * @covers ::setParametersFromReflection
164    *
165    * @dataProvider providerTestSetRouteOptionsWithEntityTypeNoUpcasting
166    */
167   public function testSetRouteOptionsWithEntityTypeNoUpcasting($controller) {
168     $this->setupEntityTypes();
169
170     $route = new Route('/example/{entity_test}', [
171       '_controller' => $controller,
172     ]);
173
174     $defaults = $route->getDefaults();
175     $this->entityResolverManager->setRouteOptions($route);
176     $this->assertEquals($defaults, $route->getDefaults());
177     $this->assertEmpty($route->getOption('parameters'));
178   }
179
180   /**
181    * Data provider for testSetRouteOptionsWithEntityTypeNoUpcasting.
182    */
183   public function providerTestSetRouteOptionsWithEntityTypeNoUpcasting() {
184     return [
185       ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerWithEntityNoUpcasting'],
186       ['Drupal\Tests\Core\Entity\test_function_controller_no_upcasting'],
187     ];
188   }
189
190   /**
191    * Tests setRouteOptions() with an entity type parameter, upcasting.
192    *
193    * @covers ::setRouteOptions
194    * @covers ::getControllerClass
195    * @covers ::getEntityTypes
196    * @covers ::setParametersFromReflection
197    *
198    * @dataProvider providerTestSetRouteOptionsWithEntityTypeUpcasting
199    */
200   public function testSetRouteOptionsWithEntityTypeUpcasting($controller) {
201     $this->setupEntityTypes();
202
203     $route = new Route('/example/{entity_test}', [
204       '_controller' => $controller,
205     ]);
206
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);
212   }
213
214   /**
215    * Data provider for testSetRouteOptionsWithEntityTypeUpcasting.
216    */
217   public function providerTestSetRouteOptionsWithEntityTypeUpcasting() {
218     return [
219       ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerWithEntityUpcasting'],
220       ['Drupal\Tests\Core\Entity\test_function_controller_entity_upcasting'],
221     ];
222   }
223
224   /**
225    * Tests setRouteOptions() with an entity type parameter form.
226    *
227    * @covers ::setRouteOptions
228    * @covers ::getControllerClass
229    * @covers ::getEntityTypes
230    * @covers ::setParametersFromReflection
231    */
232   public function testSetRouteOptionsWithEntityFormUpcasting() {
233     $this->setupEntityTypes();
234
235     $route = new Route('/example/{entity_test}', [
236       '_form' => 'Drupal\Tests\Core\Entity\BasicForm',
237     ]);
238
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);
244   }
245
246   /**
247    * Tests setRouteOptions() with entity form upcasting, no create method.
248    *
249    * @covers ::setRouteOptions
250    * @covers ::getControllerClass
251    * @covers ::getEntityTypes
252    * @covers ::setParametersFromReflection
253    */
254   public function testSetRouteOptionsWithEntityUpcastingNoCreate() {
255     $this->setupEntityTypes();
256
257     $route = new Route('/example/{entity_test}', [
258       '_form' => 'Drupal\Tests\Core\Entity\BasicFormNoContainerInjectionInterface',
259     ]);
260
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);
266   }
267
268   /**
269    * Tests setRouteOptions() with an form parameter without interface.
270    *
271    * @covers ::setRouteOptions
272    * @covers ::getControllerClass
273    * @covers ::getEntityTypes
274    * @covers ::setParametersFromReflection
275    */
276   public function testSetRouteOptionsWithEntityFormNoUpcasting() {
277     $this->setupEntityTypes();
278
279     $route = new Route('/example/{entity_test}', [
280       '_form' => 'Drupal\Tests\Core\Entity\BasicFormNoUpcasting',
281     ]);
282
283     $defaults = $route->getDefaults();
284     $this->entityResolverManager->setRouteOptions($route);
285     $this->assertEquals($defaults, $route->getDefaults());
286     $this->assertEmpty($route->getOption('parameters'));
287   }
288
289   /**
290    * Tests setRouteOptions() with an _entity_view route.
291    *
292    * @covers ::setRouteOptions
293    * @covers ::getControllerClass
294    * @covers ::getEntityTypes
295    * @covers ::setParametersFromReflection
296    * @covers ::setParametersFromEntityInformation
297    */
298   public function testSetRouteOptionsWithEntityViewRouteAndManualParameters() {
299     $this->setupEntityTypes();
300     $route = new Route('/example/{foo}',
301       [
302         '_entity_view' => 'entity_test.view',
303       ],
304       [],
305       [
306         'parameters' => [
307           'foo' => [
308             'type' => 'entity:entity_test',
309           ],
310         ],
311       ]
312     );
313
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);
319   }
320
321   /**
322    * Tests setRouteOptions() with an _entity_view route.
323    *
324    * @covers ::setRouteOptions
325    * @covers ::getControllerClass
326    * @covers ::getEntityTypes
327    * @covers ::setParametersFromReflection
328    * @covers ::setParametersFromEntityInformation
329    */
330   public function testSetRouteOptionsWithEntityViewRoute() {
331     $this->setupEntityTypes();
332     $route = new Route('/example/{entity_test}', [
333       '_entity_view' => 'entity_test.view',
334     ]);
335
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);
341   }
342
343   /**
344    * Tests setRouteOptions() with an _entity_list route.
345    *
346    * @covers ::setRouteOptions
347    * @covers ::getControllerClass
348    * @covers ::getEntityTypes
349    * @covers ::setParametersFromReflection
350    * @covers ::setParametersFromEntityInformation
351    */
352   public function testSetRouteOptionsWithEntityListRoute() {
353     $this->setupEntityTypes();
354     $route = new Route('/example/{entity_test}', [
355       '_entity_list' => 'entity_test',
356     ]);
357
358     $defaults = $route->getDefaults();
359     $this->entityResolverManager->setRouteOptions($route);
360     $this->assertEquals($defaults, $route->getDefaults());
361     $parameters = $route->getOption('parameters');
362     $this->assertNull($parameters);
363   }
364
365   /**
366    * Tests setRouteOptions() with an _entity_form route.
367    *
368    * @covers ::setRouteOptions
369    * @covers ::getControllerClass
370    * @covers ::getEntityTypes
371    * @covers ::setParametersFromReflection
372    * @covers ::setParametersFromEntityInformation
373    */
374   public function testSetRouteOptionsWithEntityFormRoute() {
375     $this->setupEntityTypes();
376     $route = new Route('/example/{entity_test}', [
377       '_entity_form' => 'entity_test.edit',
378     ]);
379
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);
385   }
386
387   /**
388    * Tests an _entity_form route where a non-entity parameter is first.
389    *
390    * The {argument} preceding {entity_test} in route path, is upcasting with a
391    * custom param converter.
392    *
393    * @covers ::setRouteOptions
394    * @covers ::getControllerClass
395    * @covers ::getEntityTypes
396    * @covers ::setParametersFromReflection
397    * @covers ::setParametersFromEntityInformation
398    */
399   public function testSetRouteOptionsWithEntityFormRouteAndArgument() {
400     $this->setupEntityTypes();
401     $route = new Route('/example/{argument}/{entity_test}', [
402       '_entity_form' => 'entity_test.edit',
403     ]);
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']]);
407
408     $defaults = $route->getDefaults();
409     $this->entityResolverManager->setRouteOptions($route);
410     $this->assertEquals($defaults, $route->getDefaults());
411     $parameters = $route->getOption('parameters');
412     $expect = [
413       'argument' => ['type' => 'argument_type'],
414       'entity_test' => ['type' => 'entity:entity_test'],
415     ];
416     $this->assertEquals($expect, $parameters);
417   }
418
419   /**
420    * Tests setRouteOptions() with an _entity_form route for an add form.
421    *
422    * @covers ::setRouteOptions
423    * @covers ::getControllerClass
424    * @covers ::getEntityTypes
425    * @covers ::setParametersFromReflection
426    * @covers ::setParametersFromEntityInformation
427    */
428   public function testSetRouteOptionsWithEntityAddFormRoute() {
429     $this->setupEntityTypes();
430     $route = new Route('/example/add', [
431       '_entity_form' => 'entity_test.add',
432     ]);
433
434     $defaults = $route->getDefaults();
435     $this->entityResolverManager->setRouteOptions($route);
436     $this->assertEquals($defaults, $route->getDefaults());
437     $this->assertFalse($route->hasOption('parameters'));
438   }
439
440   /**
441    * Creates the entity manager mock returning entity type objects.
442    */
443   protected function setupEntityTypes() {
444     $definition = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
445     $definition->expects($this->any())
446       ->method('getClass')
447       ->will($this->returnValue('Drupal\Tests\Core\Entity\SimpleTestEntity'));
448     $this->entityManager->expects($this->any())
449       ->method('getDefinitions')
450       ->will($this->returnValue([
451         'entity_test' => $definition,
452       ]));
453     $this->entityManager->expects($this->any())
454       ->method('getDefinition')
455       ->will($this->returnCallback(function ($entity_type) use ($definition) {
456         if ($entity_type == 'entity_test') {
457           return $definition;
458         }
459         else {
460           return NULL;
461         }
462       }));
463   }
464
465 }
466
467 /**
468  * A class containing all kind of different controller methods.
469  */
470 class BasicControllerClass {
471
472   public function exampleControllerMethod() {
473   }
474
475   public function exampleControllerMethodWithArgument($argument) {
476   }
477
478   public function exampleControllerWithEntityNoUpcasting($entity_test) {
479   }
480
481   public function exampleControllerWithEntityUpcasting(EntityInterface $entity_test) {
482   }
483
484 }
485
486 /**
487  * A concrete entity.
488  */
489 class SimpleTestEntity extends Entity {
490
491 }
492
493 /**
494  * A basic form with a passed entity with an interface.
495  */
496 class BasicForm extends FormBase {
497
498   /**
499    * {@inheritdoc}
500    */
501   public function getFormId() {
502   }
503
504   /**
505    * {@inheritdoc}
506    */
507   public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity_test = NULL) {
508   }
509
510   /**
511    * {@inheritdoc}
512    */
513   public function submitForm(array &$form, FormStateInterface $form_state) {
514   }
515
516 }
517
518 /**
519  * A basic form with a passed entity without an interface.
520  */
521 class BasicFormNoUpcasting extends FormBase {
522
523   /**
524    * {@inheritdoc}
525    */
526   public function getFormId() {
527   }
528
529   /**
530    * {@inheritdoc}
531    */
532   public function buildForm(array $form, FormStateInterface $form_state, $entity_test = NULL) {
533   }
534
535   /**
536    * {@inheritdoc}
537    */
538   public function submitForm(array &$form, FormStateInterface $form_state) {
539   }
540
541 }
542
543 class BasicFormNoContainerInjectionInterface implements FormInterface {
544
545   /**
546    * {@inheritdoc}
547    */
548   public function getFormId() {
549   }
550
551   /**
552    * {@inheritdoc}
553    */
554   public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity_test = NULL) {
555   }
556
557   /**
558    * {@inheritdoc}
559    */
560   public function validateForm(array &$form, FormStateInterface $form_state) {
561   }
562
563   /**
564    * {@inheritdoc}
565    */
566   public function submitForm(array &$form, FormStateInterface $form_state) {
567   }
568
569 }
570
571 function test_function_controller() {
572 }
573
574 function test_function_controller_with_argument($argument) {
575 }
576
577 function test_function_controller_no_upcasting($entity_test) {
578 }
579
580 function test_function_controller_entity_upcasting(EntityInterface $entity_test) {
581 }