ddc0fbd4154e653145bac1a693edc2eb7d3b2574
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Menu / ContextualLinkManagerTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Menu;
4
5 use Drupal\Component\Plugin\Exception\PluginException;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\Language\Language;
8 use Drupal\Core\Menu\ContextualLinkDefault;
9 use Drupal\Tests\UnitTestCase;
10 use Symfony\Component\HttpFoundation\RequestStack;
11
12 /**
13  * @coversDefaultClass \Drupal\Core\Menu\ContextualLinkManager
14  * @group Menu
15  */
16 class ContextualLinkManagerTest extends UnitTestCase {
17
18   /**
19    * The tested contextual link manager.
20    *
21    * @var \Drupal\Core\Menu\ContextualLinkManager
22    */
23   protected $contextualLinkManager;
24
25   /**
26    * The mocked controller resolver.
27    *
28    * @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface|\Drupal\Core\\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $controllerResolver;
31
32   /**
33    * The mocked plugin discovery.
34    *
35    * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\PHPUnit_Framework_MockObject_MockObject
36    */
37   protected $pluginDiscovery;
38
39   /**
40    * The plugin factory used in the test.
41    *
42    * @var \Drupal\Component\Plugin\Factory\FactoryInterface|\PHPUnit_Framework_MockObject_MockObject
43    */
44   protected $factory;
45
46   /**
47    * The cache backend used in the test.
48    *
49    * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
50    */
51   protected $cacheBackend;
52
53   /**
54    * The mocked module handler.
55    *
56    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
57    */
58   protected $moduleHandler;
59
60   /**
61    * The mocked access manager.
62    *
63    * @var \Drupal\Core\Access\AccessManagerInterface|\PHPUnit_Framework_MockObject_MockObject
64    */
65   protected $accessManager;
66
67   /**
68    * The mocked account.
69    *
70    * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
71    */
72   protected $account;
73
74   protected function setUp() {
75     $this->contextualLinkManager = $this
76       ->getMockBuilder('Drupal\Core\Menu\ContextualLinkManager')
77       ->disableOriginalConstructor()
78       ->setMethods(NULL)
79       ->getMock();
80
81     $this->controllerResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
82     $this->pluginDiscovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
83     $this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
84     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
85     $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface');
86     $this->accessManager = $this->getMock('Drupal\Core\Access\AccessManagerInterface');
87     $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
88
89     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'controllerResolver');
90     $property->setAccessible(TRUE);
91     $property->setValue($this->contextualLinkManager, $this->controllerResolver);
92
93     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'discovery');
94     $property->setAccessible(TRUE);
95     $property->setValue($this->contextualLinkManager, $this->pluginDiscovery);
96
97     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'factory');
98     $property->setAccessible(TRUE);
99     $property->setValue($this->contextualLinkManager, $this->factory);
100
101     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'account');
102     $property->setAccessible(TRUE);
103     $property->setValue($this->contextualLinkManager, $this->account);
104
105     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'accessManager');
106     $property->setAccessible(TRUE);
107     $property->setValue($this->contextualLinkManager, $this->accessManager);
108
109     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'moduleHandler');
110     $property->setAccessible(TRUE);
111     $property->setValue($this->contextualLinkManager, $this->moduleHandler);
112
113     $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
114     $language_manager->expects($this->any())
115       ->method('getCurrentLanguage')
116       ->will($this->returnValue(new Language(['id' => 'en'])));
117
118     $request_stack = new RequestStack();
119     $property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'requestStack');
120     $property->setAccessible(TRUE);
121     $property->setValue($this->contextualLinkManager, $request_stack);
122
123     $method = new \ReflectionMethod('Drupal\Core\Menu\ContextualLinkManager', 'alterInfo');
124     $method->setAccessible(TRUE);
125     $method->invoke($this->contextualLinkManager, 'contextual_links_plugins');
126
127     $this->contextualLinkManager->setCacheBackend($this->cacheBackend, 'contextual_links_plugins:en');
128   }
129
130   /**
131    * Tests the getContextualLinkPluginsByGroup method.
132    *
133    * @see \Drupal\Core\Menu\ContextualLinkManager::getContextualLinkPluginsByGroup()
134    */
135   public function testGetContextualLinkPluginsByGroup() {
136     $definitions = [
137       'test_plugin1' => [
138         'id' => 'test_plugin1',
139         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
140         'group' => 'group1',
141         'route_name' => 'test_route',
142       ],
143       'test_plugin2' => [
144         'id' => 'test_plugin2',
145         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
146         'group' => 'group1',
147         'route_name' => 'test_route2',
148       ],
149       'test_plugin3' => [
150         'id' => 'test_plugin3',
151         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
152         'group' => 'group2',
153         'route_name' => 'test_router3',
154       ],
155     ];
156     $this->pluginDiscovery->expects($this->once())
157       ->method('getDefinitions')
158       ->will($this->returnValue($definitions));
159
160     // Test with a non existing group.
161     $result = $this->contextualLinkManager->getContextualLinkPluginsByGroup('group_non_existing');
162     $this->assertEmpty($result);
163
164     $result = $this->contextualLinkManager->getContextualLinkPluginsByGroup('group1');
165     $this->assertEquals(['test_plugin1', 'test_plugin2'], array_keys($result));
166
167     $result = $this->contextualLinkManager->getContextualLinkPluginsByGroup('group2');
168     $this->assertEquals(['test_plugin3'], array_keys($result));
169   }
170
171   /**
172    * Tests the getContextualLinkPluginsByGroup method with a prefilled cache.
173    */
174   public function testGetContextualLinkPluginsByGroupWithCache() {
175     $definitions = [
176       'test_plugin1' => [
177         'id' => 'test_plugin1',
178         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
179         'group' => 'group1',
180         'route_name' => 'test_route',
181       ],
182       'test_plugin2' => [
183         'id' => 'test_plugin2',
184         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
185         'group' => 'group1',
186         'route_name' => 'test_route2',
187       ],
188     ];
189
190     $this->cacheBackend->expects($this->once())
191       ->method('get')
192       ->with('contextual_links_plugins:en:group1')
193       ->will($this->returnValue((object) ['data' => $definitions]));
194
195     $result = $this->contextualLinkManager->getContextualLinkPluginsByGroup('group1');
196     $this->assertEquals($definitions, $result);
197
198     // Ensure that the static cache works, so no second cache get is executed.
199
200     $result = $this->contextualLinkManager->getContextualLinkPluginsByGroup('group1');
201     $this->assertEquals($definitions, $result);
202   }
203
204   /**
205    * Tests processDefinition() by passing a plugin definition without a route.
206    *
207    * @see \Drupal\Core\Menu\ContextualLinkManager::processDefinition()
208    */
209   public function testProcessDefinitionWithoutRoute() {
210     $definition = [
211       'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
212       'group' => 'example',
213       'id' => 'test_plugin',
214     ];
215     $this->setExpectedException(PluginException::class);
216     $this->contextualLinkManager->processDefinition($definition, 'test_plugin');
217   }
218
219   /**
220    * Tests processDefinition() by passing a plugin definition without a group.
221    *
222    * @see \Drupal\Core\Menu\ContextualLinkManager::processDefinition()
223    */
224   public function testProcessDefinitionWithoutGroup() {
225     $definition = [
226       'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
227       'route_name' => 'example',
228       'id' => 'test_plugin',
229     ];
230     $this->setExpectedException(PluginException::class);
231     $this->contextualLinkManager->processDefinition($definition, 'test_plugin');
232   }
233
234   /**
235    * Tests the getContextualLinksArrayByGroup method.
236    *
237    * @see \Drupal\Core\Menu\ContextualLinkManager::getContextualLinksArrayByGroup()
238    */
239   public function testGetContextualLinksArrayByGroup() {
240     $definitions = [
241       'test_plugin1' => [
242         'id' => 'test_plugin1',
243         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
244         'title' => 'Plugin 1',
245         'weight' => 0,
246         'group' => 'group1',
247         'route_name' => 'test_route',
248         'options' => [],
249       ],
250       'test_plugin2' => [
251         'id' => 'test_plugin2',
252         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
253         'title' => 'Plugin 2',
254         'weight' => 2,
255         'group' => 'group1',
256         'route_name' => 'test_route2',
257         'options' => ['key' => 'value'],
258       ],
259       'test_plugin3' => [
260         'id' => 'test_plugin3',
261         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
262         'title' => 'Plugin 3',
263         'weight' => 5,
264         'group' => 'group2',
265         'route_name' => 'test_router3',
266         'options' => [],
267       ],
268     ];
269
270     $this->pluginDiscovery->expects($this->once())
271       ->method('getDefinitions')
272       ->will($this->returnValue($definitions));
273
274     $this->accessManager->expects($this->any())
275       ->method('checkNamedRoute')
276       ->will($this->returnValue(AccessResult::allowed()));
277
278     // Set up mocking of the plugin factory.
279     $map = [];
280     foreach ($definitions as $plugin_id => $definition) {
281       $map[] = [$plugin_id, [], new ContextualLinkDefault([], $plugin_id, $definition)];
282     }
283     $this->factory->expects($this->any())
284       ->method('createInstance')
285       ->will($this->returnValueMap($map));
286
287     $this->moduleHandler->expects($this->at(1))
288       ->method('alter')
289       ->with($this->equalTo('contextual_links'), new \PHPUnit_Framework_Constraint_Count(2), $this->equalTo('group1'), $this->equalTo(['key' => 'value']));
290
291     $result = $this->contextualLinkManager->getContextualLinksArrayByGroup('group1', ['key' => 'value']);
292     $this->assertCount(2, $result);
293     foreach (['test_plugin1', 'test_plugin2'] as $plugin_id) {
294       $definition = $definitions[$plugin_id];
295       $this->assertEquals($definition['weight'], $result[$plugin_id]['weight']);
296       $this->assertEquals($definition['title'], $result[$plugin_id]['title']);
297       $this->assertEquals($definition['route_name'], $result[$plugin_id]['route_name']);
298       $this->assertEquals($definition['options'], $result[$plugin_id]['localized_options']);
299     }
300   }
301
302   /**
303    * Tests the access checking of the getContextualLinksArrayByGroup method.
304    *
305    * @see \Drupal\Core\Menu\ContextualLinkManager::getContextualLinksArrayByGroup()
306    */
307   public function testGetContextualLinksArrayByGroupAccessCheck() {
308     $definitions = [
309       'test_plugin1' => [
310         'id' => 'test_plugin1',
311         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
312         'title' => 'Plugin 1',
313         'weight' => 0,
314         'group' => 'group1',
315         'route_name' => 'test_route',
316         'options' => [],
317       ],
318       'test_plugin2' => [
319         'id' => 'test_plugin2',
320         'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
321         'title' => 'Plugin 2',
322         'weight' => 2,
323         'group' => 'group1',
324         'route_name' => 'test_route2',
325         'options' => ['key' => 'value'],
326       ],
327     ];
328
329     $this->pluginDiscovery->expects($this->once())
330       ->method('getDefinitions')
331       ->will($this->returnValue($definitions));
332
333     $this->accessManager->expects($this->any())
334       ->method('checkNamedRoute')
335       ->will($this->returnValueMap([
336         ['test_route', ['key' => 'value'], $this->account, FALSE, TRUE],
337         ['test_route2', ['key' => 'value'], $this->account, FALSE, FALSE],
338       ]));
339
340     // Set up mocking of the plugin factory.
341     $map = [];
342     foreach ($definitions as $plugin_id => $definition) {
343       $plugin = $this->getMock('Drupal\Core\Menu\ContextualLinkInterface');
344       $plugin->expects($this->any())
345         ->method('getRouteName')
346         ->will($this->returnValue($definition['route_name']));
347       $plugin->expects($this->any())
348         ->method('getTitle')
349         ->will($this->returnValue($definition['title']));
350       $plugin->expects($this->any())
351         ->method('getWeight')
352         ->will($this->returnValue($definition['weight']));
353       $plugin->expects($this->any())
354         ->method('getOptions')
355         ->will($this->returnValue($definition['options']));
356       $map[] = [$plugin_id, [], $plugin];
357     }
358     $this->factory->expects($this->any())
359       ->method('createInstance')
360       ->will($this->returnValueMap($map));
361
362     $result = $this->contextualLinkManager->getContextualLinksArrayByGroup('group1', ['key' => 'value']);
363
364     // Ensure that access checking was respected.
365     $this->assertTrue(isset($result['test_plugin1']));
366     $this->assertFalse(isset($result['test_plugin2']));
367   }
368
369   /**
370    * Tests the plugins alter hook.
371    */
372   public function testPluginDefinitionAlter() {
373     $definitions['test_plugin'] = [
374       'id' => 'test_plugin',
375       'class' => ContextualLinkDefault::class,
376       'title' => 'Plugin',
377       'weight' => 2,
378       'group' => 'group1',
379       'route_name' => 'test_route',
380       'options' => ['key' => 'value'],
381     ];
382
383     $this->pluginDiscovery->expects($this->once())
384       ->method('getDefinitions')
385       ->will($this->returnValue($definitions));
386
387     $this->moduleHandler->expects($this->once())
388       ->method('alter')
389       ->with('contextual_links_plugins', $definitions);
390
391     $this->contextualLinkManager->getDefinition('test_plugin');
392   }
393
394 }