diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module index cfd29f0..d5e4520 100644 --- a/core/modules/menu_ui/menu_ui.module +++ b/core/modules/menu_ui/menu_ui.module @@ -127,54 +127,33 @@ function menu_ui_block_view_system_menu_block_alter(array &$build, BlockPluginIn } /** - * Implements hook_ENTITY_TYPE_insert() for node entities. + * Helper function to save a menu link for a node. */ -function menu_ui_node_insert(EntityInterface $node) { - menu_ui_node_save($node); -} - -/** - * Implements hook_ENTITY_TYPE_update() for node entities. - */ -function menu_ui_node_update(EntityInterface $node) { - menu_ui_node_save($node); -} - -/** - * Helper for hook_ENTITY_TYPE_insert() and hook_ENTITY_TYPE_update() for nodes. - */ -function menu_ui_node_save(EntityInterface $node) { - if (!empty($node->menu)) { - /** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */ - $definition = $node->menu; - if (trim($definition['title'])) { - if (!empty($definition['entity_id'])) { - $entity = MenuLinkContent::load($definition['entity_id']); - $entity->enabled->value = 1; - $entity->title->value = trim($definition['title']); - $entity->description->value = trim($definition['description']); - $entity->menu_name->value = $definition['menu_name']; - $entity->parent->value = $definition['parent']; - $entity->weight->value = isset($definition['weight']) ? $definition['weight'] : 0; - } - else { - // Create a new menu_link_content entity. - $entity = entity_create('menu_link_content', array( - 'title' => trim($definition['title']), - 'description' => trim($definition['description']), - 'link' => ['uri' => 'entity:node/' . $node->id()], - 'menu_name' => $definition['menu_name'], - 'parent' => $definition['parent'], - 'weight' => isset($definition['weight']) ? $definition['weight'] : 0, - 'enabled' => 1, - 'langcode' => $node->getUntranslated()->language()->getId(), - )); - } - if (!$entity->save()) { - drupal_set_message(t('There was an error saving the menu link.'), 'error'); - } - } +function menu_ui_node_save(NodeInterface $node, array $definition) { + /** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */ + if (!empty($definition['entity_id'])) { + $entity = MenuLinkContent::load($definition['entity_id']); + $entity->enabled->value = 1; + $entity->title->value = trim($definition['title']); + $entity->description->value = trim($definition['description']); + $entity->menu_name->value = $definition['menu_name']; + $entity->parent->value = $definition['parent']; + $entity->weight->value = isset($definition['weight']) ? $definition['weight'] : 0; + } + else { + // Create a new menu_link_content entity. + $entity = entity_create('menu_link_content', array( + 'title' => trim($definition['title']), + 'description' => trim($definition['description']), + 'link' => ['uri' => 'entity:node/' . $node->id()], + 'menu_name' => $definition['menu_name'], + 'parent' => $definition['parent'], + 'weight' => isset($definition['weight']) ? $definition['weight'] : 0, + 'enabled' => 1, + 'langcode' => $node->getUntranslated()->language()->getId(), + )); } + $entity->save(); } /** @@ -196,70 +175,73 @@ function menu_ui_node_predelete(EntityInterface $node) { } /** - * Implements hook_node_prepare_form(). + * Returns the definition for a menu link for the given node. + * + * @param \Drupal\node\NodeInterface $node + * The node entity. + * + * @return array + * A definition array that matches the form structure. */ -function menu_ui_node_prepare_form(NodeInterface $node, $operation, FormStateInterface $form_state) { - if (!$form_state->get('menu_link_definition')) { - // Prepare the node for the edit form so that $node->menu always exists. - /** @var \Drupal\node\NodeTypeInterface $node_type */ - $node_type = $node->type->entity; - $menu_name = strtok($node_type->getThirdPartySetting('menu_ui', 'parent', 'main:'), ':'); - $definition = FALSE; - if ($node->id()) { - $id = FALSE; - // Give priority to the default menu - $type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', array('main')); - if (in_array($menu_name, $type_menus)) { - $query = \Drupal::entityQuery('menu_link_content') - // @todo Use link.uri once https://www.drupal.org/node/2391217 is in. - ->condition('link__uri', 'node/' . $node->id()) - ->condition('menu_name', $menu_name) - ->sort('id', 'ASC') - ->range(0, 1); - $result = $query->execute(); +function menu_ui_get_definition(NodeInterface $node) { + // Prepare the definition for the edit form. + /** @var \Drupal\node\NodeTypeInterface $node_type */ + $node_type = $node->type->entity; + $menu_name = strtok($node_type->getThirdPartySetting('menu_ui', 'parent', 'main:'), ':'); + $definition = FALSE; + if ($node->id()) { + $id = FALSE; + // Give priority to the default menu + $type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', array('main')); + if (in_array($menu_name, $type_menus)) { + $query = \Drupal::entityQuery('menu_link_content') + // @todo Use link.uri once https://www.drupal.org/node/2391217 is in. + ->condition('link__uri', 'node/' . $node->id()) + ->condition('menu_name', $menu_name) + ->sort('id', 'ASC') + ->range(0, 1); + $result = $query->execute(); - $id = (!empty($result)) ? reset($result) : FALSE; - } - // Check all allowed menus if a link does not exist in the default menu. - if (!$id && !empty($type_menus)) { - $query = \Drupal::entityQuery('menu_link_content') - // @todo Use link.uri once https://www.drupal.org/node/2391217 is in. - ->condition('link__uri', 'entity:node/' . $node->id()) - ->condition('menu_name', array_values($type_menus), 'IN') - ->sort('id', 'ASC') - ->range(0, 1); - $result = $query->execute(); - - $id = (!empty($result)) ? reset($result) : FALSE; - } - if ($id) { - $menu_link = MenuLinkContent::load($id); - $definition = array( - 'entity_id' => $menu_link->id(), - 'id' => $menu_link->getPluginId(), - 'title' => $menu_link->getTitle(), - 'description' => $menu_link->getDescription(), - 'menu_name' => $menu_link->getMenuName(), - 'parent' => $menu_link->getParentId(), - 'weight' => $menu_link->getWeight(), - ); - } + $id = (!empty($result)) ? reset($result) : FALSE; } + // Check all allowed menus if a link does not exist in the default menu. + if (!$id && !empty($type_menus)) { + $query = \Drupal::entityQuery('menu_link_content') + // @todo Use link.uri once https://www.drupal.org/node/2391217 is in. + ->condition('link__uri', 'entity:node/' . $node->id()) + ->condition('menu_name', array_values($type_menus), 'IN') + ->sort('id', 'ASC') + ->range(0, 1); + $result = $query->execute(); - if (!$definition) { + $id = (!empty($result)) ? reset($result) : FALSE; + } + if ($id) { + $menu_link = MenuLinkContent::load($id); $definition = array( - 'entity_id' => 0, - 'id' => '', - 'title' => '', - 'description' => '', - 'menu_name' => $menu_name, - 'parent' => '', - 'weight' => 0, + 'entity_id' => $menu_link->id(), + 'id' => $menu_link->getPluginId(), + 'title' => $menu_link->getTitle(), + 'description' => $menu_link->getDescription(), + 'menu_name' => $menu_link->getMenuName(), + 'parent' => $menu_link->getParentId(), + 'weight' => $menu_link->getWeight(), ); } - // Set default values. - $form_state->set('menu_link_definition', $definition); } + + if (!$definition) { + $definition = array( + 'entity_id' => 0, + 'id' => '', + 'title' => '', + 'description' => '', + 'menu_name' => $menu_name, + 'parent' => '', + 'weight' => 0, + ); + } + return $definition; } /** @@ -267,13 +249,13 @@ function menu_ui_node_prepare_form(NodeInterface $node, $operation, FormStateInt * * Adds menu item fields to the node form. * - * @see menu_ui_node_submit() + * @see menu_ui_form_node_form_submit() */ function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) { // Generate a list of possible parents (not including this link or descendants). // @todo This must be handled in a #process handler. $node = $form_state->getFormObject()->getEntity(); - $definition = $form_state->get('menu_link_definition'); + $definition = menu_ui_get_definition($node); /** @var \Drupal\node\NodeTypeInterface $node_type */ $node_type = $node->type->entity; /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */ @@ -353,14 +335,16 @@ function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) { '#default_value' => $definition['weight'], '#description' => t('Menu links with lower weights are displayed before links with higher weights.'), ); + $form['actions']['submit']['#submit'][] = 'menu_ui_form_node_form_submit'; } /** - * Implements hook_node_submit(). + * Form submission handler for menu item field on the node form. * * @see menu_ui_form_node_form_alter() */ -function menu_ui_node_submit(EntityInterface $node, $form, FormStateInterface $form_state) { +function menu_ui_form_node_form_submit($form, FormStateInterface $form_state) { + $node = $form_state->getFormObject()->getEntity(); if (!$form_state->isValueEmpty('menu')) { $definition = $form_state->getValue('menu'); if (empty($definition['enabled'])) { @@ -377,11 +361,7 @@ function menu_ui_node_submit(EntityInterface $node, $form, FormStateInterface $f $definition['menu_name'] = $menu_name; $definition['parent'] = $parent; } - // @todo Figure out how to save this data without adding non-Field API - // properties to the node entity. https://www.drupal.org/node/2310173 - // We have to tack this onto the node so we can save it later when we - // have a node ID for any new node. - $node->menu = $definition; + menu_ui_node_save($node, $definition); } } } diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php index 9ae46d6..f04de79 100644 --- a/core/modules/node/node.api.php +++ b/core/modules/node/node.api.php @@ -409,65 +409,6 @@ function hook_node_update_index(\Drupal\node\NodeInterface $node, $langcode) { } /** - * Perform node validation before a node is created or updated. - * - * This hook is invoked from NodeForm::validate(), after a user has - * finished editing the node and is previewing or submitting it. It is invoked - * at the end of all the standard validation steps. - * - * To indicate a validation error, use $form_state->setErrorByName(). - * - * Note: Changes made to the $node object within your hook implementation will - * have no effect. The preferred method to change a node's content is to use - * hook_node_presave() instead. If it is really necessary to change the node at - * the validate stage, you can use setValueForElement(). - * - * @param \Drupal\node\NodeInterface $node - * The node being validated. - * @param $form - * The form being used to edit the node. - * @param $form_state - * The current state of the form. - * - * @ingroup entity_crud - */ -function hook_node_validate(\Drupal\node\NodeInterface $node, $form, \Drupal\Core\Form\FormStateInterface $form_state) { - if (isset($node->end) && isset($node->start)) { - if ($node->start > $node->end) { - $form_state->setErrorByName('time', t('An event may not end before it starts.')); - } - } -} - -/** - * Act on a node after validated form values have been copied to it. - * - * This hook is invoked when a node form is submitted with either the "Save" or - * "Preview" button, after form values have been copied to the form state's node - * object, but before the node is saved or previewed. It is a chance for modules - * to adjust the node's properties from what they are simply after a copy from - * $form_state->getValues(). This hook is intended for adjusting non-field-related - * properties. - * - * @param \Drupal\node\NodeInterface $node - * The node entity being updated in response to a form submission. - * @param $form - * The form being used to edit the node. - * @param $form_state - * The current state of the form. - * - * @ingroup entity_crud - */ -function hook_node_submit(\Drupal\node\NodeInterface $node, $form, \Drupal\Core\Form\FormStateInterface $form_state) { - // Decompose the selected menu parent option into 'menu_name' and 'parent', if - // the form used the default parent selection widget. - $parent = $form_state->getValue(array('menu', 'parent')); - if (!empty($parent)) { - list($node->menu['menu_name'], $node->menu['parent']) = explode(':', $parent); - } -} - -/** * Provide additional methods of scoring for core search results for nodes. * * A node's search score is used to rank it among other nodes matched by the diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php index fb8daa9..fda9fdb 100644 --- a/core/modules/node/src/NodeForm.php +++ b/core/modules/node/src/NodeForm.php @@ -293,14 +293,6 @@ public function validate(array $form, FormStateInterface $form_state) { $form_state->setErrorByName('changed', $this->t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.')); } - // Invoke hook_node_validate() for validation needed by modules. - // Can't use \Drupal::moduleHandler()->invokeAll(), because $form_state must - // be receivable by reference. - foreach (\Drupal::moduleHandler()->getImplementations('node_validate') as $module) { - $function = $module . '_node_validate'; - $function($node, $form, $form_state); - } - parent::validate($form, $form_state); } @@ -328,12 +320,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { else { $node->setNewRevision(FALSE); } - - $node->validated = TRUE; - foreach (\Drupal::moduleHandler()->getImplementations('node_submit') as $module) { - $function = $module . '_node_submit'; - $function($node, $form, $form_state); - } } /** diff --git a/core/modules/node/src/Tests/NodeSaveTest.php b/core/modules/node/src/Tests/NodeSaveTest.php index 068eaae..b850cb4 100644 --- a/core/modules/node/src/Tests/NodeSaveTest.php +++ b/core/modules/node/src/Tests/NodeSaveTest.php @@ -63,8 +63,7 @@ function testImport() { $node = entity_create('node', $node); $node->enforceIsNew(); - // Verify that node_submit did not overwrite the user ID. - $this->assertEqual($node->getOwnerId(), $this->webUser->id(), 'Function node_submit() preserves user ID'); + $this->assertEqual($node->getOwnerId(), $this->webUser->id()); $node->save(); // Test the import. diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index ed04686..de42abd 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -152,7 +152,6 @@ * * Some specific entity types have additional hooks that are run during * various steps in the process: - * - Node entities: hook_node_validate() and hook_submit(). * * @section delete Delete operations * To delete one or more entities, load them and then delete them: