/** * Test creating, editing, deleting menu links via node form widget. */ function testMenuNodeFormWidget() { // Verify that cacheability metadata is bubbled from the menu link tree // access checking that is performed when determining the "default parent // item" options in menu_ui_form_node_type_form_alter(). The "log out" link // adds the "user.roles:authenticated" cache context. $this->drupalGet('admin/structure/types/manage/page'); $this->assertCacheContext('user.roles:authenticated'); // Disable the default main menu, so that no menus are enabled. $edit = array('menu_options[main]' => FALSE); $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); // Verify that no menu settings are displayed and nodes can be created. $this->drupalGet('node/add/page'); $this->assertText(t('Create Basic page')); $this->assertNoText(t('Menu settings')); $node_title = $this->randomMachineName(); $edit = array('title[0][value]' => $node_title, 'body[0][value]' => $this->randomString()); $this->drupalPostForm(NULL, $edit, t('Save')); $node = $this->drupalGetNodeByTitle($node_title); $this->assertEqual($node->getTitle(), $edit['title[0][value]']); // Test that we cannot set a menu item from a menu that is not set as // available. $edit = array('menu_options[tools]' => 1, 'menu_parent' => 'main:'); $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); $this->assertText(t('The selected menu item is not under one of the selected menus.')); $this->assertNoRaw(t('The content type %name has been updated.', array('%name' => 'Basic page'))); // Enable Tools menu as available menu. $edit = array('menu_options[main]' => 1, 'menu_options[tools]' => 1, 'menu_parent' => 'main:'); $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); $this->assertRaw(t('The content type %name has been updated.', array('%name' => 'Basic page'))); // Test that we can preview a node that will create a menu item. $edit = array('title[0][value]' => $node_title, 'menu[enabled]' => 1, 'menu[title]' => 'Test preview'); $this->drupalPostForm('node/add/page', $edit, t('Preview')); // Create a node. $node_title = $this->randomMachineName(); $edit = array('title[0][value]' => $node_title, 'body[0][value]' => $this->randomString()); $this->drupalPostForm('node/add/page', $edit, t('Save')); $node = $this->drupalGetNodeByTitle($node_title); // Assert that there is no link for the node. $this->drupalGet('test-page'); $this->assertNoLink($node_title); // Edit the node, enable the menu link setting, but skip the link title. $edit = array('menu[enabled]' => 1); $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); // Assert that there is no link for the node. $this->drupalGet('test-page'); $this->assertNoLink($node_title); // Use not only the save button, but also the two special buttons: // 'Save and publish' as well as 'Save and keep published'. // These buttons just appear for 'administer nodes' users. $admin_user = $this->drupalCreateUser(['access administration pages', 'administer content types', 'administer nodes', 'administer menu', 'create page content', 'edit any page content']); $this->drupalLogin($admin_user); foreach (['Save and unpublish' => FALSE, 'Save and keep unpublished' => FALSE, 'Save and publish' => TRUE, 'Save and keep published' => TRUE] as $submit => $visible) { $edit = ['menu[enabled]' => 1, 'menu[title]' => $node_title]; $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, $submit); // Assert that the link exists. $this->drupalGet('test-page'); if ($visible) { $this->assertLink($node_title, 0, 'Found a menu link after submitted with ' . $submit); } else { $this->assertNoLink($node_title, 'Found no menu link after submitted with ' . $submit); } } // Log back in as normal user. $this->drupalLogin($this->editor); // Edit the node and create a menu link. $edit = array('menu[enabled]' => 1, 'menu[title]' => $node_title, 'menu[weight]' => 17); $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); // Assert that the link exists. $this->drupalGet('test-page'); $this->assertLink($node_title); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertFieldById('edit-menu-weight', 17, 'Menu weight correct in edit form'); // Disable the menu link, then edit the node--the link should stay disabled. $link_id = menu_ui_get_menu_link_defaults($node)['entity_id']; /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $link */ $link = MenuLinkContent::load($link_id); $link->set('enabled', FALSE); $link->save(); $this->drupalPostForm($node->urlInfo('edit-form'), $edit, t('Save')); $link = MenuLinkContent::load($link_id); $this->assertFalse($link->isEnabled(), 'Saving a node with a disabled menu link keeps the menu link disabled.'); // Edit the node and remove the menu link. $edit = array('menu[enabled]' => FALSE); $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); // Assert that there is no link for the node. $this->drupalGet('test-page'); $this->assertNoLink($node_title); // Add a menu link to the Administration menu. $item = entity_create('menu_link_content', array('link' => [['uri' => 'entity:node/' . $node->id()]], 'title' => $this->randomMachineName(16), 'menu_name' => 'admin')); $item->save(); // Assert that disabled Administration menu is not shown on the // node/$nid/edit page. $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertText('Provide a menu link', 'Link in not allowed menu not shown in node edit form'); // Assert that the link is still in the Administration menu after save. $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); $link = MenuLinkContent::load($item->id()); $this->assertTrue($link, 'Link in not allowed menu still exists after saving node'); // Move the menu link back to the Tools menu. $item->menu_name->value = 'tools'; $item->save(); // Create a second node. $child_node = $this->drupalCreateNode(array('type' => 'article')); // Assign a menu link to the second node, being a child of the first one. $child_item = entity_create('menu_link_content', array('link' => [['uri' => 'entity:node/' . $child_node->id()]], 'title' => $this->randomMachineName(16), 'parent' => $item->getPluginId(), 'menu_name' => $item->getMenuName())); $child_item->save(); // Edit the first node. $this->drupalGet('node/' . $node->id() . '/edit'); // Assert that it is not possible to set the parent of the first node to itself or the second node. $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $item->getPluginId()); $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $child_item->getPluginId()); // Assert that unallowed Administration menu is not available in options. $this->assertNoOption('edit-menu-menu-parent', 'admin:'); }
function testMenuTokens() { // Make sure we have a body field on the node type. $this->drupalCreateContentType(['type' => 'page']); // Add a menu. $menu = entity_create('menu', array('id' => 'main-menu', 'label' => 'Main 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.')); $menu->save(); // Place the menu block. $this->drupalPlaceBlock('system_menu_block:main-menu'); // Add a root link. /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $root_link */ $root_link = entity_create('menu_link_content', array('link' => ['uri' => 'internal:/admin'], 'title' => 'Administration', 'menu_name' => 'main-menu')); $root_link->save(); // Add another link with the root link as the parent. /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $parent_link */ $parent_link = entity_create('menu_link_content', array('link' => ['uri' => 'internal:/admin/config'], 'title' => 'Configuration', 'menu_name' => 'main-menu', 'parent' => $root_link->getPluginId())); $parent_link->save(); // Test menu link tokens. $tokens = array('id' => $parent_link->getPluginId(), 'title' => 'Configuration', 'menu' => 'Main menu', 'menu:name' => 'Main menu', 'menu:machine-name' => $menu->id(), '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.', 'menu:menu-link-count' => '2', 'menu:edit-url' => Url::fromRoute('entity.menu.edit_form', ['menu' => 'main-menu'], array('absolute' => TRUE))->toString(), 'url' => Url::fromRoute('system.admin_config', [], array('absolute' => TRUE))->toString(), 'url:absolute' => Url::fromRoute('system.admin_config', [], array('absolute' => TRUE))->toString(), 'url:relative' => Url::fromRoute('system.admin_config', [], array('absolute' => FALSE))->toString(), 'url:path' => '/admin/config', 'url:alias' => '/admin/config', 'edit-url' => Url::fromRoute('entity.menu_link_content.canonical', ['menu_link_content' => $parent_link->id()], array('absolute' => TRUE))->toString(), 'parent' => 'Administration', 'parent:id' => $root_link->getPluginId(), 'parent:title' => 'Administration', 'parent:menu' => 'Main menu', 'parent:parent' => NULL, 'parents' => 'Administration', 'parents:count' => 1, 'parents:keys' => $root_link->getPluginId(), 'root' => 'Administration', 'root:id' => $root_link->getPluginId(), 'root:parent' => NULL, 'root:root' => NULL); $this->assertTokens('menu-link', array('menu-link' => $parent_link), $tokens); // Add a node. $node = $this->drupalCreateNode(); // Allow main menu for this node type. //$this->config('menu.entity.node.' . $node->getType())->set('available_menus', array('main-menu'))->save(); // Add a node menu link. /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $node_link */ $node_link = entity_create('menu_link_content', array('link' => ['uri' => 'entity:node/' . $node->id()], 'title' => 'Node link', 'parent' => $parent_link->getPluginId(), 'menu_name' => 'main-menu')); $node_link->save(); // Test [node:menu] tokens. $tokens = array('menu-link' => 'Node link', 'menu-link:id' => $node_link->getPluginId(), 'menu-link:title' => 'Node link', 'menu-link:menu' => 'Main menu', 'menu-link:url' => $node->url('canonical', ['absolute' => TRUE]), 'menu-link:url:path' => '/node/' . $node->id(), 'menu-link:edit-url' => $node_link->url('edit-form', ['absolute' => TRUE]), 'menu-link:parent' => 'Configuration', 'menu-link:parent:id' => $parent_link->getPluginId(), 'menu-link:parents' => 'Administration, Configuration', 'menu-link:parents:count' => 2, 'menu-link:parents:keys' => $root_link->getPluginId() . ', ' . $parent_link->getPluginId(), 'menu-link:root' => 'Administration', 'menu-link:root:id' => $root_link->getPluginId()); $this->assertTokens('node', array('node' => $node), $tokens); // Reload the node which will not have $node->menu defined and re-test. $loaded_node = Node::load($node->id()); $this->assertTokens('node', array('node' => $loaded_node), $tokens); // Regression test for http://drupal.org/node/1317926 to ensure the // original node object is not changed when calling menu_node_prepare(). $this->assertTrue(!isset($loaded_node->menu), t('The $node->menu property was not modified during token replacement.'), 'Regression'); // Now add a node with a menu-link from the UI and ensure it works. $this->drupalLogin($this->drupalCreateUser(['create page content', 'edit any page content', 'administer menu', 'administer nodes', 'administer content types', 'access administration pages'])); // Setup node type menu options. $edit = array('menu_options[main-menu]' => 1, 'menu_options[main]' => 1, 'menu_parent' => 'main-menu:'); $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); // Use a menu-link token in the body. $this->drupalGet('node/add/page'); $this->drupalPostForm(NULL, ['title[0][value]' => 'Node menu title test', 'body[0][value]' => 'This is a [node:menu-link:title] token to the menu link title', 'menu[enabled]' => 1, 'menu[title]' => 'Test preview'], t('Save and publish')); $node = $this->drupalGetNodeByTitle('Node menu title test'); $this->assertEqual('This is a Test preview token to the menu link title', $node->body->value); // Disable the menu link, save the node and verify that the menu link is // no longer displayed. $link = menu_ui_get_menu_link_defaults($node); $this->drupalPostForm('admin/structure/menu/manage/main-menu', ['links[menu_plugin_id:' . $link['id'] . '][enabled]' => FALSE], t('Save')); $this->assertText('Menu Main menu has been updated.'); $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and keep published')); $this->assertNoLink('Test preview'); // Now test a parent link and token. $this->drupalGet('node/add/page'); // Make sure that the previous node save didn't result in two menu-links // being created by the computed menu-link ER field. // @see token_entity_base_field_info() // @see token_node_menu_link_submit() $selects = $this->cssSelect('select[name="menu[menu_parent]"]'); $select = reset($selects); $options = $this->getAllOptions($select); // Filter to items with title containing 'Test preview'. $options = array_filter($options, function (\SimpleXMLElement $item) { return strpos((string) $item[0], 'Test preview') !== FALSE; }); $this->assertEqual(1, count($options)); $this->drupalPostForm(NULL, ['title[0][value]' => 'Node menu title parent path test', 'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent', 'menu[enabled]' => 1, 'menu[title]' => 'Child link', 'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId()], t('Save and publish')); $node = $this->drupalGetNodeByTitle('Node menu title parent path test'); $this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value); // Now edit the node and update the parent and title. $this->drupalPostForm('node/' . $node->id() . '/edit', ['menu[menu_parent]' => 'main-menu:' . $node_link->getPluginId(), 'title[0][value]' => 'Node menu title edit parent path test', 'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent'], t('Save and keep published')); $node = $this->drupalGetNodeByTitle('Node menu title edit parent path test', TRUE); $this->assertEqual(sprintf('This is a /node/%d token to the menu link parent', $loaded_node->id()), $node->body->value); // Make sure that the previous node edit didn't result in two menu-links // being created by the computed menu-link ER field. // @see token_entity_base_field_info() // @see token_node_menu_link_submit() $this->drupalGet('node/add/page'); $selects = $this->cssSelect('select[name="menu[menu_parent]"]'); $select = reset($selects); $options = $this->getAllOptions($select); // Filter to items with title containing 'Test preview'. $options = array_filter($options, function (\SimpleXMLElement $item) { return strpos((string) $item[0], 'Child link') !== FALSE; }); $this->assertEqual(1, count($options)); // Now add a new node with no menu. $this->drupalGet('node/add/page'); $this->drupalPostForm(NULL, ['title[0][value]' => 'Node menu adding menu later test', 'body[0][value]' => 'Going to add a menu link on edit', 'menu[enabled]' => 0], t('Save and publish')); $node = $this->drupalGetNodeByTitle('Node menu adding menu later test'); // Now edit it and add a menu item. $this->drupalGet('node/' . $node->id() . '/edit'); $this->drupalPostForm(NULL, ['title[0][value]' => 'Node menu adding menu later test', 'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent', 'menu[enabled]' => 1, 'menu[title]' => 'Child link', 'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId()], t('Save and keep published')); $node = $this->drupalGetNodeByTitle('Node menu adding menu later test', TRUE); $this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value); // And make sure the menu link exists with the right URI. $link = menu_ui_get_menu_link_defaults($node); $this->assertTrue(!empty($link['entity_id'])); $query = \Drupal::entityQuery('menu_link_content')->condition('link.uri', 'entity:node/' . $node->id())->sort('id', 'ASC')->range(0, 1); $result = $query->execute(); $this->assertTrue($result); }