diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 3ba3b5d..731d185 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -643,7 +643,12 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { // including unserializing all existing link options and running this code // on them, as well as adding validation to menu_link_save(). if (isset($item['options']['attributes']['class']) && is_string($item['options']['attributes']['class'])) { - $item['localized_options']['attributes']['class'] = explode(' ', $item['options']['attributes']['class']); + if ($item instanceof MenuLink) { + $item->localized_options->attributes['class'] = explode(' ', $item->options->attributes['class']); + } + else { + $item['localized_options']['attributes']['class'] = explode(' ', $item['options']['attributes']['class']); + } } // If we are translating the title of a menu link, and its title is the same // as the corresponding router item, then we can use the title information @@ -671,7 +676,12 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { } // Avoid calling check_plain again on l() function. if ($title_callback == 'check_plain') { - $item['localized_options']['html'] = TRUE; + if ($item instanceof MenuLink) { + $item->localized_options->html = TRUE; + } + else { + $item['localized_options']['html'] = TRUE; + } } } } @@ -707,8 +717,8 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { } // If the title and description are the same, use the translated description // as a localized title. - if ($link_translate && isset($original_description) && isset($item['options']['attributes']['title']) && $item['options']['attributes']['title'] == $original_description) { - $item['localized_options']['attributes']['title'] = $item['description']; + if ($link_translate && isset($original_description) && isset($item['options']['attributes']['title']) && $item->options->attributes['title'] == $original_description) { + $item->localized_options->setValue(array('title' => $item['description']) + $item['localized_options']['attributes']); } } @@ -872,21 +882,18 @@ function menu_tail_load($arg, &$map, $index) { * to $item['localized_options'] by _menu_item_localize(). */ function _menu_link_translate(&$item, $translate = FALSE) { - if (!is_array($item['options'])) { - $item['options'] = unserialize($item['options']); - } - if ($item['external']) { - $item['access'] = 1; + if ($item->isExternal()) { + $item->setAccess(1); $map = array(); - $item['href'] = $item['link_path']; - $item['title'] = $item['link_title']; - $item['localized_options'] = $item['options']; + $item['href'] = $item->getLinkPath(); + $item['title'] = $item->getLinkTitle(); + $item->localized_options->setValue($item->options->getValue()); } else { // Complete the path of the menu link with elements from the current path, // if it contains dynamic placeholders (%). - $map = explode('/', $item['link_path']); - if (strpos($item['link_path'], '%') !== FALSE) { + $map = explode('/', $item->getLinkPath()); + if (strpos($item->getLinkPath(), '%') !== FALSE) { // Invoke registered to_arg callbacks. if (!empty($item['to_arg_functions'])) { _menu_link_map_translate($map, $item['to_arg_functions']); @@ -901,7 +908,7 @@ function _menu_link_translate(&$item, $translate = FALSE) { elseif ($translate && ($current_router_item = menu_get_item())) { // If $translate is TRUE, then this link is in the active trail. // Only translate paths within the current path. - if (strpos($current_router_item['path'], $item['link_path']) === 0) { + if (strpos($current_router_item['path'], $item->getLinkPath()) === 0) { $count = count($map); $map = array_slice($current_router_item['original_map'], 0, $count); $item['original_map'] = $map; @@ -909,7 +916,7 @@ function _menu_link_translate(&$item, $translate = FALSE) { $item['map'] = array_slice($current_router_item['map'], 0, $count); } // Reset access to check it (for the first time). - unset($item['access']); + $item->setAccess(NULL); } } } @@ -917,17 +924,17 @@ function _menu_link_translate(&$item, $translate = FALSE) { // Skip links containing untranslated arguments. if (strpos($item['href'], '%') !== FALSE) { - $item['access'] = FALSE; + $item->setAccess(FALSE); return FALSE; } // menu_tree_check_access() may set this ahead of time for links to nodes. - if (!isset($item['access'])) { + if ($item->getAccess() === NULL) { if ($route = $item->getRoute()) { - $item['access'] = menu_item_route_access($route, $item['href'], $map); + $item->setAccess(menu_item_route_access($route, $item['href'], $map)); } elseif (!empty($item['load_functions']) && !_menu_load_objects($item, $map)) { // An error occurred loading an object. - $item['access'] = FALSE; + $item->setAccess(FALSE); return FALSE; } // Apply the access check defined in hook_menu() if there is not route @@ -937,7 +944,7 @@ function _menu_link_translate(&$item, $translate = FALSE) { } } // For performance, don't localize a link the user can't access. - if ($item['access']) { + if ($item->getAccess()) { _menu_item_localize($item, $map, TRUE); } } @@ -945,7 +952,7 @@ function _menu_link_translate(&$item, $translate = FALSE) { // Allow other customizations - e.g. adding a page-specific query string to the // options array. For performance reasons we only invoke this hook if the link // has the 'alter' flag set in the options array. - if (!empty($item['options']['alter'])) { + if (!empty($item->options->alter)) { drupal_alter('translated_menu_link', $item, $map); } @@ -1097,7 +1104,7 @@ function menu_tree_output($tree) { // Pull out just the menu links we are going to render so that we // get an accurate count for the first/last classes. foreach ($tree as $data) { - if ($data['link']['access'] && !$data['link']['hidden']) { + if ($data['link']->getAccess() && !$data['link']->isHidden()) { $items[] = $data; } } @@ -1115,45 +1122,48 @@ function menu_tree_output($tree) { // Set a class for the
  • -tag. Since $data['below'] may contain local // tasks, only set 'expanded' class if the link also has children within // the current menu. - if ($data['link']['has_children'] && $data['below']) { + if ($data['link']->hasChildren() && $data['below']) { $class[] = 'expanded'; } - elseif ($data['link']['has_children']) { + elseif ($data['link']->hasChildren()) { $class[] = 'collapsed'; } else { $class[] = 'leaf'; } // Set a class if the link is in the active trail. - if ($data['link']['in_active_trail']) { + $localized_attributes = $data['link']->localized_options->attributes; + if ($data['link']->in_active_trail->value) { $class[] = 'active-trail'; - $data['link']['localized_options']['attributes']['class'][] = 'active-trail'; + $localized_attributes['class'][] = 'active-trail'; } // Normally, l() compares the href of every link with the current path and // sets the active class accordingly. But local tasks do not appear in menu // trees, so if the current path is a local task, and this link is its // tab root, then we have to set the class manually. if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != current_path()) { - $data['link']['localized_options']['attributes']['class'][] = 'active'; + $localized_attributes['class'][] = 'active'; } + $data['link']->localized_options->attributes = $localized_attributes; // Allow menu-specific theme overrides. - $element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_'); + $element['#theme'] = 'menu_link__' . strtr($data['link']->getMenuName(), '-', '_'); $element['#attributes']['class'] = $class; $element['#title'] = $data['link']['title']; $element['#href'] = $data['link']['href']; - $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array(); + $localized_options = $data['link']['localized_options']; + $element['#localized_options'] = !empty($localized_options) ? $localized_options : array(); $element['#below'] = $data['below'] ? menu_tree_output($data['below']) : $data['below']; $element['#original_link'] = $data['link']; // Index using the link's unique mlid. - $build[$data['link']['mlid']] = $element; + $build[$data['link']->id()] = $element; } if ($build) { // Make sure drupal_render() does not re-order the links. $build['#sorted'] = TRUE; // Add the theme wrapper for outer markup. // Allow menu-specific theme overrides. - $build['#theme_wrappers'][] = 'menu_tree__' . strtr($data['link']['menu_name'], '-', '_'); + $build['#theme_wrappers'][] = 'menu_tree__' . strtr($data['link']->getMenuName(), '-', '_'); } return $build; @@ -1361,12 +1371,13 @@ function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = // active trail, if it resides in the requested menu. Otherwise, // we'd needlessly re-run _menu_build_tree() queries for every menu // on every page. - if ($active_link['menu_name'] == $menu_name) { + if ($active_link->getMenuName() == $menu_name) { // Use all the coordinates, except the last one because there // can be no child beyond the last column. for ($i = 1; $i < MENU_MAX_DEPTH; $i++) { - if ($active_link['p' . $i]) { - $active_trail[$active_link['p' . $i]] = $active_link['p' . $i]; + $p_i = 'p' . $i; + if ($active_link->{$p_i}->value) { + $active_trail[$active_link->{$p_i}->value] = $active_link->{$p_i}->value; } } // If we are asked to build links for the active trail only, skip @@ -1531,11 +1542,11 @@ function _menu_build_tree($menu_name, array $parameters = array()) { */ function menu_tree_collect_node_links(&$tree, &$node_links) { foreach ($tree as $key => $v) { - if ($tree[$key]['link']['router_path'] == 'node/%') { - $nid = substr($tree[$key]['link']['link_path'], 5); + if ($tree[$key]['link']->getRouterPath() == 'node/%') { + $nid = substr($tree[$key]['link']->getLinkPath(), 5); if (is_numeric($nid)) { - $node_links[$nid][$tree[$key]['link']['mlid']] = &$tree[$key]['link']; - $tree[$key]['link']['access'] = FALSE; + $node_links[$nid][$tree[$key]['link']->id()] = &$tree[$key]['link']; + $tree[$key]['link']->set('access', FALSE); } } if ($tree[$key]['below']) { @@ -1582,14 +1593,14 @@ function _menu_tree_check_access(&$tree) { foreach ($tree as $key => $v) { $item = &$tree[$key]['link']; _menu_link_translate($item); - if ($item['access'] || ($item['in_active_trail'] && strpos($item['href'], '%') !== FALSE)) { + if ($item->getAccess() || ($item->in_active_trail->value && strpos($item['href'], '%') !== FALSE)) { if ($tree[$key]['below']) { _menu_tree_check_access($tree[$key]['below']); } // The weights are made a uniform 5 digits by adding 50000 as an offset. // After _menu_link_translate(), $item['title'] has the localized link title. // Adding the mlid to the end of the index insures that it is unique. - $new_tree[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $tree[$key]; + $new_tree[(50000 + $item->getWeight()) . ' ' . $item['title'] . ' ' . $item->id()] = $tree[$key]; } } // Sort siblings in the tree based on the weights and localized titles. @@ -1640,9 +1651,9 @@ function _menu_tree_data(&$links, $parents, $depth) { while ($item = array_pop($links)) { // We need to determine if we're on the path to root so we can later build // the correct active trail. - $item['in_active_trail'] = in_array($item['mlid'], $parents); + $item->in_active_trail->value = in_array($item->id(), $parents); // Add the current link to the tree. - $tree[$item['mlid']] = array( + $tree[$item->id()] = array( 'link' => $item, 'below' => array(), ); @@ -1650,14 +1661,14 @@ function _menu_tree_data(&$links, $parents, $depth) { // to other recursive function calls if we return or build a sub-tree. $next = end($links); // Check whether the next link is the first in a new sub-tree. - if ($next && $next['depth'] > $depth) { + if ($next && $next->getDepth() > $depth) { // Recursively call _menu_tree_data to build the sub-tree. - $tree[$item['mlid']]['below'] = _menu_tree_data($links, $parents, $next['depth']); + $tree[$item->id()]['below'] = _menu_tree_data($links, $parents, $next->getDepth()); // Fetch next link after filling the sub-tree. $next = end($links); } // Determine if we should exit the loop and return. - if (!$next || $next['depth'] < $depth) { + if (!$next || $next->getDepth() < $depth) { break; } } @@ -1907,12 +1918,12 @@ function menu_navigation_links($menu_name, $level = 0) { $router_item = menu_get_item(); $links = array(); foreach ($tree as $item) { - if (!$item['link']['hidden']) { + if (!$item['link']->isHidden()) { $class = ''; - $l = $item['link']['localized_options']; + $l = $item['link']->localized_options->getValue(); $l['href'] = $item['link']['href']; $l['title'] = $item['link']['title']; - if ($item['link']['in_active_trail']) { + if ($item['link']->in_active_trail->value) { $class = ' active-trail'; $l['attributes']['class'][] = 'active-trail'; } @@ -1924,7 +1935,7 @@ function menu_navigation_links($menu_name, $level = 0) { $l['attributes']['class'][] = 'active'; } // Keyed with the unique mlid to generate classes in theme_links(). - $links['menu-' . $item['link']['mlid'] . $class] = $l; + $links['menu-' . $item['link']->id() . $class] = $l; } } return $links; @@ -2478,7 +2489,7 @@ function menu_set_active_trail($new_trail = NULL) { // Pass TRUE for $only_active_trail to make menu_tree_page_data() build // a stripped down menu tree containing the active trail only, in case // the given menu has not been built in this request yet. - $tree = menu_tree_page_data($preferred_link['menu_name'], NULL, TRUE); + $tree = menu_tree_page_data($preferred_link->getMenuName(), NULL, TRUE); list($key, $curr) = each($tree); } // There is no link for the current path. @@ -2489,7 +2500,7 @@ function menu_set_active_trail($new_trail = NULL) { while ($curr) { $link = $curr['link']; - if ($link['in_active_trail']) { + if ($link->in_active_trail->value) { // Add the link to the trail, unless it links to its parent. if (!($link['type'] & MENU_LINKS_TO_PARENT)) { // The menu tree for the active trail may contain additional links @@ -2503,7 +2514,7 @@ function menu_set_active_trail($new_trail = NULL) { if (strpos($link['href'], '%') !== FALSE) { _menu_link_translate($link, TRUE); } - if ($link['access']) { + if ($link->getAccess()) { $trail[] = $link; } } @@ -2581,10 +2592,10 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) { // Sort candidates by link path and menu name. $candidates = array(); foreach ($menu_links as $candidate) { - $candidates[$candidate['link_path']][$candidate['menu_name']] = $candidate; + $candidates[$candidate->getLinkPath()][$candidate->getMenuName()] = $candidate; // Add any menus not already in the menu name search list. - if (!in_array($candidate['menu_name'], $menu_names)) { - $menu_names[] = $candidate['menu_name']; + if (!in_array($candidate->getMenuName(), $menu_names)) { + $menu_names[] = $candidate->getMenuName(); } } @@ -2597,7 +2608,7 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) { $candidate_item = $candidates[$link_path][$menu_name]; $map = explode('/', $path); _menu_translate($candidate_item, $map); - if ($candidate_item['access']) { + if ($candidate_item->getAccess()) { $preferred_links[$path][$menu_name] = $candidate_item; if (empty($preferred_links[$path][MENU_PREFERRED_LINK])) { // Store the most specific link. @@ -2840,6 +2851,8 @@ function _menu_navigation_links_rebuild($menu) { array_multisort($sort, SORT_NUMERIC, $router_items); foreach ($router_items as $key => $router_item) { + // Add the path to the item. + $router_item['path'] = $key; // For performance reasons, do a straight query now and convert to a menu // link entity later. // @todo revisit before release. @@ -2847,9 +2860,8 @@ function _menu_navigation_links_rebuild($menu) { ->fields('menu_links') ->condition('link_path', $router_item['path']) ->condition('module', 'system') - ->execute()->fetchAll(); + ->execute()->fetch(); if ($existing_item) { - $existing_item = reset($existing_item); $existing_item->options = unserialize($existing_item->options); $router_item['mlid'] = $existing_item->mlid; @@ -2875,8 +2887,8 @@ function _menu_navigation_links_rebuild($menu) { $existing_item = NULL; } - if ($existing_item && $existing_item->customized) { - $parent_candidates[$existing_item->mlid] = $existing_item; + if ($existing_item && $existing_item->customized->value) { + $parent_candidates[$existing_item->id()] = $existing_item; } else { $menu_link = MenuLink::buildFromRouterItem($router_item); @@ -2893,11 +2905,11 @@ function _menu_navigation_links_rebuild($menu) { // Updated and customized items whose router paths are gone need new ones. $menu_links = $menu_link_controller->loadUpdatedCustomized($paths); foreach ($menu_links as $menu_link) { - $router_path = _menu_find_router_path($menu_link->link_path); - if (!empty($router_path) && ($router_path != $menu_link->router_path || $menu_link->updated)) { + $router_path = _menu_find_router_path($menu_link->link_path->value); + if (!empty($router_path) && ($router_path != $menu_link->router_path->value || $menu_link->updated->value)) { // If the router path and the link path matches, it's surely a working // item, so we clear the updated flag. - $updated = $menu_link->updated && $router_path != $menu_link->link_path; + $updated = $menu_link->updated->value && $router_path != $menu_link->link_path->value; $menu_link->router_path = $router_path; $menu_link->updated = (int) $updated; diff --git a/core/includes/path.inc b/core/includes/path.inc index 2187dd3..52ab706 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -204,7 +204,7 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) { $item['link_path'] = $form_item['link_path']; $item['link_title'] = $form_item['link_title']; $item['external'] = FALSE; - $item['options'] = ''; + $item['options'] = array(); _menu_link_translate($item); } } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index b65b71e..0888ed4 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1703,9 +1703,9 @@ function theme_links($variables) { // Handle title-only text items. else { // Merge in default array properties into $link. - $link += array( - 'html' => FALSE, - ); + if (!isset($link['html'])) { + $link['html'] = FALSE; + } $item = ($link['html'] ? $link['title'] : check_plain($link['title'])); if (isset($link['attributes'])) { $item = '' . $item . ''; diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index 49fa3a0..10e8237 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -617,7 +617,7 @@ public function updateOriginalValues() { } /** - * Implements the magic method for setting object properties. + * Implements the magic method for getting object properties. * * @todo: A lot of code still uses non-fields (e.g. $entity->content in render * controllers) by reference. Clean that up. diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php new file mode 100644 index 0000000..b2e55ce --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php @@ -0,0 +1,96 @@ +properties as $name => $property) { + $definitions[$name] = $property->getDefinition(); + } + + return $definitions; + } + + /** + * Overrides \Drupal\Core\Entity\Field\FieldItemBase::setValue(). + * + * @param array|null $values + * An array of property values. + */ + public function setValue($values, $notify = TRUE) { + $this->properties = array(); + if (!isset($values)) { + return; + } + + if (!is_array($values)) { + if ($values instanceof MapItem) { + $values = $values->getValue(); + } + else { + $values = unserialize($values); + } + } + + foreach($values as $name => $value) { + $this->properties[$name] = $this->valueToProperty($value, $name); + } + } + + public function __get($name) { + if (!isset($this->properties[$name])) { + $this->properties[$name] = $this->valueToProperty(array(), $name); + } + + return $this->properties[$name]->getValue(); + } + + public function __set($name, $value) { + if (isset($value)) { + if (isset($this->properties[$name])) { + $this->properties[$name]->setValue($value); + } + else { + $this->properties[$name] = $this->valueToProperty($value, $name); + } + } + else { + unset($this->properties[$name]); + } + } + + protected function valueToProperty($value, $name) { + $def = array('type' => 'any'); + if ($value instanceof TypedData) { + $def = $value->getDefinition(); + $value = $value->getValue(); + } + + return \Drupal::typedData()->create($def, $value, $name, $this); + } +} \ No newline at end of file diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 282aa92..fd86043 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -58,7 +58,7 @@ function book_entity_bundle_info() { function book_menu_link_load($entities) { foreach ($entities as $entity) { // Change the bundle of menu links related to a book. - if (strpos($entity->menu_name, 'book-toc-') === 0) { + if (strpos($entity->menu_name->value, 'book-toc-') === 0) { $entity->bundle = 'book-toc'; } } @@ -904,7 +904,7 @@ function book_menu_subtree_data($link) { } $links = array(); foreach ($query->execute() as $item) { - $links[] = $item; + $links[] = entity_create('menu_link', $item); } $data['tree'] = menu_tree_data($links, array(), $link['depth']); $data['node_links'] = array(); diff --git a/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php b/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php index 2fef927..93d9e8e 100644 --- a/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php +++ b/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php @@ -85,8 +85,8 @@ public function build(array $attributes) { $depth = 1; while (!empty($book['p' . ($depth + 1)])) { if (!empty($menu_links[$book['p' . $depth]]) && ($menu_link = $menu_links[$book['p' . $depth]])) { - if ($this->accessManager->checkNamedRoute($menu_link->route_name, $menu_link->route_parameters)) { - $links[] = $this->linkGenerator->generate($menu_link->label(), $menu_link->route_name, $menu_link->route_parameters, $menu_link->options); + if ($this->accessManager->checkNamedRoute($menu_link->route_name->value, $menu_link->route_parameters[0]->getValue())) { + $links[] = $this->linkGenerator->generate($menu_link->label(), $menu_link->route_name->value, $menu_link->route_parameters[0]->getValue(), $menu_link->options[0]->getValue()); } } $depth++; diff --git a/core/modules/book/lib/Drupal/book/BookManager.php b/core/modules/book/lib/Drupal/book/BookManager.php index d154c46..bbd59c5 100644 --- a/core/modules/book/lib/Drupal/book/BookManager.php +++ b/core/modules/book/lib/Drupal/book/BookManager.php @@ -108,7 +108,7 @@ protected function loadBooks() { $link['options'] = unserialize($link['options']); $link['title'] = $nodes[$nid]->label(); $link['type'] = $nodes[$nid]->bundle(); - $this->books[$link['bid']] = $link; + $this->books[$link['bid']] = entity_create('menu_link', $link); } } } diff --git a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php index 153c547..5b19072 100644 --- a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php +++ b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php @@ -53,11 +53,10 @@ public function viewModeTypeSelection() { $entity_types = array(); foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) { if ($entity_info['fieldable'] && isset($entity_info['controllers']['render'])) { - $entity_types[$entity_type] = array( - 'title' => $entity_info['label'], - 'href' => 'admin/structure/display-modes/view/add/' . $entity_type, - 'localized_options' => array(), - ); + $entity_types[$entity_type] = entity_create('menu_link', array( + 'link_title' => $entity_info['label'], + 'link_path' => 'admin/structure/display-modes/view/add/' . $entity_type, + )); } } return array( @@ -77,11 +76,10 @@ public function formModeTypeSelection() { $entity_types = array(); foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) { if ($entity_info['fieldable'] && isset($entity_info['controllers']['form'])) { - $entity_types[$entity_type] = array( - 'title' => $entity_info['label'], - 'href' => 'admin/structure/display-modes/form/add/' . $entity_type, - 'localized_options' => array(), - ); + $entity_types[$entity_type] = entity_create('menu_link', array( + 'link_title' => $entity_info['label'], + 'link_path' => 'admin/structure/display-modes/form/add/' . $entity_type, + )); } } return array( diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php index 2815a91..43db3a2 100644 --- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php +++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php @@ -18,7 +18,7 @@ class MenuLinkDeleteForm extends EntityConfirmFormBase { * {@inheritdoc} */ public function getQuestion() { - return t('Are you sure you want to delete the custom menu link %item?', array('%item' => $this->entity->link_title)); + return t('Are you sure you want to delete the custom menu link %item?', array('%item' => $this->entity->link_title->value)); } /** @@ -28,7 +28,7 @@ public function getCancelRoute() { return array( 'route_name' => 'menu.menu_edit', 'route_parameters' => array( - 'menu' => $this->entity->menu_name, + 'menu' => $this->entity->menu_name->value, ), ); } @@ -38,10 +38,10 @@ public function getCancelRoute() { */ public function submit(array $form, array &$form_state) { menu_link_delete($this->entity->id()); - $t_args = array('%title' => $this->entity->link_title); + $t_args = array('%title' => $this->entity->getLinkTitle()); drupal_set_message(t('The menu link %title has been deleted.', $t_args)); watchdog('menu', 'Deleted menu link %title.', $t_args, WATCHDOG_NOTICE); - $form_state['redirect'] = 'admin/structure/menu/manage/' . $this->entity->menu_name; + $form_state['redirect'] = 'admin/structure/menu/manage/' . $this->entity->getMenuName(); } } diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php index 5b79ef4..6f41606 100644 --- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php +++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php @@ -18,7 +18,7 @@ class MenuLinkResetForm extends EntityConfirmFormBase { * {@inheritdoc} */ public function getQuestion() { - return t('Are you sure you want to reset the link %item to its default values?', array('%item' => $this->entity->link_title)); + return t('Are you sure you want to reset the link %item to its default values?', array('%item' => $this->entity->link_title->value)); } /** @@ -28,7 +28,7 @@ public function getCancelRoute() { return array( 'route_name' => 'menu.menu_edit', 'route_parameters' => array( - 'menu' => $this->entity->menu_name, + 'menu' => $this->entity->menu_name->value, ), ); } @@ -53,7 +53,7 @@ public function getConfirmText() { public function submit(array $form, array &$form_state) { $new_menu_link = $this->entity->reset(); drupal_set_message(t('The menu link was reset to its default settings.')); - $form_state['redirect'] = 'admin/structure/menu/manage/' . $new_menu_link->menu_name; + $form_state['redirect'] = 'admin/structure/menu/manage/' . $new_menu_link->getMenuName(); } } diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuNodeTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuNodeTest.php index 39a9d43..ea5613e 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuNodeTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuNodeTest.php @@ -81,9 +81,11 @@ function testMenuNodeFormWidget() { $this->assertNoLink($node_title); // Edit the node and create a menu link. + $menu_link_description = $this->randomString(16); $edit = array( 'menu[enabled]' => 1, 'menu[link_title]' => $node_title, + 'menu[description]' => $menu_link_description, 'menu[weight]' => 17, ); $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); @@ -93,6 +95,25 @@ function testMenuNodeFormWidget() { $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertOptionSelected('edit-menu-weight', 17, 'Menu weight correct in edit form'); + $this->assertFieldById('edit-menu-description', $menu_link_description, 'Menu description correct in edit form'); + + // Change the menu link settings. Set description to empty to test its + // special handling. + $edit = array( + 'menu[enabled]' => 1, + 'menu[link_title]' => $node_title . '-foo', + 'menu[description]' => '', + 'menu[weight]' => 15, + ); + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + // Assert that the changed link exists. + $this->drupalGet('test-page'); + $this->assertLink($node_title . '-foo'); + + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertOptionSelected('edit-menu-weight', 15, 'Menu weight was changed and is correct in edit form'); + $this->assertFieldById('edit-menu-description', '', 'Menu description was changed and is correct in edit form'); + // Edit the node and remove the menu link. $edit = array( diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index f7e0690..e0ac0d7 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -82,13 +82,13 @@ function testMenu() { $item = entity_load('menu_link', $item['mlid']); // Verify that a change to the description is saved. $description = $this->randomName(16); - $item['options']['attributes']['title'] = $description; + $item->options->attributes = array('title' => $description); $return_value = menu_link_save($item); // Save the menu link again to test the return value of the procedural save // helper. $this->assertIdentical($return_value, $item->save(), 'Return value of menu_link_save() is identical to the return value of $menu_link->save().'); $saved_item = entity_load('menu_link', $item['mlid']); - $this->assertEqual($description, $saved_item['options']['attributes']['title'], 'Saving an existing link updates the description (title attribute)'); + $this->assertEqual($description, $saved_item->options->attributes['title'], 'Saving an existing link updates the description (title attribute)'); $this->resetMenuLink($item, $old_title); } @@ -448,7 +448,7 @@ public function testMenuBundles() { $unsaved_item = entity_create('menu_link', array('menu_name' => $menu->id(), 'link_title' => $this->randomName(16), 'link_path' => '')); $this->assertEqual($unsaved_item->bundle(), $menu->id(), 'Unsaved menu link bundle matches the menu'); - $this->assertEqual($unsaved_item->menu_name, $menu->id(), 'Unsaved menu link menu name matches the menu'); + $this->assertEqual($unsaved_item->menu_name->value, $menu->id(), 'Unsaved menu link menu name matches the menu'); } diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install index 61f73b2..04c0dbb 100644 --- a/core/modules/menu/menu.install +++ b/core/modules/menu/menu.install @@ -18,7 +18,7 @@ function menu_install() { $system_link = reset($system_link); $base_link = entity_create('menu_link', array( - 'menu_name' => $system_link->menu_name, + 'menu_name' => $system_link->getMenuName(), 'router_path' => 'admin/structure/menu/manage/%', 'module' => 'menu', )); @@ -31,8 +31,8 @@ function menu_install() { $link->link_path = 'admin/structure/menu/manage/' . $menu->id(); $query = \Drupal::entityQuery('menu_link') - ->condition('link_path', $link->link_path) - ->condition('plid', $link->plid); + ->condition('link_path', $link->getLinkPath()) + ->condition('plid', $link->getParentLinkId()); $result = $query->execute(); if (empty($result)) { diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index 1689d35..d420a7e 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -351,7 +351,7 @@ function menu_block_view_system_menu_block_alter(array &$build, BlockPluginInter list(, $menu_name) = explode(':', $block->getPluginId()); if (isset($menus[$menu_name]) && isset($build['content'])) { foreach (element_children($build['content']) as $key) { - $build['content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['content'][$key]['#original_link']['menu_name'])); + $build['content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['content'][$key]['#original_link']->getMenuName())); } } } @@ -376,22 +376,24 @@ function menu_node_update(EntityInterface $node) { function menu_node_save(EntityInterface $node) { if (isset($node->menu)) { $link = &$node->menu; - if (empty($link['enabled'])) { + if (empty($link->enabled)) { if (!$link->isNew()) { menu_link_delete($link['mlid']); } } - elseif (trim($link['link_title'])) { - $link['link_title'] = trim($link['link_title']); - $link['link_path'] = 'node/' . $node->id(); + elseif (trim($link->link_title[0]->value)) { + $link->link_title = trim($link->link_title[0]->value); + $link->link_path = 'node/' . $node->id(); + $options = $link->options[0]->getValue(); if (trim($link['description'])) { - $link['options']['attributes']['title'] = trim($link['description']); + $options['attributes']['title'] = trim($link['description']); } else { // If the description field was left empty, remove the title attribute // from the menu link. - unset($link['options']['attributes']['title']); + unset($options['attributes']['title']); } + $link->options = $options; if (!menu_link_save($link)) { drupal_set_message(t('There was an error saving the menu link.'), 'error'); } @@ -561,7 +563,7 @@ function menu_form_node_form_alter(&$form, $form_state) { ); // Get number of items in menu so the weight selector is sized appropriately. - $delta = entity_get_controller('menu_link')->countMenuLinks($link->menu_name); + $delta = entity_get_controller('menu_link')->countMenuLinks($link->getMenuName()); if ($delta < 50) { // Old hardcoded value $delta = 50; @@ -585,7 +587,8 @@ function menu_node_submit(EntityInterface $node, $form, $form_state) { // Decompose the selected menu parent option into 'menu_name' and 'plid', if // the form used the default parent selection widget. if (!empty($form_state['values']['menu']['parent'])) { - list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']); + $parts = explode(':', $form_state['values']['menu']['parent']); + $node->menu->setMenuName($parts[0])->setParentLinkId($parts[1]); } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php index 0fc739a..878ace8 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php @@ -7,16 +7,18 @@ namespace Drupal\menu_link\Entity; +use Drupal\Core\Annotation\Translation; +use Drupal\Core\Entity\Annotation\EntityType; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityNG; +use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\TypedData\TypedDataInterface; +use Drupal\Component\Uuid\Uuid; use Drupal\menu_link\MenuLinkInterface; +use Drupal\menu_link\MenuLinkStorageControllerInterface; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; -use Drupal\Core\Entity\EntityStorageException; -use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityStorageControllerInterface; -use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Entity\Entity; - /** * Defines the menu link entity class. * @@ -47,14 +49,7 @@ * } * ) */ -class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { - - /** - * The link's menu name. - * - * @var string - */ - public $menu_name = 'tools'; +class MenuLink extends EntityNG implements \ArrayAccess, MenuLinkInterface { /** * The link's bundle. @@ -64,215 +59,40 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { public $bundle = 'tools'; /** - * The menu link ID. - * - * @var int - */ - public $mlid; - - /** - * The menu link UUID. - * - * @var string - */ - public $uuid; - - /** - * The parent link ID. - * - * @var int - */ - public $plid; - - /** - * The Drupal path or external path this link points to. - * - * @var string - */ - public $link_path; - - /** - * For links corresponding to a Drupal path (external = 0), this connects the - * link to a {menu_router}.path for joins. - * - * @var string - */ - public $router_path; - - /** - * The entity label. - * - * @var string - */ - public $link_title = ''; - - /** - * A serialized array of options to be passed to the url() or l() function, - * such as a query string or HTML attributes. - * - * @var array - */ - public $options = array(); - - /** - * The name of the module that generated this link. - * - * @var string - */ - public $module = 'menu'; - - /** - * A flag for whether the link should be rendered in menus. - * - * @var int - */ - public $hidden = 0; - - /** - * A flag to indicate if the link points to a full URL starting with a - * protocol, like http:// (1 = external, 0 = internal). - * - * @var int - */ - public $external; - - /** - * Flag indicating whether any links have this link as a parent. - * - * @var int - */ - public $has_children = 0; - - /** - * Flag for whether this link should be rendered as expanded in menus. - * Expanded links always have their child links displayed, instead of only - * when the link is in the active trail. - * - * @var int - */ - public $expanded = 0; - - /** - * Link weight among links in the same menu at the same depth. - * - * @var int - */ - public $weight = 0; - - /** - * The depth relative to the top level. A link with plid == 0 will have - * depth == 1. - * - * @var int - */ - public $depth; - - /** - * A flag to indicate that the user has manually created or edited the link. - * - * @var int - */ - public $customized = 0; - - /** - * The first entity ID in the materialized path. - * - * @var int - * - * @todo Investigate whether the p1, p2, .. pX properties can be moved to a - * single array property. - */ - public $p1; - - /** - * The second entity ID in the materialized path. - * - * @var int - */ - public $p2; - - /** - * The third entity ID in the materialized path. - * - * @var int - */ - public $p3; - - /** - * The fourth entity ID in the materialized path. - * - * @var int - */ - public $p4; - - /** - * The fifth entity ID in the materialized path. - * - * @var int - */ - public $p5; - - /** - * The sixth entity ID in the materialized path. - * - * @var int - */ - public $p6; - - /** - * The seventh entity ID in the materialized path. - * - * @var int - */ - public $p7; - - /** - * The eighth entity ID in the materialized path. - * - * @var int - */ - public $p8; - - /** - * The ninth entity ID in the materialized path. - * - * @var int - */ - public $p9; - - /** - * The menu link modification timestamp. + * The route object associated with this menu link, if any. * - * @var int + * @var \Symfony\Component\Routing\Route */ - public $updated = 0; + protected $routeObject; /** - * The name of the route associated with this menu link, if any. + * Crap coming from the old routing system. * - * @var string - */ - public $route_name; - - /** - * The parameters of the route associated with this menu link, if any. + * @todo Remove when we rip out the old routing system. * * @var array */ - public $route_parameters; + protected $oldRouterItem = array(); /** * The route object associated with this menu link, if any. * * @var \Symfony\Component\Routing\Route */ - protected $routeObject; + protected $oldRoutingProperties = array( + 'path', 'load_functions', 'to_arg_functions', 'access_callback', + 'access_arguments', 'page_callback', 'page_arguments', 'fit', + 'number_parts', 'context', 'tab_parent', 'tab_root', 'title', + 'title_callback', 'title_arguments', 'theme_callback', 'theme_arguments', + 'type', 'description', 'description_callback', 'description_arguments', + 'position', 'include_file', + ); /** - * Overrides Entity::id(). + * {@inheritdoc} */ public function id() { - return $this->mlid; + return $this->get('mlid')->value; } /** @@ -287,7 +107,8 @@ public function bundle() { */ public function createDuplicate() { $duplicate = parent::createDuplicate(); - $duplicate->plid = NULL; + + $duplicate->get('plid')->offsetGet(0)->set('value', NULL); return $duplicate; } @@ -295,12 +116,12 @@ public function createDuplicate() { * {@inheritdoc} */ public function getRoute() { - if (!$this->route_name) { + if (!$this->getRouteName()) { return NULL; } if (!($this->routeObject instanceof Route)) { $route_provider = \Drupal::service('router.route_provider'); - $this->routeObject = $route_provider->getRouteByName($this->route_name); + $this->routeObject = $route_provider->getRouteByName($this->getRouteName()); } return $this->routeObject; } @@ -322,11 +143,11 @@ public function reset() { // not stored anywhere else. Since resetting a link happens rarely and this // is a one-time operation, retrieving the full menu router does no harm. $menu = menu_get_router(); - $router_item = $menu[$this->router_path]; + $router_item = $menu[$this->getRouterPath()]; $new_link = self::buildFromRouterItem($router_item); // Merge existing menu link's ID and 'has_children' property. foreach (array('mlid', 'has_children') as $key) { - $new_link->{$key} = $this->{$key}; + $new_link->{$key}->value = $this->{$key}->value; } $new_link->save(); return $new_link; @@ -351,37 +172,101 @@ public static function buildFromRouterItem(array $item) { 'link_title' => $item['title'], 'link_path' => $item['path'], 'options' => empty($item['description']) ? array() : array('attributes' => array('title' => $item['description'])), + 'route_name' => $item['route_name'], ); return \Drupal::entityManager() ->getStorageController('menu_link')->create($item); } /** - * Implements ArrayAccess::offsetExists(). + * {@inheritdoc} */ public function offsetExists($offset) { - return isset($this->{$offset}); + if (in_array($offset, $this->oldRoutingProperties)) { + return isset($this->oldRouterItem[$offset]); + } + return isset($this->{$offset}->value); } /** - * Implements ArrayAccess::offsetGet(). + * {@inheritdoc} */ - public function &offsetGet($offset) { - return $this->{$offset}; + public function offsetGet($offset) { + if (in_array($offset, $this->oldRoutingProperties)) { + // For now we simply return NULL if a property isn't found. + return (isset($this->oldRouterItem[$offset])) ? $this->oldRouterItem[$offset] : NULL; + } + elseif (in_array($offset, array('options', 'localized_options', 'route_parameters'))) { + $values = $this->{$offset}[0]->getValue(); + return $values; + } + elseif ($this->getPropertyDefinition($offset)) { + return $this->get($offset)->value; + } + else { + return $this->$offset; + } } /** - * Implements ArrayAccess::offsetSet(). + * {@inheritdoc} */ public function offsetSet($offset, $value) { - $this->{$offset} = $value; + if (in_array($offset, $this->oldRoutingProperties)) { + $this->oldRouterItem[$offset] = $value; + } + elseif (in_array($offset, array('options', 'localized_options', 'route_parameters'))) { + if (is_array($value)) { + foreach ($value as $delta => $value_item) { + if (!is_numeric($delta)) { + $this->{$offset} = array($value); + return; + } + } + } + } + elseif ($this->getPropertyDefinition($offset)) { + $this->{$offset} = $value; + } + else { + $this->{$offset} = $value; + } } /** - * Implements ArrayAccess::offsetUnset(). + * {@inheritdoc} */ public function offsetUnset($offset) { - unset($this->{$offset}); + if (in_array($offset, $this->oldRoutingProperties)) { + unset($this->oldRouterItem[$offset]); + } + elseif (in_array($offset, array('options', 'localized_options', 'route_parameters'))) { + $this->{$offset}[0]->setValue(NULL); + } + elseif ($this->getPropertyDefinition($offset)) { + $this->get($offset)->setValue(NULL); + } + else { + $this->get($offset)->setValue(NULL); + } + } + + public function __set($name, $value) { + if (in_array($name, $this->oldRoutingProperties)) { + $this->oldRouterItem[$name] = $value; + } + else { + parent::__set($name, $value); + } + } + + /** + * {@inheritdoc} + */ + public static function preCreate(EntityStorageControllerInterface $storage_controller, array &$values) { + if (empty($values['menu_name'])) { + $values['menu_name'] = $values['bundle'] = 'tools'; + } } /** @@ -397,10 +282,10 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr foreach ($entities as $entity) { // Children get re-attached to the item's parent. - if ($entity->has_children) { - $children = $storage_controller->loadByProperties(array('plid' => $entity->plid)); + if ($entity->hasChildren()) { + $children = $storage_controller->loadByProperties(array('plid' => $entity->getParentLinkId())); foreach ($children as $child) { - $child->plid = $entity->plid; + $child->setParentLinkId($entity->getParentLinkId()); $storage_controller->save($child); } } @@ -421,8 +306,8 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont } // Store all menu names for which we need to clear the cache. - if (!isset($affected_menus[$entity->menu_name])) { - $affected_menus[$entity->menu_name] = $entity->menu_name; + if (!isset($affected_menus[$entity->getMenuName()])) { + $affected_menus[$entity->getMenuName()] = $entity->getMenuName(); } } @@ -440,67 +325,70 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { // This is the easiest way to handle the unique internal path '', // since a path marked as external does not need to match a router path. - $this->external = (url_is_external($this->link_path) || $this->link_path == '') ? 1 : 0; + $this->external->value = (url_is_external($this->getLinkPath()) || $this->getLinkPath() == '') ? 1 : 0; // Try to find a parent link. If found, assign it and derive its menu. $parent_candidates = !empty($this->parentCandidates) ? $this->parentCandidates : array(); $parent = $this->findParent($storage_controller, $parent_candidates); if ($parent) { - $this->plid = $parent->id(); - $this->menu_name = $parent->menu_name; + $this->setParentLinkId($parent->id()); + $this->setMenuName($parent->getMenuName()); } // If no corresponding parent link was found, move the link to the top-level. else { - $this->plid = 0; + $this->setParentLinkId(0); } // Directly fill parents for top-level links. - if ($this->plid == 0) { - $this->p1 = $this->id(); + if ($this->getParentLinkId() == 0) { + $this->p1->value = $this->id(); for ($i = 2; $i <= MENU_MAX_DEPTH; $i++) { $parent_property = "p$i"; - $this->{$parent_property} = 0; + $this->{$parent_property}->value = 0; } - $this->depth = 1; + $this->depth->value = 1; } // Otherwise, ensure that this link's depth is not beyond the maximum depth // and fill parents based on the parent link. else { - if ($this->has_children && $this->original) { + if ($this->hasChildren() && $this->original) { $limit = MENU_MAX_DEPTH - $storage_controller->findChildrenRelativeDepth($this->original) - 1; } else { $limit = MENU_MAX_DEPTH - 1; } - if ($parent->depth > $limit) { + if ($parent->getDepth() > $limit) { return FALSE; } - $this->depth = $parent->depth + 1; + $this->depth->value = $parent->getDepth() + 1; $this->setParents($parent); } // Need to check both plid and menu_name, since plid can be 0 in any menu. - if (isset($this->original) && ($this->plid != $this->original->plid || $this->menu_name != $this->original->menu_name)) { + if (isset($this->original) && ($this->getParentLinkId() != $this->original->getParentLinkId() || $this->getMenuName() != $this->original->getMenuName())) { $storage_controller->moveChildren($this, $this->original); } // Find the router_path. - if (empty($this->router_path) || empty($this->original) || (isset($this->original) && $this->original->link_path != $this->link_path)) { - if ($this->external) { - $this->router_path = ''; + if (!($this->getRouterPath()) || empty($this->original) || (isset($this->original) && $this->original->getLinkPath() != $this->getLinkPath())) { + if ($this->isExternal()) { + $this->setRouterPath(''); } else { // Find the router path which will serve this path. - $this->parts = explode('/', $this->link_path, MENU_MAX_PARTS); - $this->router_path = _menu_find_router_path($this->link_path); + // @todo Where do we need 'parts'? + $this->parts = explode('/', $this->getLinkPath(), MENU_MAX_PARTS); + $this->setRouterPath(_menu_find_router_path($this->getLinkPath())); } } + // Find the route_name. - if (!isset($this->route_name)) { - if ($result = static::findRouteNameParameters($this->link_path)) { - list($this->route_name, $this->route_parameters) = $result; + if ($this->getRouteName() === NULL) { + if ($result = static::findRouteNameParameters($this->getLinkPath())) { + $this->setRouteName($result[0]); + $this->route_parameters = $result[1]; } else { - $this->route_name = ''; + $this->setRouteName(''); $this->route_parameters = array(); } } @@ -515,9 +403,9 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $ // Check the has_children status of the parent. $storage_controller->updateParentalStatus($this); - menu_cache_clear($this->menu_name); - if (isset($this->original) && $this->menu_name != $this->original->menu_name) { - menu_cache_clear($this->original->menu_name); + menu_cache_clear($this->getMenuName()); + if (isset($this->original) && $this->getMenuName() != $this->original->getMenuName()) { + menu_cache_clear($this->original->getMenuName()); } // Now clear the cache. @@ -549,46 +437,46 @@ public static function findRouteNameParameters($link_path) { /** * {@inheritdoc} */ - public function setParents(EntityInterface $parent) { + public function setParents(MenuLinkInterface $parent) { $i = 1; - while ($i < $this->depth) { - $p = 'p' . $i++; - $this->{$p} = $parent->{$p}; + while ($i < $this->getDepth()) { + $p = 'p' . $i; + $this->{$p}->value = $parent->getMaterializedPathEntity($i); + $i++; } $p = 'p' . $i++; // The parent (p1 - p9) corresponding to the depth always equals the mlid. - $this->{$p} = $this->id(); + $this->{$p}->value = $this->id(); while ($i <= MENU_MAX_DEPTH) { $p = 'p' . $i++; - $this->{$p} = 0; + $this->{$p}->value = 0; } } /** * {@inheritdoc} */ - public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()) { + public function findParent(MenuLinkStorageControllerInterface $storage_controller, array $parent_candidates = array()) { $parent = FALSE; + $plid = $this->getParentLinkId(); // This item is explicitely top-level, skip the rest of the parenting. - if (isset($this->plid) && empty($this->plid)) { + if ($plid === 0) { return $parent; } // If we have a parent link ID, try to use that. $candidates = array(); - if (isset($this->plid)) { - $candidates[] = $this->plid; + if ($plid) { + $candidates = array($plid); } // Else, if we have a link hierarchy try to find a valid parent in there. - if (!empty($this->depth) && $this->depth > 1) { - for ($depth = $this->depth - 1; $depth >= 1; $depth--) { - $parent_property = "p$depth"; - $candidates[] = $this->$parent_property; + if ($this->getDepth() > 1) { + for ($depth = $this->getDepth() - 1; $depth >= 1; $depth--) { + $candidates[] = $this->getMaterializedPathEntity($depth); } } - foreach ($candidates as $mlid) { if (isset($parent_candidates[$mlid])) { $parent = $parent_candidates[$mlid]; @@ -604,12 +492,469 @@ public function findParent(EntityStorageControllerInterface $storage_controller, // If everything else failed, try to derive the parent from the path // hierarchy. This only makes sense for links derived from menu router // items (ie. from hook_menu()). - if ($this->module == 'system') { + if ($this->getModule() == 'system') { $parent = $storage_controller->getParentFromHierarchy($this); } return $parent; } + /** + * overrides \Drupal\Core\Entity\EntityNG::set() + */ + public function set($property_name, $value, $notify = TRUE) { + // work-around entity_form_submit_build_entity() -> entity.set() trying to + // set a non-existing fields into MenuLink. + $definition = $this->getPropertyDefinition($property_name); + if (!$definition) { + $this->$property_name = $value; + } + else { + parent::set($property_name, $value, $notify); + } + } + + /** + * {@inheritdoc} + */ + public function getMenuName() { + return $this->get('menu_name')->value; + } + + /** + * {@inheritdoc} + */ + public function setMenuName($menu_name) { + $this->set('menu_name', $menu_name); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getParentLinkId() { + return $this->get('plid')->value; + } + + /** + * {@inheritdoc} + */ + public function setParentLinkId($plid) { + $this->set('plid', $plid); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLinkPath() { + return $this->get('link_path')->value; + } + + /** + * {@inheritdoc} + */ + public function setLinkPath($link_path) { + $this->set('link_path', $link_path); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLinkTitle() { + return $this->get('link_title')->value; + } + + /** + * {@inheritdoc} + */ + public function setLinkTitle($link_title) { + $this->set('link_title', $link_title); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRouterPath() { + return $this->get('router_path')->value; + } + + /** + * {@inheritdoc} + */ + public function setRouterPath($router_path) { + $this->set('router_path', $router_path); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getOptions() { + return $this->get('options')->value; + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options) { + $this->set('options', $options); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getModule() { + return $this->get('module')->value; + } + + /** + * {@inheritdoc} + */ + public function setModule($module) { + $this->set('module', $module); + return $this; + } + + /** + * {@inheritdoc} + */ + public function setExpanded($expanded) { + $this->set('expanded', $expanded ? 1 : 0); + } + + /**v + */ + public function isExpanded() { + return (bool) $this->get('expanded')->value; + } + + /** + * {@inheritdoc} + */ + public function isExternal() { + return (bool) $this->get('external')->value; + } + + /** + * {@inheritdoc} + */ + public function setCustomized($customized) { + $this->set('customized', $customized); + return $this; + } + + /** + * {@inheritdoc} + */ + public function isCustomized() { + return (bool) $this->get('customized')->value; + } + + /** + * {@inheritdoc} + */ + public function setHidden($hidden) { + $this->set('hidden', $hidden ? 1 : 0); + return $this; + } + + /** + * {@inheritdoc} + */ + public function isHidden() { + return (bool)$this->get('hidden')->value; + } + + /** + * {@inheritdoc} + */ + public function hasChildren() { + return (bool)$this->get('has_children')->value; + } + + /** + * {@inheritdoc} + */ + public function getDepth() { + return $this->get('depth')->value; + } + + /** + * {@inheritdoc} + */ + public function getWeight() { + return $this->get('weight')->value; + } + + /** + * {@inheritdoc} + */ + public function setWeight($weight) { + $this->set('weight', $weight); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMaterializedPathEntity($depth) { + if ($depth < 1 || $depth > 9) { + return NULL; + } + return $this->get('p' . $depth)->value; + } + + /** + * {@inheritdoc} + */ + public function getChangedTime() { + return $this->get('updated')->value; + } + + /** + * {@inheritdoc} + */ + public function getRouteName() { + return $this->get('route_name')->value; + } + + /** + * {@inheritdoc} + */ + public function setRouteName($route_name) { + $this->set('route_name', $route_name); + return $this; + } + + public function getAccess() { + return $this->get('access')->value; + } + + public function setAccess($access) { + $this->set('access', $access); + return $this; + } + /** + * {@inheritdoc} + */ + public function getRouteParams() { + return $this->get('route_parameters')->value; + } + + /** + * {@inheritdoc} + */ + public function setRouteParams($route_parameters) { + $this->set('route_parameters', $route_parameters); + return $this; + } + + /** + * {@inheritdoc} + */ + public static function baseFieldDefinitions($entity_type) { + $properties['menu_name'] = array( + 'label' => t('Menu name'), + 'description' => t('The menu name. All links with the same menu name (such as "tools") are part of the same menu.'), + 'type' => 'string_field', + 'settings' => array( + 'default_value' => 'tools', + ), + ); + $properties['mlid'] = array( + 'label' => t('Menu link ID'), + 'description' => t('The menu link ID.'), + 'type' => 'integer_field', + 'read-only' => TRUE, + ); + $properties['uuid'] = array( + 'label' => t('UUID'), + 'description' => t('The menu link UUID.'), + 'type' => 'uuid_field', + 'read-only' => TRUE, + ); + $properties['plid'] = array( + 'label' => t('Parent ID'), + 'description' => t('The parent menu link ID.'), + 'type' => 'entity_reference_field', + 'settings' => array('target_type' => 'menu_link'), + ); + $properties['link_path'] = array( + 'label' => t('Link path'), + 'description' => t('The Drupal path or external path this link points to.'), + 'type' => 'string_field', + ); + $properties['router_path'] = array( + 'label' => t('Router path'), + 'description' => t('For links corresponding to a Drupal path (external = 0), this connects the link to a {menu_router}.path.'), + 'type' => 'string_field', + ); + $properties['langcode'] = array( + 'label' => t('Language code'), + 'description' => t('The menu link language code.'), + 'type' => 'language_field', + ); + $properties['link_title'] = array( + 'label' => t('Title'), + 'description' => t('The text displayed for the link, which may be modified by a title callback stored in {menu_router}.'), + 'type' => 'string_field', + 'settings' => array( + 'default_value' => '', + ), + ); + $properties['options'] = array( + 'label' => t('Options'), + 'description' => t('A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.'), + 'type' => 'map_field', + ); + $properties['module'] = array( + 'label' => t('Module'), + 'description' => t('The name of the module that generated this link.'), + 'type' => 'string_field', + 'settings' => array( + 'default_value' => 'menu', + ), + ); + $properties['hidden'] = array( + 'label' => t('Hidden'), + 'description' => t('A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link).'), + 'type' => 'boolean_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + $properties['external'] = array( + 'label' => t('External'), + 'description' => t('A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).'), + 'type' => 'boolean_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + $properties['has_children'] = array( + 'label' => t('Has children'), + 'description' => t('Flag indicating whether any links have this link as a parent (1 = children exist, 0 = no children).'), + 'type' => 'boolean_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + $properties['expanded'] = array( + 'label' => t('Expanded'), + 'description' => t('Flag for whether this link should be rendered as expanded in menus - expanded links always have their child links displayed, instead of only when the link is in the active trail (1 = expanded, 0 = not expanded).'), + 'type' => 'boolean_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + $properties['weight'] = array( + 'label' => t('Weight'), + 'description' => t('Link weight among links in the same menu at the same depth.'), + 'type' => 'integer_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + $properties['depth'] = array( + 'label' => t('Depth'), + 'description' => t('The depth relative to the top level. A link with plid == 0 will have depth == 1.'), + 'type' => 'integer_field', + ); + $properties['customized'] = array( + 'label' => t('Customized'), + 'description' => t('A flag to indicate that the user has manually created or edited the link (1 = customized, 0 = not customized).'), + 'type' => 'boolean_field', + 'settings' => array( + 'default_value' => 0, + ), + ); + // @todo Declaring these pX properties as integer for the moment, we need to + // investigate if using 'entity_reference_field' cripples performance. + $properties['p1'] = array( + 'label' => t('Parent 1'), + 'description' => t('The first mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p2'] = array( + 'label' => t('Parent 2'), + 'description' => t('The second mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p3'] = array( + 'label' => t('Parent 3'), + 'description' => t('The third mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p4'] = array( + 'label' => t('Parent 4'), + 'description' => t('The fourth mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p5'] = array( + 'label' => t('Parent 5'), + 'description' => t('The fifth mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p6'] = array( + 'label' => t('Parent 6'), + 'description' => t('The sixth mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p7'] = array( + 'label' => t('Parent 7'), + 'description' => t('The seventh mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p8'] = array( + 'label' => t('Parent 8'), + 'description' => t('The eighth mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['p9'] = array( + 'label' => t('Parent 9'), + 'description' => t('The ninth mlid in the materialized path.'), + 'type' => 'integer_field', + ); + $properties['updated'] = array( + 'label' => t('Updated'), + 'description' => t('Flag that indicates that this link was generated during the update from Drupal 5.'), + 'type' => 'boolean_field', + ); + $properties['route_name'] = array( + 'label' => t('Route name'), + 'description' => t('The machine name of a defined Symfony Route this menu item represents.'), + 'type' => 'string_field', + ); + $properties['route_parameters'] = array( + 'label' => t('Route parameters'), + 'description' => t('A serialized array of route parameters of this menu link.'), + 'type' => 'map_field', + ); + + // @todo Most of these should probably go away. + $properties['access'] = array( + 'label' => t('(old router) Access'), + 'description' => t(''), + 'type' => 'boolean_field', + 'computed' => TRUE, + ); + $properties['in_active_trail'] = array( + 'label' => t('In active trail'), + 'description' => t(''), + 'type' => 'boolean_field', + 'computed' => TRUE, + ); + $properties['localized_options'] = array( + 'label' => t('Localized options'), + 'description' => t(''), + 'type' => 'map_field', + 'computed' => TRUE, + ); + return $properties; + } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php index a1c2c69..e710775 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php @@ -27,11 +27,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A switch ($operation) { case 'reset': // Reset allowed for items defined via hook_menu() and customized. - return $entity->module == 'system' && $entity->customized; + return $entity->module->value == 'system' && $entity->customized->value; case 'delete': // Only items created by the menu module can be deleted. - return $entity->module == 'menu' || $entity->updated == 1; + return $entity->module->value == 'menu' || $entity->updated->value == 1; } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php index 4f437ec..ab09332 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -7,7 +7,8 @@ namespace Drupal\menu_link; -use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityFormControllerNG; use Drupal\Core\Language\Language; use Drupal\Core\Path\AliasManagerInterface; use Drupal\Core\Routing\UrlGenerator; @@ -17,7 +18,7 @@ /** * Form controller for the node edit forms. */ -class MenuLinkFormController extends EntityFormController { +class MenuLinkFormController extends EntityFormControllerNG { /** * The menu link storage controller. @@ -79,26 +80,26 @@ public function form(array $form, array &$form_state) { $form['link_title'] = array( '#type' => 'textfield', '#title' => t('Menu link title'), - '#default_value' => $menu_link->link_title, + '#default_value' => $menu_link->link_title->value, '#description' => t('The text to be used for this link in the menu.'), '#required' => TRUE, ); foreach (array('link_path', 'mlid', 'module', 'has_children', 'options') as $key) { - $form[$key] = array('#type' => 'value', '#value' => $menu_link->{$key}); + $form[$key] = array('#type' => 'value', '#value' => $menu_link->{$key}->getValue()); } // Any item created or edited via this interface is considered "customized". $form['customized'] = array('#type' => 'value', '#value' => 1); // We are not using url() when constructing this path because it would add // $base_path. - $path = $menu_link->link_path; - if (isset($menu_link->options['query'])) { - $path .= '?' . $this->urlGenerator->httpBuildQuery($menu_link->options['query']); + $path = $menu_link->link_path->value; + if (isset($menu_link->options->query)) { + $path .= '?' . $this->urlGenerator->httpBuildQuery($menu_link->options->query); } - if (isset($menu_link->options['fragment'])) { - $path .= '#' . $menu_link->options['fragment']; + if (isset($menu_link->options->fragment)) { + $path .= '#' . $menu_link->options->fragment; } - if ($menu_link->module == 'menu') { + if ($menu_link->module->value == 'menu') { $form['link_path'] = array( '#type' => 'textfield', '#title' => t('Path'), @@ -112,33 +113,33 @@ public function form(array $form, array &$form_state) { $form['_path'] = array( '#type' => 'item', '#title' => t('Path'), - '#description' => l($menu_link->link_title, $menu_link->href, $menu_link->options), + '#description' => l($menu_link->link_title->value, $menu_link->href, $menu_link['options']), ); } $form['description'] = array( '#type' => 'textarea', '#title' => t('Description'), - '#default_value' => isset($menu_link->options['attributes']['title']) ? $menu_link->options['attributes']['title'] : '', + '#default_value' => isset($menu_link->options->attributes['title']) ? $menu_link->options->attributes['title'] : '', '#rows' => 1, '#description' => t('Shown when hovering over the menu link.'), ); $form['enabled'] = array( '#type' => 'checkbox', '#title' => t('Enabled'), - '#default_value' => !$menu_link->hidden, + '#default_value' => !$menu_link->hidden->value, '#description' => t('Menu links that are not enabled will not be listed in any menu.'), ); $form['expanded'] = array( '#type' => 'checkbox', '#title' => t('Show as expanded'), - '#default_value' => $menu_link->expanded, + '#default_value' => $menu_link->expanded->value, '#description' => t('If selected and this menu link has children, the menu will always appear expanded.'), ); // Generate a list of possible parents (not including this link or descendants). $options = menu_parent_options(menu_get_menus(), $menu_link); - $default = $menu_link->menu_name . ':' . $menu_link->plid; + $default = $menu_link->menu_name->value . ':' . $menu_link->plid->target_id; if (!isset($options[$default])) { $default = 'tools:0'; } @@ -152,13 +153,13 @@ public function form(array $form, array &$form_state) { ); // Get number of items in menu so the weight selector is sized appropriately. - $delta = $this->menuLinkStorageController->countMenuLinks($menu_link->menu_name); + $delta = $this->menuLinkStorageController->countMenuLinks($menu_link->menu_name->value); $form['weight'] = array( '#type' => 'weight', '#title' => t('Weight'), // Old hardcoded value. '#delta' => max($delta, 50), - '#default_value' => $menu_link->weight, + '#default_value' => $menu_link->weight->value, '#description' => t('Optional. In the menu, the heavier links will sink and the lighter links will be positioned nearer the top.'), ); @@ -168,13 +169,13 @@ public function form(array $form, array &$form_state) { // be configured individually. if ($this->moduleHandler->moduleExists('language')) { $language_configuration = language_get_default_configuration('menu_link', $menu_link->bundle()); - $default_langcode = ($menu_link->isNew() ? $language_configuration['langcode'] : $menu_link->langcode); + $default_langcode = ($menu_link->isNew() ? $language_configuration['langcode'] : $menu_link->langcode->value); $language_show = $language_configuration['language_show']; } // Without Language module menu links inherit the menu language and no // language selector is shown. else { - $default_langcode = ($menu_link->isNew() ? entity_load('menu', $menu_link->menu_name)->langcode : $menu_link->langcode); + $default_langcode = ($menu_link->isNew() ? entity_load('menu', $menu_link->menu_name->value)->langcode : $menu_link->langcode->value); $language_show = FALSE; } @@ -201,74 +202,65 @@ protected function actions(array $form, array &$form_state) { } /** - * Overrides EntityFormController::validate(). + * {@inheritdoc} */ public function validate(array $form, array &$form_state) { $menu_link = $this->buildEntity($form, $form_state); - $normal_path = $this->pathAliasManager->getSystemPath($menu_link->link_path); - if ($menu_link->link_path != $normal_path) { - drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $menu_link->link_path, '%normal_path' => $normal_path))); - $menu_link->link_path = $normal_path; + $normal_path = $this->pathAliasManager->getSystemPath($menu_link->getLinkPath()); + if ($menu_link->getLinkPath() != $normal_path) { + drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $menu_link->getLinkPath(), '%normal_path' => $normal_path))); $form_state['values']['link_path'] = $normal_path; + $menu_link->setLinkPath($normal_path); } - if (!url_is_external($menu_link->link_path)) { - $parsed_link = parse_url($menu_link->link_path); + if (!url_is_external($menu_link->getLinkPath())) { + $parsed_link = parse_url($menu_link->getLinkPath()); if (isset($parsed_link['query'])) { - $menu_link->options['query'] = array(); - parse_str($parsed_link['query'], $menu_link->options['query']); + $query = array(); + parse_str($parsed_link['query'], $query); + $menu_link->options->query = $query; } else { - // Use unset() rather than setting to empty string - // to avoid redundant serialized data being stored. - unset($menu_link->options['query']); + $menu_link->options->query = ''; } if (isset($parsed_link['fragment'])) { - $menu_link->options['fragment'] = $parsed_link['fragment']; + $menu_link->options->fragment = $parsed_link['fragment']; } else { - unset($menu_link->options['fragment']); + $menu_link->options->fragment = ''; } - if (isset($parsed_link['path']) && $menu_link->link_path != $parsed_link['path']) { - $menu_link->link_path = $parsed_link['path']; + if (isset($parsed_link['path']) && $menu_link->getLinkPath() != $parsed_link['path']) { + $menu_link->setLinkPath($parsed_link['path']); } } - if (!trim($menu_link->link_path) || !drupal_valid_path($menu_link->link_path, TRUE)) { - form_set_error('link_path', t("The path '@link_path' is either invalid or you do not have access to it.", array('@link_path' => $menu_link->link_path))); + if (!trim($menu_link->getLinkPath()) || !drupal_valid_path($menu_link->getLinkPath(), TRUE)) { + form_set_error('link_path', t("The path '@link_path' is either invalid or you do not have access to it.", array('@link_path' => $menu_link->getLinkPath()))); } parent::validate($form, $form_state); } - /** - * Overrides EntityFormController::submit(). - */ - public function submit(array $form, array &$form_state) { - // Build the menu link object from the submitted values. - $menu_link = parent::submit($form, $form_state); - + public function buildEntity(array $form, array &$form_state) { + $entity = parent::buildEntity($form, $form_state); // The value of "hidden" is the opposite of the value supplied by the // "enabled" checkbox. - $menu_link->hidden = (int) !$menu_link->enabled; - unset($menu_link->enabled); - - $menu_link->options['attributes']['title'] = $menu_link->description; - list($menu_link->menu_name, $menu_link->plid) = explode(':', $menu_link->parent); - - return $menu_link; + $entity->hidden->value = (int) !$form_state['values']['enabled']; + $substrs = explode(':', $form_state['values']['parent']); + $entity->setMenuName($substrs[0]); + $entity->plid = intval($substrs[1]); + $attributes = $entity->options->attributes; + $attributes['title'] = $form_state['values']['description']; + $entity->options->attributes = $attributes; + return $entity; } /** * Overrides EntityFormController::save(). */ public function save(array $form, array &$form_state) { - $menu_link = $this->entity; - - $saved = $menu_link->save(); - - if ($saved) { + if ($this->entity->save()) { drupal_set_message(t('The menu link has been saved.')); - $form_state['redirect'] = 'admin/structure/menu/manage/' . $menu_link->menu_name; + $form_state['redirect'] = 'admin/structure/menu/manage/' . $this->entity->getMenuName(); } else { drupal_set_message(t('There was an error saving the menu link.'), 'error'); @@ -280,7 +272,6 @@ public function save(array $form, array &$form_state) { * Overrides EntityFormController::delete(). */ public function delete(array $form, array &$form_state) { - $menu_link = $this->entity; - $form_state['redirect'] = 'admin/structure/menu/item/' . $menu_link->id() . '/delete'; + $form_state['redirect'] = 'admin/structure/menu/item/' . $this->entity->id() . '/delete'; } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php index b8e639e..3b307ba 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php @@ -10,7 +10,6 @@ use Symfony\Component\Routing\Route; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Provides an interface defining a menu link entity. @@ -70,10 +69,10 @@ public static function findRouteNameParameters($link_path); /** * Sets the p1 through p9 properties for a menu link entity being saved. * - * @param \Drupal\Core\Entity\EntityInterface $parent + * @param \Drupal\menu_link\MenuLinkInterface $parent * A menu link entity. */ - public function setParents(EntityInterface $parent); + public function setParents(MenuLinkInterface $parent); /** * Finds a possible parent for a given menu link entity. @@ -86,7 +85,7 @@ public function setParents(EntityInterface $parent); * - else, for system menu links (derived from hook_menu()), reparent * based on the path hierarchy. * - * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller + * @param \Drupal\menu_link\MenuLinkStorageControllerInterface $storage_controller * Storage controller object. * @param array $parent_candidates * An array of menu link entities keyed by mlid. @@ -95,5 +94,301 @@ public function setParents(EntityInterface $parent); * A menu link entity structure of the possible parent or FALSE if no valid * parent has been found. */ - public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()); + public function findParent(MenuLinkStorageControllerInterface $storage_controller, array $parent_candidates = array()); + + /** + * Returns the menu name of this menu link. + * + * @return string + * The name of the menu. + */ + public function getMenuName(); + + /** + * Sets the menu name of this menu link. + * + * @param string $menu_name + * The name of the menu. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setMenuName($menu_name); + + /** + * Returns the parent menu link ID of this menu link. + * + * @return int + * The parent link ID of the menu. + */ + public function getParentLinkId(); + + /** + * Sets the parent menu link id of this menu link. + * + * @param int $plid + * The parent link ID of the menu. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setParentLinkId($plid); + + /** + * Returns the Drupal path or external path this link points to. + * + * @return string + * The Drupal path or external path this link points to. + */ + public function getLinkPath(); + + /** + * Sets the Drupal path or external path this link points to. + * + * @param string $link_path + * The the Drupal path or external path this link points to. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setLinkPath($link_path); + + /** + * Returns the title of this menu link. + * + * @return string + * The title of this menu link. + */ + public function getLinkTitle(); + + /** + * Sets the title of this menu link. + * + * @param string $link_title + * The title of this menu link. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setLinkTitle($link_title); + + /** + * Returns the menu router path for this link. + * + * @return string + * The menu router path for this link. + */ + public function getRouterPath(); + + /** + * Sets the Drupal path or external path this link points to. + * + * @param string $router_path + * The menu router path for this link. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setRouterPath($router_path); + + /** + * Returns the menu link options. + * + * @return array + * The menu link options, to be passed to to l() or url(). + */ + public function getOptions(); + + /** + * Sets the menu link options. + * + * @todo: Add a method to add options? + * + * @param array $options + * The menu link options. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setOptions(array $options); + + /** + * Returns the name of the module that generated this link. + * + * @return string + * The name of the module that generated this link. + */ + public function getModule(); + + /** + * Sets the name of the module that generated this link. + * + * @param string $module + * The name of the module that generated this link. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setModule($module); + + /** + * Sets whether the menu link is expanded. + * + * @param bool $expanded + * TRUE if the menu link is expanded, FALSE if not. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setExpanded($expanded); + + /** + * Returns whether the menu link is expanded + * + * @return string + * TRUE if the menu link is expanded, FALSE if not. + */ + public function isExpanded(); + + /** + * Returns whether the menu link is external. + * + * @return string + * TRUE if the menu link is external, FALSE if not. + */ + public function isExternal(); + + /** + * Sets if the menu link is customized. + * + * @param bool $customized + * TRUE if the menu link is customized, FALSE if not. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setCustomized($customized); + + /** + * Returns whether the menu link is customized. + * + * @return string + * TRUE if the menu link is customized, FALSE if not. + */ + public function isCustomized(); + + /** + * Sets whether the menu link is hidden. + * + * @param bool $hidden + * TRUE if the menu link is hidden, FALSE if not. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setHidden($hidden); + + /** + * Returns whether the menu link is hidden. + * + * @return string + * TRUE if the menu link is hidden, FALSE if not. + */ + public function isHidden(); + + /** + * Returns whether the menu link is expanded + * + * @return string + * TRUE if the menu link has children, FALSE if not. + */ + public function hasChildren(); + + /** + * Returns the depth relative to the top level of this link. + * + * A link with parent ID 0 will have depth of 1. + * + * @return int + * The menu link depth. + */ + public function getDepth(); + + /** + * Returns the weight among menu links with the same depth. + * + * @return int + * The menu link weight. + */ + public function getWeight(); + + /** + * Sets the weight among menu links with the same depth. + * + *ยท@param int $weight + * The menu link weight. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setWeight($weight); + + /** + * Returns the nth depth entity ID of the materialized path. + * + * @param int $depth + * Indicates the depth of entity ID of the materialized path that should be + * returned, between 1 and 9. + * + * @return int + * Nth Entity ID of the materialized path. + */ + public function getMaterializedPathEntity($depth); + + /** + * Returns the menu link modification timestamp. + * + * @return int + * Menu link modification timestamp. + */ + public function getChangedTime(); + + /** + * Returns the route name associated with this menu link, if any. + * + * @return string|null + * The route name of this menu link. + */ + public function getRouteName(); + + /** + * Sets the route name associated with this menu link. + * + * @param string|null $route_name + * The route name associated with this menu link. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setRouteName($route_name); + + /** + * Returns the route parameters associated with this menu link, if any. + * + * @return array + * The route parameters of this menu link. + */ + public function getRouteParams(); + + /** + * Sets the route parameters associated with this menu link. + * + * @param array $route_parameters + * The route parameters associated with this menu link. + * + * @return \Drupal\menu_link\MenuLinkInterface + * The called menu link entity. + */ + public function setRouteParams($route_parameters); + } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index 1fa6140..7f691fb 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -8,7 +8,7 @@ namespace Drupal\menu_link; use Drupal\Component\Uuid\UuidInterface; -use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\Core\Entity\DatabaseStorageControllerNG; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Database\Connection; @@ -17,12 +17,9 @@ use Symfony\Cmf\Component\Routing\RouteProviderInterface; /** - * Controller class for menu links. - * - * This extends the Drupal\entity\DatabaseStorageController class, adding - * required special handling for menu_link entities. + * Defines the storage controller class for menu links. */ -class MenuLinkStorageController extends DatabaseStorageController implements MenuLinkStorageControllerInterface { +class MenuLinkStorageController extends DatabaseStorageControllerNG implements MenuLinkStorageControllerInterface { /** * Indicates whether the delete operation should re-parent children items. @@ -67,7 +64,7 @@ public function __construct($entity_type, array $entity_info, Connection $databa $this->routeProvider = $route_provider; if (empty(static::$routerItemFields)) { - static::$routerItemFields = array_diff(drupal_schema_fields_sql('menu_router'), array('weight')); + static::$routerItemFields = array_diff(drupal_schema_fields_sql('menu_router'), array('weight', 'route_name')); } } @@ -80,6 +77,7 @@ public function create(array $values) { if (!isset($values['bundle']) && isset($values['menu_name'])) { $values['bundle'] = $values['menu_name']; } + return parent::create($values); } @@ -98,7 +96,7 @@ public static function createInstance(ContainerInterface $container, $entity_typ } /** - * Overrides DatabaseStorageController::buildQuery(). + * {@inheritdoc} */ protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); @@ -109,51 +107,73 @@ protected function buildQuery($ids, $revision_id = FALSE) { } /** - * Overrides DatabaseStorageController::attachLoad(). - * - * @todo Don't call parent::attachLoad() at all because we want to be able to - * control the entity load hooks. + * {@inheritdoc} */ - protected function attachLoad(&$menu_links, $load_revision = FALSE) { + protected function attachLoad(&$queried_entities, $load_revision = FALSE) { $routes = array(); - foreach ($menu_links as &$menu_link) { - $menu_link->options = unserialize($menu_link->options); - $menu_link->route_parameters = unserialize($menu_link->route_parameters); + foreach ($queried_entities as &$record) { + $record->options = unserialize($record->options); + $record->route_parameters = isset($record->route_parameters) ? unserialize($record->route_parameters) : array(); // Use the weight property from the menu link. - $menu_link->router_item['weight'] = $menu_link->weight; + $record->router_item['weight'] = $record->weight; // By default use the menu_name as type. - $menu_link->bundle = $menu_link->menu_name; + $record->bundle = $record->menu_name; // For all links that have an associated route, load the route object now // and save it on the object. That way we avoid a select N+1 problem later. - if ($menu_link->route_name) { - $routes[$menu_link->id()] = $menu_link->route_name; + if ($record->route_name) { + $routes[$record->{$this->idKey}] = $record->route_name; } } + parent::attachLoad($queried_entities, $load_revision); + // Now mass-load any routes needed and associate them. if ($routes) { $route_objects = $this->routeProvider->getRoutesByNames($routes); foreach ($routes as $entity_id => $route) { // Not all stored routes will be valid on load. if (isset($route_objects[$route])) { - $menu_links[$entity_id]->setRouteObject($route_objects[$route]); + $queried_entities[$entity_id]->setRouteObject($route_objects[$route]); } } } + } - parent::attachLoad($menu_links, $load_revision); + /** + * {@inheritdoc} + */ + protected function mapFromStorageRecords(array $records, $load_revision = FALSE) { + $entities = parent::mapFromStorageRecords($records, $load_revision); + + foreach ($entities as &$entity) { + foreach (static::$routerItemFields as $router_field) { + $entity->offsetSet($router_field, $records[$entity->id()]->{$router_field}); + } + } + + return $entities; } /** + * Overrides DatabaseStorageControllerNG::mapToStorageRecord(). + */ + protected function mapToStorageRecord(EntityInterface $entity) { + $record = parent::mapToStorageRecord($entity); + foreach (array('options', 'route_parameters') as $property) { + $record->$property = $entity->$property->getValue(); + } + + return $record; + } + + /** * Overrides DatabaseStorageController::save(). */ public function save(EntityInterface $entity) { - $entity_class = $this->entityInfo['class']; - // We return SAVED_UPDATED by default because the logic below might not // update the entity if its values haven't changed, so returning FALSE // would be confusing in that situation. @@ -161,6 +181,9 @@ public function save(EntityInterface $entity) { $transaction = $this->database->startTransaction(); try { + // Sync the changes made in the fields array to the internal values array. + $entity->updateOriginalValues(); + // Load the stored entity, if any. if (!$entity->isNew() && !isset($entity->original)) { $entity->original = entity_load_unchanged($this->entityType, $entity->id()); @@ -183,20 +206,46 @@ public function save(EntityInterface $entity) { // array_intersect_key() with the $entity as the first parameter because // $entity may have additional keys left over from building a router entry. // The intersect removes the extra keys, allowing a meaningful comparison. - if ($entity->isNew() || (array_intersect_key(get_object_vars($entity), get_object_vars($entity->original)) != get_object_vars($entity->original))) { - $return = drupal_write_record($this->entityInfo['base_table'], $entity, $this->idKey); + if ($entity->isNew() || (array_intersect_key($entity->getPropertyValues(), $entity->original->getPropertyValues()) != $entity->original->getPropertyValues())) { + // Create the storage record to be saved. + $record = $this->mapToStorageRecord($entity); + $return = drupal_write_record($this->entityInfo['base_table'], $record, $this->idKey); if ($return) { if (!$entity->isNew()) { - $this->resetCache(array($entity->{$this->idKey})); + // @todo, should a different value be returned when saving an entity + // with $isDefaultRevision = FALSE? + if (!$entity->isDefaultRevision()) { + $return = FALSE; + } + + if ($this->revisionKey) { + $record->{$this->revisionKey} = $this->saveRevision($entity); + } + if ($this->dataTable) { + $this->savePropertyData($entity); + } + $this->resetCache(array($entity->id())); $entity->postSave($this, TRUE); $this->invokeFieldMethod('update', $entity); $this->saveFieldItems($entity, TRUE); $this->invokeHook('update', $entity); + if ($this->dataTable) { + $this->invokeTranslationHooks($entity); + } } else { $return = SAVED_NEW; - $this->resetCache(); + if ($this->revisionKey) { + $record->{$this->revisionKey} = $this->saveRevision($entity); + } + $entity->{$this->idKey}->value = $record->{$this->idKey}; + if ($this->dataTable) { + $this->savePropertyData($entity); + } + + // Reset general caches, but keep caches specific to certain entities. + $this->resetCache(array()); $entity->enforceIsNew(FALSE); $entity->postSave($this, FALSE); @@ -238,6 +287,10 @@ public function getPreventReparenting() { * {@inheritdoc} */ public function loadUpdatedCustomized(array $router_paths) { + $menu_links = array(); + + // @todo This doesn't really make sense anymore with EntityNG.. and EFQ got + // OR condition support in the meantime, so convert this query. $query = parent::buildQuery(NULL); $query ->condition(db_or() @@ -248,16 +301,12 @@ public function loadUpdatedCustomized(array $router_paths) { ->condition('customized', 1) ) ); - $query_result = $query->execute(); - if (!empty($this->entityInfo['class'])) { - // We provide the necessary arguments for PDO to create objects of the - // specified entity class. - // @see Drupal\Core\Entity\EntityInterface::__construct() - $query_result->setFetchMode(\PDO::FETCH_CLASS, $this->entityInfo['class'], array(array(), $this->entityType)); + if ($ids = $query->execute()->fetchCol(1)) { + $menu_links = $this->load($ids); } - return $query_result->fetchAllAssoc($this->idKey); + return $menu_links; } /** @@ -281,13 +330,13 @@ public function loadModuleAdminTasks() { */ public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE) { // If plid == 0, there is nothing to update. - if ($entity->plid) { + if ($entity->plid->target_id) { // Check if at least one visible child exists in the table. $query = \Drupal::entityQuery($this->entityType); $query - ->condition('menu_name', $entity->menu_name) + ->condition('menu_name', $entity->menu_name->value) ->condition('hidden', 0) - ->condition('plid', $entity->plid) + ->condition('plid', $entity->plid->target_id) ->count(); if ($exclude) { @@ -297,7 +346,7 @@ public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE) $parent_has_children = ((bool) $query->execute()) ? 1 : 0; $this->database->update('menu_links') ->fields(array('has_children' => $parent_has_children)) - ->condition('mlid', $entity->plid) + ->condition('mlid', $entity->plid->target_id) ->execute(); } } @@ -310,20 +359,20 @@ public function findChildrenRelativeDepth(EntityInterface $entity) { // make sense to convert to EFQ? $query = $this->database->select('menu_links'); $query->addField('menu_links', 'depth'); - $query->condition('menu_name', $entity->menu_name); + $query->condition('menu_name', $entity->menu_name->value); $query->orderBy('depth', 'DESC'); $query->range(0, 1); $i = 1; $p = 'p1'; - while ($i <= MENU_MAX_DEPTH && $entity->{$p}) { - $query->condition($p, $entity->{$p}); + while ($i <= MENU_MAX_DEPTH && $entity->{$p}->value) { + $query->condition($p, $entity->{$p}->value); $p = 'p' . ++$i; } $max_depth = $query->execute()->fetchField(); - return ($max_depth > $entity->depth) ? $max_depth - $entity->depth : 0; + return ($max_depth > $entity->depth->value) ? $max_depth - $entity->depth->value : 0; } /** @@ -332,14 +381,14 @@ public function findChildrenRelativeDepth(EntityInterface $entity) { public function moveChildren(EntityInterface $entity) { $query = $this->database->update($this->entityInfo['base_table']); - $query->fields(array('menu_name' => $entity->menu_name)); + $query->fields(array('menu_name' => $entity->menu_name->value)); $p = 'p1'; $expressions = array(); - for ($i = 1; $i <= $entity->depth; $p = 'p' . ++$i) { - $expressions[] = array($p, ":p_$i", array(":p_$i" => $entity->{$p})); + for ($i = 1; $i <= $entity->depth->value; $p = 'p' . ++$i) { + $expressions[] = array($p, ":p_$i", array(":p_$i" => $entity->{$p}->value)); } - $j = $entity->original->depth + 1; + $j = $entity->original->depth->value + 1; while ($i <= MENU_MAX_DEPTH && $j <= MENU_MAX_DEPTH) { $expressions[] = array('p' . $i++, 'p' . $j++, array()); } @@ -347,7 +396,7 @@ public function moveChildren(EntityInterface $entity) { $expressions[] = array('p' . $i++, 0, array()); } - $shift = $entity->depth - $entity->original->depth; + $shift = $entity->depth->value - $entity->original->depth->value; if ($shift > 0) { // The order of expressions must be reversed so the new values don't // overwrite the old ones before they can be used because "Single-table @@ -360,10 +409,10 @@ public function moveChildren(EntityInterface $entity) { } $query->expression('depth', 'depth + :depth', array(':depth' => $shift)); - $query->condition('menu_name', $entity->original->menu_name); + $query->condition('menu_name', $entity->original->menu_name->value); $p = 'p1'; - for ($i = 1; $i <= MENU_MAX_DEPTH && $entity->original->{$p}; $p = 'p' . ++$i) { - $query->condition($p, $entity->original->{$p}); + for ($i = 1; $i <= MENU_MAX_DEPTH && $entity->original->{$p}->value; $p = 'p' . ++$i) { + $query->condition($p, $entity->original->{$p}->value); } $query->execute(); @@ -387,7 +436,7 @@ public function countMenuLinks($menu_name) { * {@inheritdoc} */ public function getParentFromHierarchy(EntityInterface $entity) { - $parent_path = $entity->link_path; + $parent_path = $entity->link_path->value; do { $parent = FALSE; $parent_path = substr($parent_path, 0, strrpos($parent_path, '/')); @@ -398,7 +447,7 @@ public function getParentFromHierarchy(EntityInterface $entity) { ->condition('module', 'system') // We always respect the link's 'menu_name'; inheritance for router // items is ensured in _menu_router_build(). - ->condition('menu_name', $entity->menu_name) + ->condition('menu_name', $entity->menu_name->value) ->condition('link_path', $parent_path); $result = $query->execute(); diff --git a/core/modules/menu_link/menu_link.api.php b/core/modules/menu_link/menu_link.api.php index bfb8a2e..f5ec959 100644 --- a/core/modules/menu_link/menu_link.api.php +++ b/core/modules/menu_link/menu_link.api.php @@ -32,7 +32,7 @@ */ function hook_menu_link_load($menu_links) { foreach ($menu_links as $menu_link) { - if ($menu_link->href == 'devel/cache/clear') { + if ($menu_link->href->value == 'devel/cache/clear') { $menu_link->options['query'] = drupal_get_destination(); } } @@ -49,17 +49,17 @@ function hook_menu_link_load($menu_links) { */ function hook_menu_link_presave(\Drupal\menu_link\Entity\MenuLink $menu_link) { // Make all new admin links hidden (a.k.a disabled). - if (strpos($menu_link->link_path, 'admin') === 0 && $menu_link->isNew()) { + if (strpos($menu_link->link_path->value, 'admin') === 0 && $menu_link->isNew()) { $menu_link->hidden = 1; } // Flag a link to be altered by hook_menu_link_load(). - if ($menu_link->link_path == 'devel/cache/clear') { + if ($menu_link->link_path->value == 'devel/cache/clear') { $menu_link->options['alter'] = TRUE; } // Flag a menu link to be altered by hook_menu_link_load(), but only if it is // derived from a menu router item; i.e., do not alter a custom menu link // pointing to the same path that has been created by a user. - if ($menu_link->link_path == 'user' && $menu_link->module == 'system') { + if ($menu_link->link_path->value == 'user' && $menu_link->module == 'system') { $menu_link->options['alter'] = TRUE; } } @@ -82,7 +82,7 @@ function hook_menu_link_insert(\Drupal\menu_link\Entity\MenuLink $menu_link) { // In our sample case, we track menu items as editing sections // of the site. These are stored in our table as 'disabled' items. $record['mlid'] = $menu_link->id(); - $record['menu_name'] = $menu_link->menu_name; + $record['menu_name'] = $menu_link->menu_name->value; $record['status'] = 0; drupal_write_record('menu_example', $record); } @@ -104,9 +104,9 @@ function hook_menu_link_insert(\Drupal\menu_link\Entity\MenuLink $menu_link) { function hook_menu_link_update(\Drupal\menu_link\Entity\MenuLink $menu_link) { // If the parent menu has changed, update our record. $menu_name = db_query("SELECT menu_name FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $menu_link->id()))->fetchField(); - if ($menu_name != $menu_link->menu_name) { + if ($menu_name != $menu_link->menu_name->value) { db_update('menu_example') - ->fields(array('menu_name' => $menu_link->menu_name)) + ->fields(array('menu_name' => $menu_link->menu_name->value)) ->condition('mlid', $menu_link->id()) ->execute(); } diff --git a/core/modules/menu_link/menu_link.module b/core/modules/menu_link/menu_link.module index 7e0358e..b7b4449 100644 --- a/core/modules/menu_link/menu_link.module +++ b/core/modules/menu_link/menu_link.module @@ -208,7 +208,7 @@ function menu_link_system_breadcrumb_alter(array &$breadcrumb, array $attributes $menu_link = $attributes['menu_link']; if (($menu_link instanceof MenuLinkInterface) && !$menu_link->isNew()) { // Add a link to the menu admin screen. - $menu = entity_load('menu', $menu_link->menu_name); + $menu = entity_load('menu', $menu_link->menu_name->value); $breadcrumb[] = Drupal::l($menu->label(), 'menu.menu_edit', array('menu' => $menu->id)); } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php index a0012dc..6f0008f 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php @@ -33,7 +33,7 @@ public function getFormID() { * {@inheritdoc} */ public function getQuestion() { - return t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->menuLink->link_title)); + return t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->menuLink->link_title->value)); } /** @@ -43,7 +43,7 @@ public function getCancelRoute() { return array( 'route_name' => 'shortcut.set_customize', 'route_parameters' => array( - 'shortcut_set' => str_replace('shortcut-', '', $this->menuLink->menu_name), + 'shortcut_set' => str_replace('shortcut-', '', $this->menuLink->menu_name->value), ), ); } @@ -68,10 +68,10 @@ public function buildForm(array $form, array &$form_state, MenuLink $menu_link = * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { - menu_link_delete($this->menuLink->mlid); - $set_name = str_replace('shortcut-', '' , $this->menuLink->menu_name); + menu_link_delete($this->menuLink->id()); + $set_name = str_replace('shortcut-', '' , $this->menuLink->menu_name->value); $form_state['redirect'] = 'admin/config/user-interface/shortcut/manage/' . $set_name; - drupal_set_message(t('The shortcut %title has been deleted.', array('%title' => $this->menuLink->link_title))); + drupal_set_message(t('The shortcut %title has been deleted.', array('%title' => $this->menuLink->link_title->value))); } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php index 29da4a8..97aafee 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php @@ -38,13 +38,13 @@ public function form(array $form, array &$form_state) { foreach ($this->entity->links as $link) { $mlid = $link->id(); $form['shortcuts']['links'][$mlid]['#attributes']['class'][] = 'draggable'; - $form['shortcuts']['links'][$mlid]['name']['#markup'] = l($link->link_title, $link->link_path); - $form['shortcuts']['links'][$mlid]['#weight'] = $link->weight; + $form['shortcuts']['links'][$mlid]['name']['#markup'] = l($link->link_title->value, $link->link_path->value); + $form['shortcuts']['links'][$mlid]['#weight'] = $link->weight->value; $form['shortcuts']['links'][$mlid]['weight'] = array( '#type' => 'weight', - '#title' => t('Weight for @title', array('@title' => $link->link_title)), + '#title' => t('Weight for @title', array('@title' => $link->link_title->value)), '#title_display' => 'invisible', - '#default_value' => $link->weight, + '#default_value' => $link->weight->value, '#attributes' => array('class' => array('shortcut-weight')), ); @@ -88,7 +88,7 @@ protected function actions(array $form, array &$form_state) { */ public function save(array $form, array &$form_state) { foreach ($this->entity->links as $link) { - $link->weight = $form_state['values']['shortcuts']['links'][$link->mlid]['weight']; + $link->weight = $form_state['values']['shortcuts']['links'][$link->id()]['weight']; $link->save(); } drupal_set_message(t('The shortcut set has been updated.')); diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php index bd2d194..08d70dc 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php @@ -78,7 +78,7 @@ function testShortcutQuickLink() { $link = reset($this->set->links); - $this->drupalGet($link->link_path); + $this->drupalGet($link->getLinkPath()); $this->assertRaw(t('Remove from %title shortcuts', array('%title' => $this->set->label())), '"Add to shortcuts" link properly switched to "Remove from shortcuts".'); } @@ -92,7 +92,7 @@ function testShortcutLinkRename() { $new_link_name = $this->randomName(); $link = reset($set->links); - $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->mlid, array('shortcut_link[link_title]' => $new_link_name, 'shortcut_link[link_path]' => $link->link_path), t('Save')); + $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->id(), array('shortcut_link[link_title]' => $new_link_name, 'shortcut_link[link_path]' => $link->getLinkPath()), t('Save')); $saved_set = shortcut_set_load($set->id()); $titles = $this->getShortcutInformation($saved_set, 'link_title'); $this->assertTrue(in_array($new_link_name, $titles), 'Shortcut renamed: ' . $new_link_name); @@ -109,7 +109,7 @@ function testShortcutLinkChangePath() { $new_link_path = 'admin/config'; $link = reset($set->links); - $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->mlid, array('shortcut_link[link_title]' => $link->link_title, 'shortcut_link[link_path]' => $new_link_path), t('Save')); + $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->id(), array('shortcut_link[link_title]' => $link->getLinkTitle(), 'shortcut_link[link_path]' => $new_link_path), t('Save')); $saved_set = shortcut_set_load($set->id()); $paths = $this->getShortcutInformation($saved_set, 'link_path'); $this->assertTrue(in_array($new_link_path, $paths), 'Shortcut path changed: ' . $new_link_path); @@ -123,10 +123,10 @@ function testShortcutLinkDelete() { $set = $this->set; $link = reset($set->links); - $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->mlid . '/delete', array(), 'Delete'); + $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $link->id() . '/delete', array(), 'Delete'); $saved_set = shortcut_set_load($set->id()); $mlids = $this->getShortcutInformation($saved_set, 'mlid'); - $this->assertFalse(in_array($link->mlid, $mlids), 'Successfully deleted a shortcut.'); + $this->assertFalse(in_array($link->id(), $mlids), 'Successfully deleted a shortcut.'); // Delete all the remaining shortcut menu links. foreach (array_filter($mlids) as $mlid) { diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php index 06088ef..2fcfa5b 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php @@ -129,7 +129,7 @@ function generateShortcutLink($path, $title = '') { function getShortcutInformation($set, $key) { $info = array(); foreach ($set->links as $uuid => $link) { - $info[] = $link->{$key}; + $info[] = $link->{$key}->value; } return $info; } diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 8ca0472..355bc61 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -56,7 +56,7 @@ function shortcut_entity_bundle_info() { function shortcut_menu_link_load($entities) { foreach ($entities as $entity) { // Change the bundle of menu links related to a shortcut. - if (strpos($entity->menu_name, 'shortcut-') === 0) { + if (strpos($entity->menu_name->value, 'shortcut-') === 0) { $entity->bundle = 'shortcut'; } } @@ -219,9 +219,9 @@ function shortcut_link_access($menu_link) { */ function shortcut_menu_link_delete($menu_link) { // If the deleted menu link was in a shortcut set, remove it. - if (strpos($menu_link->menu_name, 'shortcut-') === 0) { - $shortcut = entity_load('shortcut_set', str_replace('shortcut-', '', $menu_link->menu_name)); - unset($shortcut->links[$menu_link->uuid]); + if (strpos($menu_link->menu_name->value, 'shortcut-') === 0) { + $shortcut = entity_load('shortcut_set', str_replace('shortcut-', '', $menu_link->menu_name->value)); + unset($shortcut->links[$menu_link->uuid()]); $shortcut->save(); } } @@ -458,8 +458,8 @@ function shortcut_preprocess_page(&$variables) { // Check if $link is already a shortcut and set $link_mode accordingly. foreach ($shortcut_set->links as $shortcut) { - if ($link == $shortcut['link_path']) { - $mlid = $shortcut['mlid']; + if ($link == $shortcut->getLinkPath()) { + $mlid = $shortcut->id(); break; } } diff --git a/core/modules/system/lib/Drupal/system/Controller/SystemController.php b/core/modules/system/lib/Drupal/system/Controller/SystemController.php index eaaa8a0..b5eef16 100644 --- a/core/modules/system/lib/Drupal/system/Controller/SystemController.php +++ b/core/modules/system/lib/Drupal/system/Controller/SystemController.php @@ -78,7 +78,7 @@ public function overview() { $system_link = reset($system_link); $query = $this->queryFactory->get('menu_link') ->condition('link_path', 'admin/help', '<>') - ->condition('menu_name', $system_link->menu_name) + ->condition('menu_name', $system_link->getMenuName()) ->condition('plid', $system_link->id()) ->condition('hidden', 0); $result = $query->execute(); @@ -86,16 +86,20 @@ public function overview() { $menu_links = $menu_link_storage->loadMultiple($result); foreach ($menu_links as $item) { _menu_link_translate($item); - if (!$item['access']) { + if (!$item->getAccess()) { continue; } // The link description, either derived from 'description' in hook_menu() // or customized via menu module is used as title attribute. - if (!empty($item['localized_options']['attributes']['title'])) { - $item['description'] = $item['localized_options']['attributes']['title']; - unset($item['localized_options']['attributes']['title']); + if (!empty($item->localized_options->attributes['title'])) { + $item['description'] = $item->localized_options->attributes['title']; + unset($item->localized_options->attributes['title']); } - $block = $item; + $block = array( + 'title' => $item->getLinkTitle(), + 'description' => $item['description'], + 'position' => $item['position'], + ); $block['content'] = array( '#theme' => 'admin_block_content', '#content' => $this->systemManager->getAdminBlock($item), @@ -107,7 +111,7 @@ public function overview() { // Prepare for sorting as in function _menu_tree_check_access(). // The weight is offset so it is always positive, with a uniform 5-digits. - $blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block; + $blocks[(50000 + $item->getWeight()) . ' ' . $item['title'] . ' ' . $item->id()] = $block; } } } diff --git a/core/modules/system/lib/Drupal/system/SystemManager.php b/core/modules/system/lib/Drupal/system/SystemManager.php index 619642e..57d893f 100644 --- a/core/modules/system/lib/Drupal/system/SystemManager.php +++ b/core/modules/system/lib/Drupal/system/SystemManager.php @@ -198,7 +198,7 @@ public function getAdminBlock($item) { $menu_links = $this->menuLinkStorage->loadByProperties(array('router_path' => $item['path'], 'module' => 'system')); $menu_link = reset($menu_links); $item['mlid'] = $menu_link->id(); - $item['menu_name'] = $menu_link->menu_name; + $item['menu_name'] = $menu_link->menu_name->value; } if (isset($this->menuItems[$item['mlid']])) { @@ -209,16 +209,16 @@ public function getAdminBlock($item) { $menu_links = $this->menuLinkStorage->loadByProperties(array('plid' => $item['mlid'], 'menu_name' => $item['menu_name'], 'hidden' => 0)); foreach ($menu_links as $link) { _menu_link_translate($link); - if ($link['access']) { + if ($link->getAccess()) { // The link description, either derived from 'description' in // hook_menu() or customized via menu module is used as title attribute. - if (!empty($link['localized_options']['attributes']['title'])) { - $link['description'] = $link['localized_options']['attributes']['title']; - unset($link['localized_options']['attributes']['title']); + if (!empty($link->localized_options->attributes['title'])) { + $link['description'] = $link->localized_options->attributes['title']; + unset($link->localized_options->attributes['title']); } // Prepare for sorting as in function _menu_tree_check_access(). // The weight is offset so it is always positive, with a uniform 5-digits. - $key = (50000 + $link['weight']) . ' ' . Unicode::strtolower($link['title']) . ' ' . $link['mlid']; + $key = (50000 + $link->getWeight()) . ' ' . Unicode::strtolower($link['title']) . ' ' . $link->id(); $content[$key] = $link; } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php index bcf7c96..b05f9e3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php @@ -246,19 +246,19 @@ public function testRouterIntegration() { 'link_path' => 'router_test/test1', )); $menu_link->save(); - $this->assertEqual($menu_link->route_name, 'router_test.1'); - $this->assertEqual($menu_link->route_parameters, array()); + $this->assertEqual($menu_link->getRouteName(), 'router_test.1'); + $this->assertEqual($menu_link->getRouteParams(), array()); $menu_link = entity_create('menu_link', array( 'link_path' => 'router_test/test3/test', )); $menu_link->save(); - $this->assertEqual($menu_link->route_name, 'router_test.3'); - $this->assertEqual($menu_link->route_parameters, array('value' => 'test')); + $this->assertEqual($menu_link->getRouteName(), 'router_test.3'); + $this->assertEqual($menu_link->getRouteParams(), 'test'); $menu_link = entity_load('menu_link', $menu_link->id()); - $this->assertEqual($menu_link->route_name, 'router_test.3'); - $this->assertEqual($menu_link->route_parameters, array('value' => 'test')); + $this->assertEqual($menu_link->getRouteName(), 'router_test.3'); + $this->assertEqual($menu_link->getRouteParams(), 'test'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php index 381e891..86e1eb3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php @@ -323,7 +323,7 @@ function testMenuName() { $menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test')); $menu_link = reset($menu_links); - $this->assertEqual($menu_link->menu_name, 'original', 'Menu name is "original".'); + $this->assertEqual($menu_link->menu_name->value, 'original', 'Menu name is "original".'); // Change the menu_name parameter in menu_test.module, then force a menu // rebuild. @@ -333,7 +333,7 @@ function testMenuName() { $menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test')); $menu_link = reset($menu_links); - $this->assertEqual($menu_link->menu_name, 'changed', 'Menu name was successfully changed after rebuild.'); + $this->assertEqual($menu_link->menu_name->value, 'changed', 'Menu name was successfully changed after rebuild.'); } /** @@ -364,7 +364,7 @@ function testMenuHidden() { $links = array(); foreach ($menu_links as $menu_link) { - $links[$menu_link->router_path] = $menu_link; + $links[$menu_link->router_path->value] = $menu_link; } $parent = $links['menu-test/hidden/menu']; @@ -416,7 +416,7 @@ function testMenuHidden() { $links = array(); foreach ($menu_links as $menu_link) { - $links[$menu_link->router_path] = $menu_link; + $links[$menu_link->router_path->value] = $menu_link; } $parent = $links['menu-test/hidden/block']; diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php index df10877..c54a2aa 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php @@ -38,7 +38,7 @@ class TreeAccessTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('menu_link'); + public static $modules = array('field', 'menu_link'); public static function getInfo() { return array( @@ -100,8 +100,8 @@ public function testRouteItemMenuLinksAccess() { // Setup the links with the route items. $this->links = array( - new MenuLink(array('mlid' => 1, 'route_name' => 'menu_test_1', 'depth' => 1, 'link_path' => 'menu_test/test_1'), 'menu_link'), - new MenuLink(array('mlid' => 2, 'route_name' => 'menu_test_2', 'depth' => 1, 'link_path' => 'menu_test/test_2'), 'menu_link'), + entity_create('menu_link', array('mlid' => 1, 'route_name' => 'menu_test_1', 'depth' => 1, 'link_path' => 'menu_test/test_1')), + entity_create('menu_link', array('mlid' => 2, 'route_name' => 'menu_test_2', 'depth' => 1, 'link_path' => 'menu_test/test_2')), ); // Build the menu tree and check access for all of the items. diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeDataUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeDataUnitTest.php index 8b6c4a1..ce4c9ab 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeDataUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeDataUnitTest.php @@ -8,12 +8,20 @@ namespace Drupal\system\Tests\Menu; use Drupal\menu_link\Entity\MenuLink; -use Drupal\simpletest\UnitTestBase; +use Drupal\simpletest\DrupalUnitTestBase; /** * Menu tree data related tests. */ -class TreeDataUnitTest extends UnitTestBase { +class TreeDataUnitTest extends DrupalUnitTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('field', 'menu_link'); + /** * Dummy link structure acceptable for menu_tree_data(). */ @@ -32,11 +40,11 @@ public static function getInfo() { */ public function testMenuTreeData() { $this->links = array( - 1 => new MenuLink(array('mlid' => 1, 'depth' => 1), 'menu_link'), - 2 => new MenuLink(array('mlid' => 2, 'depth' => 1), 'menu_link'), - 3 => new MenuLink(array('mlid' => 3, 'depth' => 2), 'menu_link'), - 4 => new MenuLink(array('mlid' => 4, 'depth' => 3), 'menu_link'), - 5 => new MenuLink(array('mlid' => 5, 'depth' => 1), 'menu_link'), + 1 => entity_create('menu_link', array('mlid' => 1, 'depth' => 1)), + 2 => entity_create('menu_link', array('mlid' => 2, 'depth' => 1)), + 3 => entity_create('menu_link', array('mlid' => 3, 'depth' => 2)), + 4 => entity_create('menu_link', array('mlid' => 4, 'depth' => 3)), + 5 => entity_create('menu_link', array('mlid' => 5, 'depth' => 1)), ); $tree = menu_tree_data($this->links); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index f1a428f..581ce30 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -344,7 +344,7 @@ function theme_admin_block_content($variables) { } $output .= '
    '; foreach ($content as $item) { - $output .= '
    ' . l($item['title'], $item['href'], $item['localized_options']) . '
    '; + $output .= '
    ' . l($item->getLinkTitle(), $item->getLinkPath(), $item['localized_options']) . '
    '; if (!$compact && isset($item['description'])) { $output .= '
    ' . filter_xss_admin($item['description']) . '
    '; } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 596122b..68f831e 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -2288,6 +2288,7 @@ function system_update_8060() { 'size' => 'big', 'not null' => FALSE, 'serialize' => TRUE, + 'initial' => 'a:0:{}', ); db_add_field('menu_links', 'route_parameters', $spec); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index fb96b52..38c1452 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2900,9 +2900,9 @@ function system_get_module_admin_tasks($module, $info) { $task = $links[$path]; // The link description, either derived from 'description' in // hook_menu() or customized via menu module is used as title attribute. - if (!empty($task['localized_options']['attributes']['title'])) { - $task['description'] = $task['localized_options']['attributes']['title']; - unset($task['localized_options']['attributes']['title']); + if (!empty($link->localized_options->attributes['title'])) { + $link['description'] = $link->localized_options->attributes['title']; + unset($link->localized_options->attributes['title']); } // Check the admin tasks for duplicate names. If one is found, diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index b20474b..a31a393 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -495,9 +495,9 @@ function toolbar_get_menu_tree() { if (!empty($result)) { $admin_link = menu_link_load(reset($result)); $tree = menu_build_tree('admin', array( - 'expanded' => array($admin_link['mlid']), - 'min_depth' => $admin_link['depth'] + 1, - 'max_depth' => $admin_link['depth'] + 1, + 'expanded' => array($admin_link->id()), + 'min_depth' => $admin_link->getDepth() + 1, + 'max_depth' => $admin_link->getDepth() + 1, )); } @@ -521,11 +521,11 @@ function toolbar_menu_navigation_links(&$tree) { } // Make sure we have a path specific ID in place, so we can attach icons // and behaviors to the items. - $tree[$key]['link']['localized_options']['attributes'] = array( - 'id' => 'toolbar-link-' . str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['link_path']), + $l_options = $tree[$key]['link']->localized_options->attributes = array( + 'id' => 'toolbar-link-' . str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']->getLinkPath()), 'class' => array( 'toolbar-icon', - 'toolbar-icon-' . strtolower(str_replace(' ', '-', $item['link']['link_title'])), + 'toolbar-icon-' . strtolower(str_replace(' ', '-', $item['link']->getLinkTitle())), ), 'title' => check_plain($item['link']['description']), ); @@ -540,16 +540,17 @@ function toolbar_get_rendered_subtrees() { $tree = toolbar_get_menu_tree(); foreach ($tree as $tree_item) { $item = $tree_item['link']; - if (!$item['hidden'] && $item['access']) { - if ($item['has_children']) { + if (!$item->isHidden() && $item->getAccess()) { + if ($item->hasChildren()) { $query = db_select('menu_links'); $query->addField('menu_links', 'mlid'); $query->condition('has_children', 1); - for ($i=1; $i <= $item['depth']; $i++) { - $query->condition('p' . $i, $item['p' . $i]); + for ($i=1; $i <= $item->getDepth(); $i++) { + $p_i = 'p' . $i; + $query->condition('p' . $i, $item->{$p_i}->value); } $parents = $query->execute()->fetchCol(); - $subtree = menu_build_tree($item['menu_name'], array('expanded' => $parents, 'min_depth' => $item['depth']+1)); + $subtree = menu_build_tree($item->getMenuName(), array('expanded' => $parents, 'min_depth' => $item->getDepth()+1)); toolbar_menu_navigation_links($subtree); $subtree = menu_tree_output($subtree); $subtree = drupal_render($subtree); @@ -655,7 +656,7 @@ function toolbar_modules_uninstalled($modules) { * Implements hook_ENTITY_TYPE_update(). */ function toolbar_menu_link_update(MenuLinkInterface $menu_link) { - if ($menu_link->get('menu_name') === 'admin') { + if ($menu_link->getMenuName() === 'admin') { _toolbar_clear_user_cache(); } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 24aee74..ac0de9f 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -877,13 +877,13 @@ function user_menu_link_presave(MenuLink $menu_link) { // for authenticated users. Authenticated users should see "My account", but // anonymous users should not see it at all. Therefore, invoke // user_menu_link_load() to conditionally hide the link. - if ($menu_link->link_path == 'user' && $menu_link->module == 'system') { - $menu_link->options['alter'] = TRUE; + if ($menu_link->getLinkPath() == 'user' && $menu_link->getModule() == 'system') { + //$menu_link->options['alter'] = TRUE; } // Force the Logout link to appear on the top-level of 'account' menu by // default (i.e., unless it has been customized). - if ($menu_link->link_path == 'user/logout' && $menu_link->module == 'system' && empty($menu_link->customized)) { + if ($menu_link->getLinkPath() == 'user/logout' && $menu_link->getModule() == 'system' && !$menu_link->isCustomized()) { $menu_link->plid = 0; } } @@ -905,8 +905,8 @@ function user_menu_breadcrumb_alter(&$active_trail, $item) { function user_menu_link_load($menu_links) { // Hide the "User account" link for anonymous users. foreach ($menu_links as $link) { - if ($link['link_path'] == 'user' && $link['module'] == 'system' && !$GLOBALS['user']->id()) { - $link['hidden'] = 1; + if ($link->getLinkPath() == 'user' && $link->getModule() == 'system' && $GLOBALS['user']->isAnonymous()) { + $link->hidden = 1; } } }