diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php new file mode 100644 index 0000000..ba994b7 --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php @@ -0,0 +1,103 @@ + 'textfield', + '#title' => t('Title'), + '#default_value' => $menu->label(), + '#required' => TRUE, + // The title of a system menu cannot be altered. + '#access' => !isset($system_menus[$menu->id()]), + ); + $form['id'] = array( + '#type' => 'machine_name', + '#title' => t('Menu name'), + '#default_value' => $menu->id(), + '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI, + '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'), + '#machine_name' => array( + 'exists' => 'menu_edit_menu_name_exists', + 'source' => array('label'), + 'replace_pattern' => '[^a-z0-9-]+', + 'replace' => '-', + ), + // A menu's machine name cannot be changed. + '#disabled' => !$menu->isNew() || isset($system_menus[$menu->id()]), + ); + $form['description'] = array( + '#type' => 'textarea', + '#title' => t('Description'), + '#default_value' => $menu->description, + ); + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + '#button_type' => 'primary', + ); + // Only custom menus may be deleted. + $form['actions']['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + '#access' => $menu->isNew() && !isset($system_menus[$menu->id()]), + ); + + return $form; + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::save(). + */ + public function save(array $form, array &$form_state) { + $menu = $this->getEntity($form_state); + + if ($menu->isNew()) { + // Add 'menu-' to the menu name to help avoid name-space conflicts. + $menu->set('id', 'menu-' . $menu->id()); + } + + $status = $menu->save(); + + $uri = $menu->uri(); + if ($status == SAVED_UPDATED) { + drupal_set_message(t('Menu %label has been updated.', array('%label' => $menu->label()))); + watchdog('contact', 'Menu %label has been updated.', array('%label' => $menu->label()), WATCHDOG_NOTICE, l(t('Edit'), $uri['path'] . '/edit')); + } + else { + drupal_set_message(t('Menu %label has been added.', array('%label' => $menu->label()))); + watchdog('contact', 'Menu %label has been added.', array('%label' => $menu->label()), WATCHDOG_NOTICE, l(t('Edit'), $uri['path'] . '/edit')); + } + + $form_state['redirect'] = 'admin/structure/menu/manage/' . $menu->id(); + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::delete(). + */ + public function delete(array $form, array &$form_state) { + $menu = $this->getEntity($form_state); + $form_state['redirect'] = 'admin/structure/menu/manage/' . $menu->id() . '/delete'; + } + +} diff --git a/core/modules/menu/lib/Drupal/menu/MenuListController.php b/core/modules/menu/lib/Drupal/menu/MenuListController.php index 1ccf212..f20708e 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuListController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuListController.php @@ -19,6 +19,7 @@ class MenuListController extends ConfigEntityListController { */ public function buildHeader() { $row['title'] = t('Title'); + $row['description'] = t('Description'); $row['operations'] = t('Operations'); return $row; } @@ -27,14 +28,8 @@ public function buildHeader() { * Overrides \Drupal\Core\Entity\EntityListController::buildRow(). */ public function buildRow(EntityInterface $entity) { - $row['title'] = array( - 'data' => array( - '#theme' => 'menu_admin_overview', - '#label' => $entity->label(), - '#id' => $entity->id(), - '#description' => $entity->description, - ), - ); + $row['title'] = check_plain($entity->label()); + $row['description'] = filter_xss_admin($entity->description); $row['operations']['data'] = $this->buildOperations($entity); return $row; } diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index 01242c0..b5d4c5d 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -115,12 +115,12 @@ function addCustomMenuCRUD() { $menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); $label = $this->randomName(16); - $menu = array( + $menu = entity_create('menu', array( 'id' => $menu_name, 'label' => $label, 'description' => 'Description text', - ); - menu_save($menu); + )); + $menu->save(); // Assert the new menu. $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit'); @@ -128,8 +128,8 @@ function addCustomMenuCRUD() { // Edit the menu. $new_label = $this->randomName(16); - $menu['label'] = $new_label; - menu_save($menu); + $menu->set('label', $new_label); + $menu->save(); $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit'); $this->assertRaw($new_label, 'Custom menu was edited.'); } diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc index 961be26..1962ce3 100644 --- a/core/modules/menu/menu.admin.inc +++ b/core/modules/menu/menu.admin.inc @@ -16,19 +16,32 @@ function menu_overview_page() { } /** - * Returns HTML for a menu title and description for the menu overview page. + * Page callback: Presents the menu creation form. * - * @param $variables - * An associative array containing: - * - id: The menu's machine name. - * - label: The menu's label. - * - description: The menu's description. + * @return array + * A form array as expected by drupal_render(). * - * @ingroup themeable + * @see menu_menu() + */ +function menu_menu_add() { + $menu = entity_create('menu', array()); + return entity_get_form($menu); +} + +/** + * Page callback: Presents the menu edit form. + * + * @param \Drupal\system\Plugin\Core\Entity\Menu $menu + * The menu to edit. + * + * @return array + * A form array as expected by drupal_render(). + * + * @see menu_menu() */ -function theme_menu_admin_overview($variables) { - return check_plain($variables['label']) . - '
' . filter_xss_admin($variables['description']) . '
'; +function menu_menu_edit(Menu $menu) { + drupal_set_title(t('Edit menu %label', array('%label' => $menu->label())), PASS_THROUGH); + return entity_get_form($menu); } /** @@ -450,76 +463,6 @@ function menu_edit_item_submit($form, &$form_state) { } /** - * Menu callback; Build the form that handles the adding/editing of a custom menu. - */ -function menu_edit_menu($form, &$form_state, $type, $menu = NULL) { - $system_menus = menu_list_system_menus(); - if (!isset($menu)) { - $menu = entity_create('menu', array()); - } - // Allow menu_edit_menu_submit() and other form submit handlers to determine - // whether the menu already exists. - $form['#insert'] = $menu->isNew(); - $form['old_name'] = array( - '#type' => 'value', - '#value' => $menu->getOriginalID(), - ); - - $form['label'] = array( - '#type' => 'textfield', - '#title' => t('Title'), - '#default_value' => $menu->label(), - '#required' => TRUE, - // The title of a system menu cannot be altered. - '#access' => !isset($system_menus[$menu->id()]), - ); - - $form['id'] = array( - '#type' => 'machine_name', - '#title' => t('Menu name'), - '#default_value' => $menu->id(), - '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI, - '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'), - '#machine_name' => array( - 'exists' => 'menu_edit_menu_name_exists', - 'source' => array('label'), - 'replace_pattern' => '[^a-z0-9-]+', - 'replace' => '-', - ), - // A menu's machine name cannot be changed. - '#disabled' => !$menu->isNew() || isset($system_menus[$menu->id()]), - ); - - $form['description'] = array( - '#type' => 'textarea', - '#title' => t('Description'), - '#default_value' => $menu->description, - ); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#button_type' => 'primary', - ); - // Only custom menus may be deleted. - $form['actions']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - '#access' => $type == 'edit' && !isset($system_menus[$menu->id()]), - '#submit' => array('menu_custom_delete_submit'), - ); - - return $form; -} - -/** - * Submit function for the 'Delete' button on the menu editing form. - */ -function menu_custom_delete_submit($form, &$form_state) { - $form_state['redirect'] = 'admin/structure/menu/manage/' . $form_state['values']['id'] . '/delete'; -} - -/** * Menu callback; check access and get a confirm form for deletion of a custom menu. */ function menu_delete_menu_page($menu) { @@ -571,7 +514,7 @@ function menu_delete_menu_confirm_submit($form, &$form_state) { } // Delete the custom menu and all its menu links. - menu_delete($menu); + $menu->delete(); $t_args = array('%title' => $menu->label()); drupal_set_message(t('The custom menu %title has been deleted.', $t_args)); diff --git a/core/modules/menu/menu.api.php b/core/modules/menu/menu.api.php index 3f3818e..95926a6 100644 --- a/core/modules/menu/menu.api.php +++ b/core/modules/menu/menu.api.php @@ -17,11 +17,8 @@ * Contributed modules may use the information to perform actions based on the * information entered into the menu system. * - * @param $menu - * An array representing a custom menu: - * - menu_name: The unique name of the custom menu. - * - title: The human readable menu title. - * - description: The custom menu description. + * @param \Drupal\system\Plugin\Core\Entity\Menu $menu + * A menu entity. * * @see hook_menu_update() * @see hook_menu_delete() @@ -29,7 +26,7 @@ function hook_menu_insert($menu) { // For example, we track available menus in a variable. $my_menus = variable_get('my_module_menus', array()); - $my_menus[$menu['menu_name']] = $menu['menu_name']; + $my_menus[$menu->id()] = $menu->id(); variable_set('my_module_menus', $my_menus); } @@ -40,13 +37,8 @@ function hook_menu_insert($menu) { * Contributed modules may use the information to perform actions based on the * information entered into the menu system. * - * @param $menu - * An array representing a custom menu: - * - menu_name: The unique name of the custom menu. - * - title: The human readable menu title. - * - description: The custom menu description. - * - old_name: The current 'menu_name'. Note that internal menu names cannot - * be changed after initial creation. + * @param \Drupal\system\Plugin\Core\Entity\Menu $menu + * A menu entity. * * @see hook_menu_insert() * @see hook_menu_delete() @@ -54,7 +46,7 @@ function hook_menu_insert($menu) { function hook_menu_update($menu) { // For example, we track available menus in a variable. $my_menus = variable_get('my_module_menus', array()); - $my_menus[$menu['menu_name']] = $menu['menu_name']; + $my_menus[$menu->id()] = $menu->id(); variable_set('my_module_menus', $my_menus); } @@ -66,11 +58,8 @@ function hook_menu_update($menu) { * information to perform actions based on the information entered into the menu * system. * - * @param $link - * An array representing a custom menu: - * - menu_name: The unique name of the custom menu. - * - title: The human readable menu title. - * - description: The custom menu description. + * @param \Drupal\system\Plugin\Core\Entity\Menu $menu + * A menu entity. * * @see hook_menu_insert() * @see hook_menu_update() @@ -78,7 +67,7 @@ function hook_menu_update($menu) { function hook_menu_delete($menu) { // Delete the record from our variable. $my_menus = variable_get('my_module_menus', array()); - unset($my_menus[$menu['menu_name']]); + unset($my_menus[$menu->id()]); variable_set('my_module_menus', $my_menus); } diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index 154f3b1..3d4a360 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -83,8 +83,7 @@ function menu_menu() { ); $items['admin/structure/menu/add'] = array( 'title' => 'Add menu', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_menu', 'add'), + 'page callback' => 'menu_menu_add', 'access arguments' => array('administer menu'), 'type' => MENU_LOCAL_ACTION, 'file' => 'menu.admin.inc', @@ -123,8 +122,8 @@ function menu_menu() { ); $items['admin/structure/menu/manage/%menu/edit'] = array( 'title' => 'Edit menu', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_menu', 'edit', 4), + 'page callback' => 'menu_menu_edit', + 'page arguments' => array(4), 'access arguments' => array('administer menu'), 'type' => MENU_LOCAL_TASK, 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, @@ -167,6 +166,9 @@ function menu_menu() { function menu_entity_info_alter(&$entity_info) { $entity_info['menu']['list_controller_class'] = 'Drupal\menu\MenuListController'; $entity_info['menu']['uri_callback'] = 'menu_uri'; + $entity_info['menu']['form_controller_class'] = array( + 'default' => 'Drupal\menu\MenuFormController', + ); } /** @@ -190,10 +192,6 @@ function menu_theme() { 'file' => 'menu.admin.inc', 'render element' => 'form', ), - 'menu_admin_overview' => array( - 'file' => 'menu.admin.inc', - 'variables' => array('label' => NULL, 'id' => NULL, 'description' => NULL), - ), ); } @@ -239,76 +237,43 @@ function menu_load($menu_name) { } /** - * Save a custom menu. - * - * @param \Drupal\system\Plugin\Core\Entity\Menu $menu - * An array representing a custom menu: - * - menu_name: The unique name of the custom menu (composed of lowercase - * letters, numbers, and hyphens). - * - title: The human readable menu title. - * - description: The custom menu description. - * - * Modules should always pass a fully populated $menu when saving a custom - * menu, so other modules are able to output proper status or watchdog messages. - * - * @see menu_load() + * Implements hook_menu_insert() */ -function menu_save($menu_array) { - $menu = entity_create('menu', $menu_array); - $status = $menu->save(); +function menu_menu_insert(Menu $menu) { menu_cache_clear_all(); // Invalidate the block cache to update menu-based derivatives. if (module_exists('block')) { drupal_container()->get('plugin.manager.block')->clearCachedDefinitions(); } + // Make sure the menu is present in the active menus variable so that its + // items may appear in the menu active trail. + // See menu_set_active_menu_names(). + $config = config('system.menu'); + + $active_menus = $config->get('active_menus_default') ?: array_keys(menu_get_menus()); + if (!in_array($menu->id(), $active_menus)) { + $active_menus[] = $menu->id(); + $config + ->set('active_menus_default', $active_menus) + ->save(); + } +} - switch ($status) { - case SAVED_NEW: - // Make sure the menu is present in the active menus variable so that its - // items may appear in the menu active trail. - // See menu_set_active_menu_names(). - $config = config('system.menu'); - - $active_menus = $config->get('active_menus_default') ?: array_keys(menu_get_menus()); - if (!in_array($menu->id(), $active_menus)) { - $active_menus[] = $menu->id(); - $config->set('active_menus_default', $active_menus); - } - - module_invoke_all('menu_insert', $menu); - break; - - case SAVED_UPDATED: - module_invoke_all('menu_update', $menu); - break; +/** + * Implements hook_menu_update(). + */ +function menu_menu_update(Menu $menu) { + menu_cache_clear_all(); + // Invalidate the block cache to update menu-based derivatives. + if (module_exists('block')) { + drupal_container()->get('plugin.manager.block')->clearCachedDefinitions(); } } /** - * Delete a custom menu and all contained links. - * - * Note that this function deletes all menu links in a custom menu. While menu - * links derived from router paths may be restored by rebuilding the menu, all - * customized and custom links will be irreversibly gone. Therefore, this - * function should usually be called from a user interface (form submit) handler - * only, which allows the user to confirm the action. - * - * @param \Drupal\system\Plugin\Core\Entity\Menu $menu - * An array representing a custom menu: - * - menu_name: The unique name of the custom menu. - * - title: The human readable menu title. - * - description: The custom menu description. - * - * Modules should always pass a fully populated $menu when deleting a custom - * menu, so other modules are able to output proper status or watchdog messages. - * - * @see menu_load() - * - * menu_delete_links() will take care of clearing the page cache. Other modules - * should take care of their menu-related data by implementing - * hook_menu_delete(). + * Implements hook_menu_predelete(). */ -function menu_delete($menu) { +function menu_menu_predelete(Menu $menu) { // Delete all links from the menu. menu_delete_links($menu->id()); @@ -320,16 +285,17 @@ function menu_delete($menu) { variable_set('menu_default_active_menus', $active_menus); } } +} - // Delete the custom menu. - $menu->delete(); - +/** + * Implements hook_menu_delete(). + */ +function menu_menu_delete(Menu $menu) { menu_cache_clear_all(); // Invalidate the block cache to update menu-based derivatives. if (module_exists('block')) { drupal_container()->get('plugin.manager.block')->clearCachedDefinitions(); } - module_invoke_all('menu_delete', $menu); } /**