diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 6492b10..3710eae 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2641,7 +2641,6 @@ function menu_reset_static_cache() { drupal_static_reset('menu_tree'); drupal_static_reset('menu_tree_all_data'); drupal_static_reset('menu_tree_page_data'); - drupal_static_reset('menu_load_all'); drupal_static_reset('menu_link_get_preferred'); } diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 26bcb25..a744f93 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -1039,11 +1039,11 @@ function block_user_role_delete($role) { function block_menu_delete($menu) { db_delete('block') ->condition('module', 'menu') - ->condition('delta', $menu['menu_name']) + ->condition('delta', $menu->id()) ->execute(); db_delete('block_role') ->condition('module', 'menu') - ->condition('delta', $menu['menu_name']) + ->condition('delta', $menu->id()) ->execute(); } diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index a04c0dd..dd2a1cc 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -76,8 +76,8 @@ function field_ui_menu() { // Extract path information from the bundle. $path = $bundle_info['admin']['path']; // Different bundles can appear on the same path (e.g. %node_type and - // %comment_node_type). To allow field_ui_menu_load() to extract the - // actual bundle object from the translated menu router path + // %comment_node_type). To allow field_ui_instance_load() to extract + // the actual bundle object from the translated menu router path // arguments, we need to identify the argument position of the bundle // name string ('bundle argument') and pass that position to the menu // loader. The position needs to be casted into a string; otherwise it @@ -90,7 +90,7 @@ function field_ui_menu() { $bundle_arg = $bundle_name; $bundle_pos = '0'; } - // This is the position of the %field_ui_menu placeholder in the + // This is the position of the %field_ui_instance placeholder in the // items below. $field_position = count(explode('/', $path)) + 1; @@ -109,15 +109,15 @@ function field_ui_menu() { 'weight' => 1, 'file' => 'field_ui.admin.inc', ) + $access; - $items["$path/fields/%field_ui_menu"] = array( + $items["$path/fields/%field_ui_instance"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title callback' => 'field_ui_menu_title', + 'title callback' => 'field_ui_instance_title', 'title arguments' => array($field_position), 'page callback' => 'drupal_get_form', 'page arguments' => array('field_ui_field_edit_form', $field_position), 'file' => 'field_ui.admin.inc', ) + $access; - $items["$path/fields/%field_ui_menu/edit"] = array( + $items["$path/fields/%field_ui_instance/edit"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Edit', 'page callback' => 'drupal_get_form', @@ -125,7 +125,7 @@ function field_ui_menu() { 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'field_ui.admin.inc', ) + $access; - $items["$path/fields/%field_ui_menu/field-settings"] = array( + $items["$path/fields/%field_ui_instance/field-settings"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Field settings', 'page callback' => 'drupal_get_form', @@ -133,7 +133,7 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'field_ui.admin.inc', ) + $access; - $items["$path/fields/%field_ui_menu/widget-type"] = array( + $items["$path/fields/%field_ui_instance/widget-type"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Widget type', 'page callback' => 'drupal_get_form', @@ -141,7 +141,7 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'field_ui.admin.inc', ) + $access; - $items["$path/fields/%field_ui_menu/delete"] = array( + $items["$path/fields/%field_ui_instance/delete"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Delete', 'page callback' => 'drupal_get_form', @@ -211,12 +211,12 @@ function field_ui_menu() { * * @ingroup field */ -function field_ui_menu_load($field_name, $entity_type, $bundle_name, $bundle_pos, $map) { +function field_ui_instance_load($field_name, $entity_type, $bundle_name, $bundle_pos, $map) { // Extract the actual bundle name from the translated argument map. // The menu router path to manage fields of an entity can be shared among // multiple bundles. For example: - // - admin/structure/types/manage/%node_type/fields/%field_ui_menu - // - admin/structure/types/manage/%comment_node_type/fields/%field_ui_menu + // - admin/structure/types/manage/%node_type/fields/%field_ui_instance + // - admin/structure/types/manage/%comment_node_type/fields/%field_ui_instance // The menu system will automatically load the correct bundle depending on the // actual path arguments, but this menu loader function only receives the node // type string as $bundle_name, which is not the bundle name for comments. @@ -242,7 +242,7 @@ function field_ui_menu_load($field_name, $entity_type, $bundle_name, $bundle_pos * * @see field_ui_menu() */ -function field_ui_menu_title($instance) { +function field_ui_instance_title($instance) { return $instance['label']; } diff --git a/core/modules/menu/config/menu.menu.account.yml b/core/modules/menu/config/menu.menu.account.yml new file mode 100644 index 0000000..6be2706 --- /dev/null +++ b/core/modules/menu/config/menu.menu.account.yml @@ -0,0 +1,3 @@ +id: account +label: User account menu +description: Links related to the user account. diff --git a/core/modules/menu/config/menu.menu.admin.yml b/core/modules/menu/config/menu.menu.admin.yml new file mode 100644 index 0000000..5435da5 --- /dev/null +++ b/core/modules/menu/config/menu.menu.admin.yml @@ -0,0 +1,3 @@ +id: admin +label: Administration +description: Contains links to administrative tasks. diff --git a/core/modules/menu/config/menu.menu.main.yml b/core/modules/menu/config/menu.menu.main.yml new file mode 100644 index 0000000..3dfe975 --- /dev/null +++ b/core/modules/menu/config/menu.menu.main.yml @@ -0,0 +1,3 @@ +id: main +label: Main navigation +description: Use this for linking to the main site sections. diff --git a/core/modules/menu/config/menu.menu.tools.yml b/core/modules/menu/config/menu.menu.tools.yml new file mode 100644 index 0000000..3f15287 --- /dev/null +++ b/core/modules/menu/config/menu.menu.tools.yml @@ -0,0 +1,3 @@ +id: tools +label: Tools +description: Contains links for site visitors. Some modules add their links here. diff --git a/core/modules/menu/lib/Drupal/menu/MenuListController.php b/core/modules/menu/lib/Drupal/menu/MenuListController.php new file mode 100644 index 0000000..806ef6f --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/MenuListController.php @@ -0,0 +1,67 @@ + array( + '#theme' => 'menu_admin_overview', + '#label' => $entity->label(), + '#id' => $entity->id(), + '#description' => $entity->description, + ), + ); + $row['operations']['data'] = $this->buildOperations($entity); + return $row; + } + + /** + * Implements Drupal\Core\Entity\EntityListController::getOperations(); + */ + public function getOperations(EntityInterface $menu) { + $uri = $menu->uri(); + $path = $uri['path']; + + $operations['list'] = array( + 'title' => t('list links'), + 'href' => $path, + 'weight' => 0, + ); + $operations['edit'] = array( + 'title' => t('edit menu'), + 'href' => $path . '/edit', + 'weight' => 5, + ); + $operations['add'] = array( + 'title' => t('add link'), + 'href' => $path . '/add', + 'weight' => 10, + ); + return $operations; + } + +} diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index e0b9b92..caf8eaf 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -102,8 +102,8 @@ function doStandardMenuTests() { */ function doCustomMenuTests() { $this->menu = $this->addCustomMenu(); - $this->doMenuTests($this->menu['menu_name']); - $this->addInvalidMenuLink($this->menu['menu_name']); + $this->doMenuTests($this->menu->id()); + $this->addInvalidMenuLink($this->menu->id()); $this->addCustomMenuCRUD(); } @@ -113,25 +113,25 @@ function doCustomMenuTests() { function addCustomMenuCRUD() { // Add a new custom menu. $menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); - $title = $this->randomName(16); + $label = $this->randomName(16); $menu = array( - 'menu_name' => $menu_name, - 'title' => $title, + 'id' => $menu_name, + 'label' => $label, 'description' => 'Description text', ); menu_save($menu); // Assert the new menu. $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit'); - $this->assertRaw($title, 'Custom menu was added.'); + $this->assertRaw($label, 'Custom menu was added.'); // Edit the menu. - $new_title = $this->randomName(16); - $menu['title'] = $new_title; + $new_label = $this->randomName(16); + $menu['label'] = $new_label; menu_save($menu); $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit'); - $this->assertRaw($new_title, 'Custom menu was edited.'); + $this->assertRaw($new_label, 'Custom menu was edited.'); } /** @@ -143,11 +143,11 @@ function addCustomMenu() { // Try adding a menu using a menu_name that is too long. $this->drupalGet('admin/structure/menu/add'); $menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1); - $title = $this->randomName(16); + $label = $this->randomName(16); $edit = array( - 'menu_name' => $menu_name, + 'id' => $menu_name, 'description' => '', - 'title' => $title, + 'label' => $label, ); $this->drupalPost('admin/structure/menu/add', $edit, t('Save')); @@ -160,7 +160,7 @@ function addCustomMenu() { // Change the menu_name so it no longer exceeds the maximum length. $menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); - $edit['menu_name'] = $menu_name; + $edit['id'] = $menu_name; $this->drupalPost('admin/structure/menu/add', $edit, t('Save')); // Verify that no validation error is given for menu_name length. @@ -172,7 +172,7 @@ function addCustomMenu() { // Unlike most other modules, there is no confirmation message displayed. $this->drupalGet('admin/structure/menu'); - $this->assertText($title, 'Menu created'); + $this->assertText($label, 'Menu created'); // Enable the custom menu block. $menu_name = 'menu-' . $menu_name; // Drupal prepends the name with 'menu-'. @@ -191,13 +191,13 @@ function addCustomMenu() { * @param string $menu_name Custom menu name. */ function deleteCustomMenu($menu) { - $menu_name = $this->menu['menu_name']; - $title = $this->menu['title']; + $menu_name = $this->menu->id(); + $label = $this->menu->label(); // Delete custom menu. $this->drupalPost("admin/structure/menu/manage/$menu_name/delete", array(), t('Delete')); $this->assertResponse(200); - $this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $title)), 'Custom menu was deleted'); + $this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $label)), 'Custom menu was deleted'); $this->assertFalse(menu_load($menu_name), 'Custom menu was deleted'); // Test if all menu links associated to the menu were removed from database. $result = db_query("SELECT menu_name FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu_name))->fetchField(); diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc index 4a78495..961be26 100644 --- a/core/modules/menu/menu.admin.inc +++ b/core/modules/menu/menu.admin.inc @@ -6,40 +6,13 @@ */ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Drupal\system\Plugin\Core\Entity\Menu; /** * Menu callback which shows an overview page of all the custom menus and their descriptions. */ function menu_overview_page() { - $result = db_query("SELECT * FROM {menu_custom} ORDER BY title", array(), array('fetch' => PDO::FETCH_ASSOC)); - $header = array(t('Title'), t('Operations')); - $rows = array(); - foreach ($result as $menu) { - $row = array(); - $row[] = theme('menu_admin_overview', array('title' => $menu['title'], 'name' => $menu['menu_name'], 'description' => $menu['description'])); - $links = array(); - $links['list'] = array( - 'title' => t('list links'), - 'href' => 'admin/structure/menu/manage/' . $menu['menu_name'], - ); - $links['edit'] = array( - 'title' => t('edit menu'), - 'href' => 'admin/structure/menu/manage/' . $menu['menu_name'] . '/edit', - ); - $links['add'] = array( - 'title' => t('add link'), - 'href' => 'admin/structure/menu/manage/' . $menu['menu_name'] . '/add', - ); - $row[] = array( - 'data' => array( - '#type' => 'operations', - '#links' => $links, - ), - ); - $rows[] = $row; - } - - return theme('table', array('header' => $header, 'rows' => $rows)); + return entity_list_controller('menu')->render(); } /** @@ -47,16 +20,15 @@ function menu_overview_page() { * * @param $variables * An associative array containing: - * - title: The menu's title. + * - id: The menu's machine name. + * - label: The menu's label. * - description: The menu's description. * * @ingroup themeable */ function theme_menu_admin_overview($variables) { - $output = check_plain($variables['title']); - $output .= '
' . filter_xss_admin($variables['description']) . '
'; - - return $output; + return check_plain($variables['label']) . + '
' . filter_xss_admin($variables['description']) . '
'; } /** @@ -73,7 +45,7 @@ function menu_overview_form($form, &$form_state, $menu) { FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.menu_name = :menu ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC"; - $result = db_query($sql, array(':menu' => $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); + $result = db_query($sql, array(':menu' => $menu->id()), array('fetch' => PDO::FETCH_ASSOC)); $links = array(); foreach ($result as $item) { $links[] = $item; @@ -99,7 +71,7 @@ function menu_overview_form($form, &$form_state, $menu) { ); } else { - $form['#empty_text'] = t('There are no menu links yet. Add link.', array('@link' => url('admin/structure/menu/manage/'. $form['#menu']['menu_name'] .'/add'))); + $form['#empty_text'] = t('There are no menu links yet. Add link.', array('@link' => url('admin/structure/menu/manage/'. $form['#menu']->id() .'/add'))); } return $form; } @@ -296,7 +268,7 @@ function theme_menu_overview_form($variables) { function menu_edit_item($form, &$form_state, $type, $item, $menu) { if ($type == 'add' || empty($item)) { // This is an add form, initialize the menu link. - $item = array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu['menu_name'], 'weight' => 0, 'link_path' => '', 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0); + $item = array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu->id(), 'weight' => 0, 'link_path' => '', 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0); } else { // Get the human-readable menu title from the given menu name. @@ -480,51 +452,48 @@ 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 = array()) { +function menu_edit_menu($form, &$form_state, $type, $menu = NULL) { $system_menus = menu_list_system_menus(); - $menu += array( - 'menu_name' => '', - 'old_name' => !empty($menu['menu_name']) ? $menu['menu_name'] : '', - 'title' => '', - 'description' => '', - ); + 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'] = empty($menu['old_name']); + $form['#insert'] = $menu->isNew(); $form['old_name'] = array( '#type' => 'value', - '#value' => $menu['old_name'], + '#value' => $menu->getOriginalID(), ); - $form['title'] = array( + $form['label'] = array( '#type' => 'textfield', '#title' => t('Title'), - '#default_value' => $menu['title'], + '#default_value' => $menu->label(), '#required' => TRUE, // The title of a system menu cannot be altered. - '#access' => !isset($system_menus[$menu['menu_name']]), + '#access' => !isset($system_menus[$menu->id()]), ); - $form['menu_name'] = array( + $form['id'] = array( '#type' => 'machine_name', '#title' => t('Menu name'), - '#default_value' => $menu['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('title'), + 'source' => array('label'), 'replace_pattern' => '[^a-z0-9-]+', 'replace' => '-', ), // A menu's machine name cannot be changed. - '#disabled' => !empty($menu['old_name']) || isset($system_menus[$menu['menu_name']]), + '#disabled' => !$menu->isNew() || isset($system_menus[$menu->id()]), ); $form['description'] = array( '#type' => 'textarea', '#title' => t('Description'), - '#default_value' => $menu['description'], + '#default_value' => $menu->description, ); $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( @@ -536,7 +505,7 @@ function menu_edit_menu($form, &$form_state, $type, $menu = array()) { $form['actions']['delete'] = array( '#type' => 'submit', '#value' => t('Delete'), - '#access' => $type == 'edit' && !isset($system_menus[$menu['menu_name']]), + '#access' => $type == 'edit' && !isset($system_menus[$menu->id()]), '#submit' => array('menu_custom_delete_submit'), ); @@ -547,7 +516,7 @@ function menu_edit_menu($form, &$form_state, $type, $menu = array()) { * 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']['menu_name'] . '/delete'; + $form_state['redirect'] = 'admin/structure/menu/manage/' . $form_state['values']['id'] . '/delete'; } /** @@ -556,7 +525,7 @@ function menu_custom_delete_submit($form, &$form_state) { function menu_delete_menu_page($menu) { // System-defined menus may not be deleted. $system_menus = menu_list_system_menus(); - if (isset($system_menus[$menu['menu_name']])) { + if (isset($system_menus[$menu->id()])) { throw new AccessDeniedHttpException(); } return drupal_get_form('menu_delete_menu_confirm', $menu); @@ -565,15 +534,15 @@ function menu_delete_menu_page($menu) { /** * Build a confirm form for deletion of a custom menu. */ -function menu_delete_menu_confirm($form, &$form_state, $menu) { +function menu_delete_menu_confirm($form, &$form_state, Menu $menu) { $form['#menu'] = $menu; $caption = ''; - $num_links = db_query("SELECT COUNT(*) FROM {menu_links} WHERE menu_name = :menu", array(':menu' => $menu['menu_name']))->fetchField(); + $num_links = db_query("SELECT COUNT(*) FROM {menu_links} WHERE menu_name = :menu", array(':menu' => $menu->id()))->fetchField(); if ($num_links) { - $caption .= '

' . format_plural($num_links, 'Warning: There is currently 1 menu link in %title. It will be deleted (system-defined items will be reset).', 'Warning: There are currently @count menu links in %title. They will be deleted (system-defined links will be reset).', array('%title' => $menu['title'])) . '

'; + $caption .= '

' . format_plural($num_links, 'Warning: There is currently 1 menu link in %title. It will be deleted (system-defined items will be reset).', 'Warning: There are currently @count menu links in %title. They will be deleted (system-defined links will be reset).', array('%title' => $menu->label())) . '

'; } $caption .= '

' . t('This action cannot be undone.') . '

'; - return confirm_form($form, t('Are you sure you want to delete the custom menu %title?', array('%title' => $menu['title'])), 'admin/structure/menu/manage/' . $menu['menu_name'], $caption, t('Delete')); + return confirm_form($form, t('Are you sure you want to delete the custom menu %title?', array('%title' => $menu->label())), 'admin/structure/menu/manage/' . $menu->id(), $caption, t('Delete')); } /** @@ -585,18 +554,18 @@ function menu_delete_menu_confirm_submit($form, &$form_state) { // System-defined menus may not be deleted - only menus defined by this module. $system_menus = menu_list_system_menus(); - if (isset($system_menus[$menu['menu_name']]) || !(db_query("SELECT 1 FROM {menu_custom} WHERE menu_name = :menu", array(':menu' => $menu['menu_name']))->fetchField())) { + if (isset($system_menus[$menu->id()])) { return; } // Reset all the menu links defined by the system via hook_menu(). - $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = 'system' ORDER BY m.number_parts ASC", array(':menu' => $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); + $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = 'system' ORDER BY m.number_parts ASC", array(':menu' => $menu->id()), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $link) { menu_reset_item($link); } // Delete all links to the overview page for this menu. - $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path = :link", array(':link' => 'admin/structure/menu/manage/' . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); + $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path = :link", array(':link' => 'admin/structure/menu/manage/' . $menu->id()), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $link) { menu_link_delete($link['mlid']); } @@ -604,7 +573,7 @@ function menu_delete_menu_confirm_submit($form, &$form_state) { // Delete the custom menu and all its menu links. menu_delete($menu); - $t_args = array('%title' => $menu['title']); + $t_args = array('%title' => $menu->label()); drupal_set_message(t('The custom menu %title has been deleted.', $t_args)); watchdog('menu', 'Deleted custom menu %title and all its menu links.', $t_args, WATCHDOG_NOTICE); } @@ -616,9 +585,9 @@ function menu_delete_menu_confirm_submit($form, &$form_state) { * @see form_validate_machine_name() */ function menu_edit_menu_name_exists($value) { + $custom_exists = entity_load('menu', $value); // 'menu-' is added to the menu name to avoid name-space conflicts. $value = 'menu-' . $value; - $custom_exists = db_query_range('SELECT 1 FROM {menu_custom} WHERE menu_name = :menu', 0, 1, array(':menu' => $value))->fetchField(); $link_exists = db_query_range("SELECT 1 FROM {menu_links} WHERE menu_name = :menu", 0, 1, array(':menu' => $value))->fetchField(); return $custom_exists || $link_exists; @@ -632,9 +601,9 @@ function menu_edit_menu_submit($form, &$form_state) { $path = 'admin/structure/menu/manage/'; if ($form['#insert']) { // Add 'menu-' to the menu name to help avoid name-space conflicts. - $menu['menu_name'] = 'menu-' . $menu['menu_name']; - $link['link_title'] = $menu['title']; - $link['link_path'] = $path . $menu['menu_name']; + $menu['id'] = 'menu-' . $menu['id']; + $link['link_title'] = $menu['label']; + $link['link_path'] = $path . $menu['id']; $link['router_path'] = $path . '%'; $link['module'] = 'menu'; $link['plid'] = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :link AND module = :module", array( @@ -648,15 +617,15 @@ function menu_edit_menu_submit($form, &$form_state) { } else { menu_save($menu); - $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path", array(':path' => $path . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); + $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path", array(':path' => $path . $menu['id']), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $m) { $link = menu_link_load($m['mlid']); - $link['link_title'] = $menu['title']; + $link['link_title'] = $menu['label']; menu_link_save($link); } } drupal_set_message(t('Your configuration has been saved.')); - $form_state['redirect'] = $path . $menu['menu_name']; + $form_state['redirect'] = $path . $menu['id']; } /** diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install index f1a7b05..56d45f3 100644 --- a/core/modules/menu/menu.install +++ b/core/modules/menu/menu.install @@ -6,64 +6,6 @@ */ /** - * Implements hook_schema(). - */ -function menu_schema() { - $schema['menu_custom'] = array( - 'description' => 'Holds definitions for top-level custom menus (for example, Main navigation menu).', - 'fields' => array( - 'menu_name' => array( - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Primary Key: Unique key for menu. This is used as a block delta so length is 32.', - ), - 'title' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Menu title; displayed at top of block.', - 'translatable' => TRUE, - ), - 'description' => array( - 'type' => 'text', - 'not null' => FALSE, - 'description' => 'Menu description.', - 'translatable' => TRUE, - ), - ), - 'primary key' => array('menu_name'), - ); - - return $schema; -} - -/** - * Implements hook_install(). - */ -function menu_install() { - $system_menus = menu_list_system_menus(); - $t = get_t(); - $descriptions = array( - 'tools' => $t('Contains links for site visitors. Some modules add their links here.'), - 'account' => $t('Links related to the user account.'), - 'admin' => $t('Contains links to administrative tasks.'), - 'main' => $t('Use this for linking to the main site sections.'), - 'footer' => $t('Use this for linking to site information.'), - ); - foreach ($system_menus as $menu_name => $title) { - $menu = array( - 'menu_name' => $menu_name, - 'title' => $t($title), - 'description' => $descriptions[$menu_name], - ); - menu_save($menu); - } -} - -/** * Implements hook_uninstall(). */ function menu_uninstall() { @@ -126,3 +68,19 @@ function menu_update_8003() { )); } +/** + * Migrate menus into configuration. + * + * @ingroup config_upgrade + */ +function menu_update_8004() { + $result = db_query('SELECT * FROM {menu_custom}'); + foreach ($result as $menu) { + // Save the config object. + config('menu.menu.' . $menu->menu_name) + ->set('id', $menu->menu_name) + ->set('label', $menu->title) + ->set('description', $menu->description) + ->save(); + } +} diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index 94fb8ef..23d62e2 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -11,9 +11,10 @@ * URLs to be added to the main site navigation menu. */ -use Drupal\node\Plugin\Core\Entity\Node; - use Symfony\Component\HttpFoundation\JsonResponse; +use Drupal\node\Plugin\Core\Entity\Node; +use Drupal\system\Plugin\Core\Entity\Menu; +use Drupal\Core\Config\Entity\ConfigEntityBase; /** * Maximum length of menu name as entered by the user. Database length is 32 @@ -101,7 +102,7 @@ function menu_menu() { 'title' => 'Customize menu', 'page callback' => 'drupal_get_form', 'page arguments' => array('menu_overview_form', 4), - 'title callback' => 'menu_overview_title', + 'title callback' => 'entity_page_label', 'title arguments' => array(4), 'access arguments' => array('administer menu'), 'file' => 'menu.admin.inc', @@ -161,6 +162,13 @@ function menu_menu() { } /** + * Implements hook_entity_info_alter(). + */ +function menu_entity_info_alter(&$entity_info) { + $entity_info['menu']['list_controller_class'] = 'Drupal\menu\MenuListController'; +} + +/** * Implements hook_theme(). */ function menu_theme() { @@ -171,7 +179,7 @@ function menu_theme() { ), 'menu_admin_overview' => array( 'file' => 'menu.admin.inc', - 'variables' => array('title' => NULL, 'name' => NULL, 'description' => NULL), + 'variables' => array('label' => NULL, 'id' => NULL, 'description' => NULL), ), ); } @@ -186,13 +194,13 @@ function menu_enable() { $base_link = db_query("SELECT mlid AS plid, menu_name FROM {menu_links} WHERE link_path = 'admin/structure/menu' AND module = 'system'")->fetchAssoc(); $base_link['router_path'] = 'admin/structure/menu/manage/%'; $base_link['module'] = 'menu'; - $result = db_query("SELECT * FROM {menu_custom}", array(), array('fetch' => PDO::FETCH_ASSOC)); - foreach ($result as $menu) { + $menus = entity_load_multiple('menu'); + foreach ($menus as $menu) { // $link is passed by reference to menu_link_save(), so we make a copy of $base_link. $link = $base_link; $link['mlid'] = 0; - $link['link_title'] = $menu['title']; - $link['link_path'] = 'admin/structure/menu/manage/' . $menu['menu_name']; + $link['link_title'] = $menu->label(); + $link['link_path'] = 'admin/structure/menu/manage/' . $menu->id(); $menu_link = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND plid = :plid", array( ':path' => $link['link_path'], ':plid' => $link['plid'] @@ -206,13 +214,6 @@ function menu_enable() { } /** - * Title callback for the menu overview page and links. - */ -function menu_overview_title($menu) { - return $menu['title']; -} - -/** * Load the data for a single custom menu. * * @param $menu_name @@ -221,34 +222,13 @@ function menu_overview_title($menu) { * Array defining the custom menu, or FALSE if the menu doesn't exist. */ function menu_load($menu_name) { - $all_menus = menu_load_all(); - return isset($all_menus[$menu_name]) ? $all_menus[$menu_name] : FALSE; -} - -/** - * Load all custom menu data. - * - * @return - * Array of custom menu data. - */ -function menu_load_all() { - $custom_menus = &drupal_static(__FUNCTION__); - if (!isset($custom_menus)) { - if ($cached = cache('menu')->get('menu_custom')) { - $custom_menus = $cached->data; - } - else { - $custom_menus = db_query('SELECT * FROM {menu_custom}')->fetchAllAssoc('menu_name', PDO::FETCH_ASSOC); - cache('menu')->set('menu_custom', $custom_menus); - } - } - return $custom_menus; + return entity_load('menu', $menu_name); } /** * Save a custom menu. * - * @param $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). @@ -260,14 +240,9 @@ function menu_load_all() { * * @see menu_load() */ -function menu_save($menu) { - $status = db_merge('menu_custom') - ->key(array('menu_name' => $menu['menu_name'])) - ->fields(array( - 'title' => $menu['title'], - 'description' => $menu['description'], - )) - ->execute(); +function menu_save($menu_array) { + $menu = entity_create('menu', $menu_array); + $status = $menu->save(); menu_cache_clear_all(); switch ($status) { @@ -278,8 +253,8 @@ function menu_save($menu) { $config = config('system.menu'); $active_menus = $config->get('active_menus_default') ?: array_keys(menu_get_menus()); - if (!in_array($menu['menu_name'], $active_menus)) { - $active_menus[] = $menu['menu_name']; + if (!in_array($menu->id(), $active_menus)) { + $active_menus[] = $menu->id(); $config->set('active_menus_default', $active_menus); } @@ -301,7 +276,7 @@ function menu_save($menu) { * function should usually be called from a user interface (form submit) handler * only, which allows the user to confirm the action. * - * @param $menu + * @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. @@ -318,21 +293,19 @@ function menu_save($menu) { */ function menu_delete($menu) { // Delete all links from the menu. - menu_delete_links($menu['menu_name']); + menu_delete_links($menu->id()); // Remove menu from active menus variable. $active_menus = variable_get('menu_default_active_menus', array_keys(menu_get_menus())); foreach ($active_menus as $i => $menu_name) { - if ($menu['menu_name'] == $menu_name) { + if ($menu->id() == $menu_name) { unset($active_menus[$i]); variable_set('menu_default_active_menus', $active_menus); } } // Delete the custom menu. - db_delete('menu_custom') - ->condition('menu_name', $menu['menu_name']) - ->execute(); + $menu->delete(); menu_cache_clear_all(); module_invoke_all('menu_delete', $menu); @@ -801,12 +774,12 @@ function menu_form_node_type_form_alter(&$form, $form_state) { * titles as the values. */ function menu_get_menus($all = TRUE) { - if ($custom_menus = menu_load_all()) { + if ($custom_menus = entity_load_multiple('menu')) { if (!$all) { $custom_menus = array_diff_key($custom_menus, menu_list_system_menus()); } foreach ($custom_menus as $menu_name => $menu) { - $custom_menus[$menu_name] = t($menu['title']); + $custom_menus[$menu_name] = $menu->label(); } asort($custom_menus); } diff --git a/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Menu.php b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Menu.php new file mode 100644 index 0000000..94f957b --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Menu.php @@ -0,0 +1,73 @@ + 'admin/structure/menu/manage/' . $this->id(), + 'options' => array( + 'entity_type' => $this->entityType, + 'entity' => $this, + ), + ); + } + +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 6dd33b1..e9b44ae 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2144,6 +2144,57 @@ function system_data_type_info() { } /** + * Implements hook_config_import_create(). + */ +function system_config_import_create($name, $new_config, $old_config) { + if (strpos($name, 'menu.menu.') !== 0) { + return FALSE; + } + + $menu = entity_create('menu', $new_config->get()); + $menu->save(); + return TRUE; +} + +/** + * Implements hook_config_import_change(). + */ +function system_config_import_change($name, $new_config, $old_config) { + if (strpos($name, 'menu.menu.') !== 0) { + return FALSE; + } + + list(, , $id) = explode('.', $name); + $entity = entity_load('menu', $id); + $entity->original = clone $entity; + foreach ($old_config->get() as $property => $value) { + $entity->original->$property = $value; + } + + // Iterate through each property of the new config, copying it to the menu + // object. + foreach ($new_config->get() as $property => $value) { + $entity->$property = $value; + } + + $entity->save(); + return TRUE; +} + +/** + * Implements hook_config_import_delete(). + */ +function system_config_import_delete($name, $new_config, $old_config) { + if (strpos($name, 'menu.menu.') !== 0) { + return FALSE; + } + + list(, , $id) = explode('.', $name); + entity_delete_multiple('menu', array($id)); + return TRUE; +} + +/** * Menu item access callback - only enabled themes can be accessed. */ function _system_themes_access($theme) {