Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / token / src / Tests / TokenMenuTest.php
1 <?php
2
3 namespace Drupal\token\Tests;
4
5 use Drupal\node\Entity\Node;
6 use Drupal\Core\Url;
7 use Drupal\node\Entity\NodeType;
8 use Drupal\language\Entity\ConfigurableLanguage;
9 use Drupal\Core\Language\LanguageInterface;
10 use Drupal\system\Entity\Menu;
11 use Drupal\menu_link_content\Entity\MenuLinkContent;
12
13 /**
14  * Tests menu tokens.
15  *
16  * @group token
17  */
18 class TokenMenuTest extends TokenTestBase {
19
20   /**
21    * Modules to enable.
22    *
23    * @var array
24    */
25   public static $modules = [
26     'menu_ui',
27     'node',
28     'block',
29     'language',
30     'block_content',
31     'content_translation',
32   ];
33
34   function testMenuTokens() {
35     // Make sure we have a body field on the node type.
36     $this->drupalCreateContentType(['type' => 'page']);
37     // Add a menu.
38     $menu = Menu::create([
39       'id' => 'main-menu',
40       'label' => 'Main menu',
41       'description' => 'The <em>Main</em> menu is used on many sites to show the major sections of the site, often in a top navigation bar.',
42     ]);
43     $menu->save();
44
45     // Place the menu block.
46     $this->drupalPlaceBlock('system_menu_block:main-menu');
47
48     // Add a root link.
49     /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $root_link */
50     $root_link = MenuLinkContent::create([
51       'link' => ['uri' => 'internal:/admin'],
52       'title' => 'Administration',
53       'menu_name' => 'main-menu',
54     ]);
55     $root_link->save();
56
57     // Add another link with the root link as the parent.
58     /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $parent_link */
59     $parent_link = MenuLinkContent::create([
60       'link' => ['uri' => 'internal:/admin/config'],
61       'title' => 'Configuration',
62       'menu_name' => 'main-menu',
63       'parent' => $root_link->getPluginId(),
64     ]);
65     $parent_link->save();
66
67     // Test menu link tokens.
68     $tokens = [
69       'id' => $parent_link->getPluginId(),
70       'title' => 'Configuration',
71       'menu' => 'Main menu',
72       'menu:name' => 'Main menu',
73       'menu:machine-name' => $menu->id(),
74       'menu:description' => 'The <em>Main</em> menu is used on many sites to show the major sections of the site, often in a top navigation bar.',
75       'menu:menu-link-count' => '2',
76       'menu:edit-url' => Url::fromRoute('entity.menu.edit_form', ['menu' => 'main-menu'], ['absolute' => TRUE])->toString(),
77       'url' => Url::fromRoute('system.admin_config', [], ['absolute' => TRUE])->toString(),
78       'url:absolute' => Url::fromRoute('system.admin_config', [], ['absolute' => TRUE])->toString(),
79       'url:relative' => Url::fromRoute('system.admin_config', [], ['absolute' => FALSE])->toString(),
80       'url:path' => '/admin/config',
81       'url:alias' => '/admin/config',
82       'edit-url' => Url::fromRoute('entity.menu_link_content.canonical', ['menu_link_content' => $parent_link->id()], ['absolute' => TRUE])->toString(),
83       'parent' => 'Administration',
84       'parent:id' => $root_link->getPluginId(),
85       'parent:title' => 'Administration',
86       'parent:menu' => 'Main menu',
87       'parent:parent' => NULL,
88       'parents' => 'Administration',
89       'parents:count' => 1,
90       'parents:keys' => $root_link->getPluginId(),
91       'root' => 'Administration',
92       'root:id' => $root_link->getPluginId(),
93       'root:parent' => NULL,
94       'root:root' => NULL,
95     ];
96     $this->assertTokens('menu-link', ['menu-link' => $parent_link], $tokens);
97
98     // Add a node.
99     $node = $this->drupalCreateNode();
100
101     // Allow main menu for this node type.
102     //$this->config('menu.entity.node.' . $node->getType())->set('available_menus', ['main-menu'])->save();
103
104     // Add a node menu link.
105     /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $node_link */
106     $node_link = MenuLinkContent::create([
107       'link' => ['uri' => 'entity:node/' . $node->id()],
108       'title' => 'Node link',
109       'parent' => $parent_link->getPluginId(),
110       'menu_name' => 'main-menu',
111     ]);
112     $node_link->save();
113
114     // Test [node:menu] tokens.
115     $tokens = [
116       'menu-link' => 'Node link',
117       'menu-link:id' => $node_link->getPluginId(),
118       'menu-link:title' => 'Node link',
119       'menu-link:menu' => 'Main menu',
120       'menu-link:url' => $node->toUrl('canonical', ['absolute' => TRUE])->toString(),
121       'menu-link:url:path' => '/node/' . $node->id(),
122       'menu-link:edit-url' => $node_link->url('edit-form', ['absolute' => TRUE]),
123       'menu-link:parent' => 'Configuration',
124       'menu-link:parent:id' => $parent_link->getPluginId(),
125       'menu-link:parents' => 'Administration, Configuration',
126       'menu-link:parents:count' => 2,
127       'menu-link:parents:keys' => $root_link->getPluginId() . ', ' . $parent_link->getPluginId(),
128       'menu-link:root' => 'Administration',
129       'menu-link:root:id' => $root_link->getPluginId(),
130     ];
131     $this->assertTokens('node', ['node' => $node], $tokens);
132
133     // Reload the node which will not have $node->menu defined and re-test.
134     $loaded_node = Node::load($node->id());
135     $this->assertTokens('node', ['node' => $loaded_node], $tokens);
136
137     // Regression test for http://drupal.org/node/1317926 to ensure the
138     // original node object is not changed when calling menu_node_prepare().
139     $this->assertTrue(!isset($loaded_node->menu), t('The $node->menu property was not modified during token replacement.'), 'Regression');
140
141     // Now add a node with a menu-link from the UI and ensure it works.
142     $this->drupalLogin($this->drupalCreateUser([
143       'create page content',
144       'edit any page content',
145       'administer menu',
146       'administer nodes',
147       'administer content types',
148       'access administration pages',
149     ]));
150     // Setup node type menu options.
151     $edit = [
152       'menu_options[main-menu]' => 1,
153       'menu_options[main]' => 1,
154       'menu_parent' => 'main-menu:',
155     ];
156     $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
157
158     // Use a menu-link token in the body.
159     $this->drupalGet('node/add/page');
160     $this->drupalPostForm(NULL, [
161       // This should get replaced on save.
162       // @see token_module_test_node_presave()
163       'title[0][value]' => 'Node menu title test',
164       'body[0][value]' => 'This is a [node:menu-link:title] token to the menu link title',
165       'menu[enabled]' => 1,
166       'menu[title]' => 'Test preview',
167     ], t('Save'));
168     $node = $this->drupalGetNodeByTitle('Node menu title test');
169     $this->assertEqual('This is a Test preview token to the menu link title', $node->body->value);
170
171     // Disable the menu link, save the node and verify that the menu link is
172     // no longer displayed.
173     $link = menu_ui_get_menu_link_defaults($node);
174     $this->drupalPostForm('admin/structure/menu/manage/main-menu', ['links[menu_plugin_id:' . $link['id'] . '][enabled]' => FALSE], t('Save'));
175     $this->assertText('Menu Main menu has been updated.');
176     $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save'));
177     $this->assertNoLink('Test preview');
178
179     // Now test a parent link and token.
180     $this->drupalGet('node/add/page');
181     // Make sure that the previous node save didn't result in two menu-links
182     // being created by the computed menu-link ER field.
183     // @see token_entity_base_field_info()
184     // @see token_node_menu_link_submit()
185     $selects = $this->cssSelect('select[name="menu[menu_parent]"]');
186     $select = reset($selects);
187     $options = $this->getAllOptions($select);
188     // Filter to items with title containing 'Test preview'.
189     $options = array_filter($options, function (\SimpleXMLElement $item) {
190       return strpos((string) $item[0], 'Test preview') !== FALSE;
191     });
192     $this->assertEqual(1, count($options));
193     $this->drupalPostForm(NULL, [
194       'title[0][value]' => 'Node menu title parent path test',
195       'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
196       'menu[enabled]' => 1,
197       'menu[title]' => 'Child link',
198       'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId(),
199     ], t('Save'));
200     $node = $this->drupalGetNodeByTitle('Node menu title parent path test');
201     $this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value);
202
203     // Now edit the node and update the parent and title.
204     $this->drupalPostForm('node/' . $node->id() . '/edit', [
205       'menu[menu_parent]' => 'main-menu:' . $node_link->getPluginId(),
206       'title[0][value]' => 'Node menu title edit parent path test',
207       'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
208     ], t('Save'));
209     $node = $this->drupalGetNodeByTitle('Node menu title edit parent path test', TRUE);
210     $this->assertEqual(sprintf('This is a /node/%d token to the menu link parent', $loaded_node->id()), $node->body->value);
211
212     // Make sure that the previous node edit didn't result in two menu-links
213     // being created by the computed menu-link ER field.
214     // @see token_entity_base_field_info()
215     // @see token_node_menu_link_submit()
216     $this->drupalGet('node/add/page');
217     $selects = $this->cssSelect('select[name="menu[menu_parent]"]');
218     $select = reset($selects);
219     $options = $this->getAllOptions($select);
220     // Filter to items with title containing 'Test preview'.
221     $options = array_filter($options, function (\SimpleXMLElement $item) {
222       return strpos((string) $item[0], 'Child link') !== FALSE;
223     });
224     $this->assertEqual(1, count($options));
225
226     // Now add a new node with no menu.
227     $this->drupalGet('node/add/page');
228     $this->drupalPostForm(NULL, [
229       'title[0][value]' => 'Node menu adding menu later test',
230       'body[0][value]' => 'Going to add a menu link on edit',
231       'menu[enabled]' => 0,
232     ], t('Save'));
233     $node = $this->drupalGetNodeByTitle('Node menu adding menu later test');
234     // Now edit it and add a menu item.
235     $this->drupalGet('node/' . $node->id() . '/edit');
236     $this->drupalPostForm(NULL, [
237       'title[0][value]' => 'Node menu adding menu later test',
238       'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
239       'menu[enabled]' => 1,
240       'menu[title]' => 'Child link',
241       'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId(),
242     ], t('Save'));
243     $node = $this->drupalGetNodeByTitle('Node menu adding menu later test', TRUE);
244     $this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value);
245     // And make sure the menu link exists with the right URI.
246     $link = menu_ui_get_menu_link_defaults($node);
247     $this->assertTrue(!empty($link['entity_id']));
248     $query = \Drupal::entityQuery('menu_link_content')
249       ->condition('link.uri', 'entity:node/' . $node->id())
250       ->sort('id', 'ASC')
251       ->range(0, 1);
252     $result = $query->execute();
253     $this->assertTrue($result);
254
255     // Create a node with a menu link and create 2 menu links linking to this
256     // node after. Verify that the menu link provided by the node has priority.
257     $node_title = $this->randomMachineName();
258     $edit = [
259       'title[0][value]' => $node_title,
260       'menu[enabled]' => 1,
261       'menu[title]' => 'menu link provided by node',
262     ];
263     $this->drupalPostForm('node/add/page', $edit, t('Save'));
264     $this->assertText('page ' . $node_title . ' has been created');
265     $node = $this->drupalGetNodeByTitle($node_title);
266
267     $menu_ui_link1 = MenuLinkContent::create([
268       'link' => ['uri' => 'entity:node/' . $node->id()],
269       'title' => 'menu link 1 provided by menu ui',
270       'menu_name' => 'main-menu',
271     ]);
272     $menu_ui_link1->save();
273
274     $menu_ui_link2 = MenuLinkContent::create([
275       'link' => ['uri' => 'entity:node/' . $node->id()],
276       'title' => 'menu link 2 provided by menu ui',
277       'menu_name' => 'main-menu',
278     ]);
279     $menu_ui_link2->save();
280
281     $tokens = [
282       'menu-link' => 'menu link provided by node',
283       'menu-link:title' => 'menu link provided by node',
284     ];
285     $this->assertTokens('node', ['node' => $node], $tokens);
286   }
287
288   /**
289    * Tests that the module doesn't affect integrity of the menu, when
290    * translating them and that menu links tokens are correct.
291    */
292   function testMultilingualMenu() {
293     // Place the menu block.
294     $this->drupalPlaceBlock('system_menu_block:main');
295
296     // Add a second language.
297     $language = ConfigurableLanguage::create([
298       'id' => 'de',
299       'label' => 'German',
300     ]);
301     $language->save();
302
303     // Create the article content type.
304     $node_type = NodeType::create([
305       'type' => 'article',
306     ]);
307     $node_type->save();
308
309     $permissions = [
310       'access administration pages',
311       'administer content translation',
312       'administer content types',
313       'administer languages',
314       'create content translations',
315       'create article content',
316       'edit any article content',
317       'translate any entity',
318       'administer menu',
319     ];
320     $this->drupalLogin($this->drupalCreateUser($permissions));
321
322     // Enable translation for articles and menu links.
323     $this->drupalGet('admin/config/regional/content-language');
324     $edit = [
325       'entity_types[node]' => TRUE,
326       'entity_types[menu_link_content]' => TRUE,
327       'settings[node][article][translatable]' => TRUE,
328       'settings[node][article][fields][title]' => TRUE,
329       'settings[menu_link_content][menu_link_content][translatable]' => TRUE,
330     ];
331     $this->drupalPostForm(NULL, $edit, t('Save configuration'));
332     $this->assertText('Settings successfully updated.');
333
334     // Create an english node with an english menu.
335     $this->drupalGet('/node/add/article');
336     $edit = [
337       'title[0][value]' => 'English test node with menu',
338       'menu[enabled]' => TRUE,
339       'menu[title]' => 'English menu title',
340     ];
341     $this->drupalPostForm('/node/add/article', $edit, t('Save'));
342     $this->assertText('English test node with menu has been created.');
343
344     // Add a german translation.
345     $this->drupalGet('node/1/translations');
346     $this->clickLink('Add');
347     $edit = [
348       'title[0][value]' => 'German test node with menu',
349       'menu[enabled]' => TRUE,
350       'menu[title]' => 'German menu title',
351     ];
352     $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
353     $this->assertText('German test node with menu has been updated.');
354
355     // Verify that the menu links are correct.
356     $this->drupalGet('node/1');
357     $this->assertLink('English menu title');
358     $this->drupalGet('de/node/1');
359     $this->assertLink('German menu title');
360
361     // Verify that tokens are correct.
362     $node = Node::load(1);
363     $this->assertTokens('node', ['node' => $node], ['menu-link' => 'English menu title']);
364     $this->assertTokens('node', ['node' => $node], [
365       'menu-link' => 'German menu title',
366       'menu-link:title' => 'German menu title',
367     ], ['langcode' => 'de']);
368
369     // Get the menu link and create a child menu link to assert parent and root
370     // tokens.
371     $url = $node->toUrl();
372     /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
373     $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
374     $links = $menu_link_manager->loadLinksByRoute($url->getRouteName(), $url->getRouteParameters());
375     $link = reset($links);
376
377     $base_options = [
378       'provider' => 'menu_test',
379       'menu_name' => 'menu_test',
380     ];
381     $child_1 = $base_options + [
382         'title' => 'child_1 title EN',
383         'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1'],
384         'parent' => $link->getPluginId(),
385         'langcode' => 'en',
386       ];
387     $child_1 = MenuLinkContent::create($child_1);
388     $child_1->save();
389
390     // Add the german translation.
391     $child_1->addTranslation('de', ['title' => 'child_1 title DE'] + $child_1->toArray());
392     $child_1->save();
393
394     $this->assertTokens('menu-link', ['menu-link' => $child_1], [
395       'title' => 'child_1 title EN',
396       'parents' => 'English menu title',
397       'root' => 'English menu title',
398     ]);
399     $this->assertTokens('menu-link', ['menu-link' => $child_1], [
400       'title' => 'child_1 title DE',
401       'parents' => 'German menu title',
402       'root' => 'German menu title',
403     ], ['langcode' => 'de']);
404   }
405
406   /**
407    * Tests menu link parents token.
408    */
409   public function testMenuLinkParentsToken() {
410     // Create a menu with a simple link hierarchy :
411     // - parent
412     //   - child-1
413     //      - child-1-1
414     Menu::create([
415       'id' => 'menu_test',
416       'label' => 'Test menu',
417     ])->save();
418     $base_options = [
419       'provider' => 'menu_test',
420       'menu_name' => 'menu_test',
421     ];
422     $parent = $base_options + [
423         'title' => 'parent title',
424         'link' => ['uri' => 'internal:/menu-test/hierarchy/parent'],
425     ];
426     $parent = MenuLinkContent::create($parent);
427     $parent->save();
428     $child_1 = $base_options + [
429         'title' => 'child_1 title',
430         'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1'],
431         'parent' => $parent->getPluginId(),
432     ];
433     $child_1 = MenuLinkContent::create($child_1);
434     $child_1->save();
435     $child_1_1 = $base_options + [
436         'title' => 'child_1_1 title',
437         'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1/child_1_1'],
438         'parent' => $child_1->getPluginId(),
439     ];
440     $child_1_1 = MenuLinkContent::create($child_1_1);
441     $child_1_1->save();
442
443     $this->assertTokens('menu-link', ['menu-link' => $child_1_1], ['parents' => 'parent title, child_1 title']);
444
445     // Change the parent of child_1_1 to 'parent' at the entity level.
446     $child_1_1->parent->value = $parent->getPluginId();
447     $child_1_1->save();
448
449     $this->assertTokens('menu-link', ['menu-link' => $child_1_1], ['parents' => 'parent title']);
450
451     // Change the parent of child_1_1 to 'main', at the entity level.
452     $child_1_1->parent->value = '';
453     $child_1_1->save();
454
455     // The token shouldn't have been generated; the menu link has no parent.
456     $this->assertNoTokens('menu-link', ['menu-link' => $child_1_1], ['parents']);
457   }
458
459 }