diff --git a/src/Tests/TokenMenuTest.php b/src/Tests/TokenMenuTest.php index b14e5e3..914f9cf 100644 --- a/src/Tests/TokenMenuTest.php +++ b/src/Tests/TokenMenuTest.php @@ -129,6 +129,7 @@ function testMenuTokens() { // 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', @@ -178,6 +179,29 @@ function testMenuTokens() { ], 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); - $this->drupalGet('admin/structure/menu/manage/main-menu'); + + // 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)); } + } diff --git a/tests/modules/token_module_test/token_module_test.module b/tests/modules/token_module_test/token_module_test.module index 7caf121..c263320 100644 --- a/tests/modules/token_module_test/token_module_test.module +++ b/tests/modules/token_module_test/token_module_test.module @@ -24,6 +24,7 @@ function token_module_test_page_attachments() { */ function token_module_test_node_presave(NodeInterface $node) { // Transform tokens in the body. + // @see \Drupal\token\Tests\TokenMenuTest::testMenuTokens() if ($node->hasField('body')) { $node->body->value = \Drupal::token() ->replace($node->body->value, ['node' => $node]); diff --git a/token.module b/token.module index 4f01385..9d8be42 100644 --- a/token.module +++ b/token.module @@ -644,10 +644,14 @@ function token_element_children(&$elements, $sort = FALSE) { * Implements hook_entity_base_field_info(). */ function token_entity_base_field_info(EntityTypeInterface $entity_type) { + // We add a psuedo entity-reference field to track the menu entry created + // from the node add/edit form so that tokens generated at that time that + // reference the menu link can access the yet to be saved menu link. + // @todo Revisit when https://www.drupal.org/node/2315773 is resolved. if ($entity_type->id() === 'node' && \Drupal::moduleHandler()->moduleExists('menu_ui')) { $fields['menu_link'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Menu link')) - ->setDescription(t('First menu link for the node.')) + ->setDescription(t('Computed menu link for the node (only available during node saving).')) ->setRevisionable(TRUE) ->setSetting('target_type', 'menu_link_content') ->setTranslatable(TRUE) @@ -678,9 +682,7 @@ function token_form_node_form_alter(&$form, FormStateInterface $form_state) { return; } /** @var \Drupal\node\NodeForm $form_object */ - $form_object = $form_state->getFormObject(); - $node = $form_object->getEntity(); - if (!$node->isNew() || !\Drupal::currentUser()->hasPermission('administer menu')) { + if (!\Drupal::currentUser()->hasPermission('administer menu')) { // We're only interested in when the node is unsaved and the editor has // permission to create new menu links. return; @@ -703,13 +705,19 @@ function token_node_menu_link_submit($entity_type, NodeInterface $node, &$form, $values['parent'] = $parent; } // Construct an unsaved entity. - // Create a new menu_link_content entity. - $entity = MenuLinkContent::create(array( - // Lets just reference the UUID for now, the link is not important for - // token generation. - 'link' => ['uri' => 'internal:/node/' . $node->uuid()], - 'langcode' => $node->language()->getId(), - )); + if ($entity_id = $form_state->getValue(['menu', 'entity_id'])) { + // Use the existing menu_link_content entity. + $entity = MenuLinkContent::load($entity_id); + } + else { + // Create a new menu_link_content entity. + $entity = MenuLinkContent::create(array( + // Lets just reference the UUID for now, the link is not important for + // token generation. + 'link' => ['uri' => 'internal:/node/' . $node->uuid()], + 'langcode' => $node->language()->getId(), + )); + } $entity->enabled->value = 1; $entity->title->value = trim($values['title']); $entity->description->value = trim($values['description']); diff --git a/token.tokens.inc b/token.tokens.inc index f1949a1..8487180 100644 --- a/token.tokens.inc +++ b/token.tokens.inc @@ -1060,7 +1060,7 @@ function menu_ui_tokens($type, $tokens, array $data = array(), array $options = foreach ($tokens as $name => $original) { switch ($name) { case 'menu-link': - // On first save we populate a calculated field with a menu_link + // On node-form save we populate a calculated field with a menu_link // references. // @see token_node_menu_link_submit() if ($node->getFieldDefinition('menu_link') && $menu_link = $node->menu_link->entity) {