diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index f55f281..e94f4c8 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -17,6 +17,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Route;
+use Drupal\menu_link\MenuLinkInterface;
/**
* @defgroup menu Menu system
@@ -637,14 +638,14 @@ function _menu_check_access(&$item, $map) {
*/
function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
$title_callback = $item['title_callback'];
- $item['localized_options'] = $item['options'];
+ $options = $item['options'];
// All 'class' attributes are assumed to be an array during rendering, but
// links stored in the database may use an old string value.
// @todo In order to remove this code we need to implement a database update
// 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 (isset($options['attributes']['class']) && is_string($options['attributes']['class'])) {
+ $options['attributes']['class'] = explode(' ', $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
@@ -672,7 +673,7 @@ 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;
+ $options['html'] = TRUE;
}
}
}
@@ -708,8 +709,15 @@ 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($options['attributes']['title']) && $options['attributes']['title'] == $original_description) {
+ $options['title'] = $item['description'];
+ }
+
+ if ($item instanceof MenuLinkInterface) {
+ $item->localized_options->setValue($options);
+ }
+ else {
+ $item['localized_options'] = $options;
}
}
@@ -873,21 +881,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']);
@@ -902,7 +907,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;
@@ -910,7 +915,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);
}
}
}
@@ -918,17 +923,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
@@ -938,7 +943,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);
}
}
@@ -946,7 +951,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);
}
@@ -1098,7 +1103,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;
}
}
@@ -1116,45 +1121,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']->inActiveTrail()) {
$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;
@@ -1362,12 +1370,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
@@ -1532,11 +1541,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']) {
@@ -1583,14 +1592,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->inActiveTrail() && 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.
@@ -1641,9 +1650,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(),
);
@@ -1651,14 +1660,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;
}
}
@@ -1917,12 +1926,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']->inActiveTrail()) {
$class = ' active-trail';
$l['attributes']['class'][] = 'active-trail';
}
@@ -1934,7 +1943,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;
@@ -2482,7 +2491,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.
@@ -2493,7 +2502,7 @@ function menu_set_active_trail($new_trail = NULL) {
while ($curr) {
$link = $curr['link'];
- if ($link['in_active_trail']) {
+ if ($link->inActiveTrail()) {
// 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
@@ -2507,7 +2516,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;
}
}
@@ -2585,10 +2594,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();
}
}
@@ -2601,7 +2610,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.
@@ -2844,6 +2853,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.
@@ -2851,9 +2862,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);
$existing_item->route_parameters = unserialize($existing_item->route_parameters);
@@ -2880,8 +2890,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->isCustomized()) {
+ $parent_candidates[$existing_item->id()] = $existing_item;
}
else {
$menu_link = MenuLink::buildFromRouterItem($router_item);
@@ -2898,11 +2908,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->getLinkPath());
+ if (!empty($router_path) && ($router_path != $menu_link->getRouterPath() || $menu_link->getChangedTime())) {
// 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->getChangedTime() && $router_path != $menu_link->getLinkPath();
$menu_link->router_path = $router_path;
$menu_link->updated = (int) $updated;
diff --git a/core/includes/path.inc b/core/includes/path.inc
index 9c41abd..4c7aab7 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -6,6 +6,7 @@
*/
use Symfony\Component\HttpFoundation\Request;
+use Drupal\menu_link\Entity\MenuLink;
/**
* Check if the current page is the front page.
@@ -201,10 +202,9 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
elseif ($dynamic_allowed && preg_match('/\/\%/', $path)) {
// Path is dynamic (ie 'user/%'), so check directly against menu_router table.
if ($item = db_query("SELECT * FROM {menu_router} where path = :path", array(':path' => $path))->fetchAssoc()) {
- $item['link_path'] = $item['path'];
- $item['link_title'] = $item['title'];
- $item['external'] = FALSE;
- $item['options'] = '';
+ $item = MenuLink::buildFromRouterItem($item);
+ $item['external'] = FALSE;
+ $item['options'] = array();
_menu_link_translate($item);
}
}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index e49bb76..ee1b997 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1720,9 +1720,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'] : String::checkPlain($link['title']));
if (isset($link['attributes'])) {
$item = '' . $item . '';
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..b79aa6d
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
@@ -0,0 +1,66 @@
+values = array();
+ if (!isset($values)) {
+ return;
+ }
+
+ if (!is_array($values)) {
+ if ($values instanceof MapItem) {
+ $values = $values->getValue();
+ }
+ else {
+ $values = unserialize($values);
+ }
+ }
+
+ $this->values = $values;
+ }
+
+ public function __get($name) {
+ if (!isset($this->values[$name])) {
+ $this->values[$name] = array();
+ }
+
+ return $this->values[$name];
+ }
+
+ public function __set($name, $value) {
+ if (isset($value)) {
+ $this->values[$name] = $value;
+ }
+ else {
+ unset($this->values[$name]);
+ }
+ }
+}
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index aef8a52..1b12cc2 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->getMenuName(), '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 dd4f919..b0598be 100644
--- a/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php
+++ b/core/modules/book/lib/Drupal/book/BookBreadcrumbBuilder.php
@@ -63,8 +63,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->l($menu_link->label(), $menu_link->route_name, $menu_link->route_parameters, $menu_link->options);
+ if ($this->accessManager->checkNamedRoute($menu_link->getRouteName(), $menu_link->route_parameters[0]->getValue())) {
+ $links[] = $this->l($menu_link->label(), $menu_link->getRouteName(), $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..3c58a67 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->getLinkTitle()));
}
/**
@@ -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->getMenuName(),
),
);
}
@@ -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..db2dcc0 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->getLinkTitle()));
}
/**
@@ -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->getMenuName(),
),
);
}
@@ -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 8316c8b..84a1da1 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->getMenuName(), $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 b3d12d6..33c87e2 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -338,7 +338,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()));
}
}
}
@@ -363,22 +363,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');
}
@@ -548,7 +550,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;
@@ -572,7 +574,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 d701640..ed5b0dc 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,17 +7,13 @@
namespace Drupal\menu_link\Entity;
-use Drupal\Core\Language\Language;
+use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
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.
*
@@ -49,14 +45,7 @@
* }
* )
*/
-class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface {
-
- /**
- * The link's menu name.
- *
- * @var string
- */
- public $menu_name = 'tools';
+class MenuLink extends ContentEntityBase implements \ArrayAccess, MenuLinkInterface {
/**
* The link's bundle.
@@ -66,209 +55,34 @@ 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',
+ );
/**
* Boolean indicating whether a new revision should be created on save.
@@ -321,10 +135,10 @@ public function preSaveRevision(EntityStorageControllerInterface $storage_contro
}
/**
- * Overrides Entity::id().
+ * {@inheritdoc}
*/
public function id() {
- return $this->mlid;
+ return $this->get('mlid')->value;
}
/**
@@ -339,7 +153,7 @@ public function bundle() {
*/
public function createDuplicate() {
$duplicate = parent::createDuplicate();
- $duplicate->plid = NULL;
+ $duplicate->setParentLinkId(NULL);
return $duplicate;
}
@@ -347,12 +161,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;
}
@@ -374,11 +188,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;
@@ -403,37 +217,91 @@ 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 ($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';
+ }
}
/**
@@ -449,10 +317,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);
}
}
@@ -473,8 +341,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();
}
}
@@ -492,67 +360,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();
}
}
@@ -567,9 +438,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.
@@ -598,46 +469,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;
- // This item is explicitely top-level, skip the rest of the parenting.
- if (isset($this->plid) && empty($this->plid)) {
+ $plid = $this->getParentLinkId();
+ // This item is explicitly top-level, skip the rest of the parenting.
+ 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];
@@ -653,12 +524,480 @@ 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;
}
+ /**
+ * {@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() {
+ $options = $this->get('options')->getValue();
+ return $options[0];
+ }
+
+ /**
+ * {@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);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function inActiveTrail() {
+ return (bool) $this->get('in_active_trail')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ 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;
+ }
+
+ /**
+ * Returns whether the menu link is accessible (old property).
+ *
+ * @return bool
+ * Returns TRUE if the link is accessible, FALSE if not.
+ */
+ public function getAccess() {
+ return $this->get('access')->value;
+ }
+
+ /**
+ * Set whether the menu link is accessible (old property).
+ *
+ * @param bool $access
+ * TRUE if the link is accessible, FALSE if not.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setAccess($access) {
+ $this->set('access', $access);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteParams() {
+ $route_params = $this->get('route_parameters')->getValue();
+ return $route_params[0];
+ }
+
+ /**
+ * {@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 85cc796..06cf687 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->getModule() == 'system' && $entity->isCustomized();
case 'delete':
// Only items created by the menu module can be deleted.
- return $entity->module == 'menu' || $entity->updated == 1;
+ return $entity->getModule() == '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 3222a68..51f4892 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,9 @@
namespace Drupal\menu_link;
-use Drupal\Core\Entity\EntityFormController;
+use Drupal\Core\Entity\ContentEntityFormController;
+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 +19,7 @@
/**
* Form controller for the node edit forms.
*/
-class MenuLinkFormController extends EntityFormController {
+class MenuLinkFormController extends ContentEntityFormController {
/**
* The menu link storage controller.
@@ -79,26 +81,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->getLinkTitle(),
'#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->getLinkPath();
+ 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->getModule() == 'menu') {
$form['link_path'] = array(
'#type' => 'textfield',
'#title' => t('Path'),
@@ -112,33 +114,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->getLinkTitle(), $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->isHidden(),
'#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->isExpanded(),
'#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->getMenuName() . ':' . $menu_link->plid->target_id;
if (!isset($options[$default])) {
$default = 'tools:0';
}
@@ -152,13 +154,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->getMenuName());
$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 +170,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->getMenuName())->langcode : $menu_link->langcode->value);
$language_show = FALSE;
}
@@ -201,103 +203,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);
}
- /**
- * {@inheritdoc}
- */
public function buildEntity(array $form, array &$form_state) {
- // @todo: Remove this when menu links are converted to content entities in
- // http://drupal.org/node/1842858.
- $entity = clone $this->entity;
- // If you submit a form, the form state comes from caching, which forces
- // the controller to be the one before caching. Ensure to have the
- // controller of the current request.
- $form_state['controller'] = $this;
-
- // Copy top-level form values to entity properties, without changing
- // existing entity properties that are not being edited by
- // this form.
- foreach ($form_state['values'] as $key => $value) {
- $entity->$key = $value;
- }
-
- // Invoke all specified builders for copying form values to entity properties.
- if (isset($form['#entity_builders'])) {
- foreach ($form['#entity_builders'] as $function) {
- call_user_func_array($function, array($entity->entityType(), $entity, &$form, &$form_state));
- }
- }
-
- return $entity;
- }
-
- /**
- * 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);
-
+ $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->setHidden((bool) !$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');
@@ -309,7 +273,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 fcf5415..7634196 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,308 @@ 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 in the active trail or not.
+ *
+ * @return bool
+ * TRUE if the menu link is in the active trail, FALSE if not.
+ */
+ public function inActiveTrail();
+
+ /**
+ * 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 e3ddabd..44f8cff 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'));
}
}
@@ -98,7 +95,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 +106,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]);
}
}
}
+ }
+
+ /**
+ * {@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});
+ }
+ }
- parent::attachLoad($menu_links, $load_revision);
+ return $entities;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'base_table') {
+ $record = parent::mapToStorageRecord($entity, $table_key);
+ 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 +180,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 +205,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 +286,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 +300,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 +329,13 @@ public function loadModuleAdminTasks() {
*/
public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE) {
// If plid == 0, there is nothing to update.
- if ($entity->plid) {
+ if ($entity->getParentLinkId()) {
// 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->getMenuName())
->condition('hidden', 0)
- ->condition('plid', $entity->plid)
+ ->condition('plid', $entity->getParentLinkId())
->count();
if ($exclude) {
@@ -297,7 +345,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->getParentLinkId())
->execute();
}
}
@@ -310,20 +358,19 @@ 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->getMenuName());
$query->orderBy('depth', 'DESC');
$query->range(0, 1);
$i = 1;
- $p = 'p1';
- while ($i <= MENU_MAX_DEPTH && $entity->{$p}) {
- $query->condition($p, $entity->{$p});
- $p = 'p' . ++$i;
+ while ($i <= MENU_MAX_DEPTH && $entity->getMaterializedPathEntity($i)) {
+ $query->condition('p' . $i, $entity->getMaterializedPathEntity($i));
+ $i++;
}
$max_depth = $query->execute()->fetchField();
- return ($max_depth > $entity->depth) ? $max_depth - $entity->depth : 0;
+ return ($max_depth > $entity->getDepth()) ? $max_depth - $entity->getDepth() : 0;
}
/**
@@ -332,14 +379,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->getMenuName()));
$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->getDepth(); $p = 'p' . ++$i) {
+ $expressions[] = array($p, ":p_$i", array(":p_$i" => $entity->{$p}->value));
}
- $j = $entity->original->depth + 1;
+ $j = $entity->original->getDepth() + 1;
while ($i <= MENU_MAX_DEPTH && $j <= MENU_MAX_DEPTH) {
$expressions[] = array('p' . $i++, 'p' . $j++, array());
}
@@ -347,7 +394,7 @@ public function moveChildren(EntityInterface $entity) {
$expressions[] = array('p' . $i++, 0, array());
}
- $shift = $entity->depth - $entity->original->depth;
+ $shift = $entity->getDepth() - $entity->original->getDepth();
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 +407,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->getMenuName());
$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 +434,7 @@ public function countMenuLinks($menu_name) {
* {@inheritdoc}
*/
public function getParentFromHierarchy(EntityInterface $entity) {
- $parent_path = $entity->link_path;
+ $parent_path = $entity->getLinkPath();
do {
$parent = FALSE;
$parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
@@ -398,7 +445,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->getMenuName())
->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..b6f42fb 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->getLinkPath(), '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->getLinkPath() == '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->getLinkPath() == 'user' && $menu_link->getModule() == '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->getMenuName();
$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->getMenuName()) {
db_update('menu_example')
- ->fields(array('menu_name' => $menu_link->menu_name))
+ ->fields(array('menu_name' => $menu_link->getMenuName()))
->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 5a393de..2c7cf3d 100755
--- 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->getMenuName());
$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..f67f63f 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->getLinkTitle()));
}
/**
@@ -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->getMenuName()),
),
);
}
@@ -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->getMenuName());
$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->getLinkTitle())));
}
}
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php
index 29da4a8..21e82ef 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->getLinkTitle(), $link->getLinkPath());
+ $form['shortcuts']['links'][$mlid]['#weight'] = $link->getWeight();
$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->getLinkTitle())),
'#title_display' => 'invisible',
- '#default_value' => $link->weight,
+ '#default_value' => $link->getWeight(),
'#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 175206d..75cffa0 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->getMenuName(), 'shortcut-') === 0) {
$entity->bundle = 'shortcut';
}
}
@@ -214,9 +214,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->getMenuName(), 'shortcut-') === 0) {
+ $shortcut = entity_load('shortcut_set', str_replace('shortcut-', '', $menu_link->getMenuName()));
+ unset($shortcut->links[$menu_link->uuid()]);
$shortcut->save();
}
}
@@ -453,8 +453,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 597471e..be60855 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,22 @@ 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']);
+ $attrs = $item->localized_options->attributes;
+ if (!empty($attrs['title'])) {
+ $item['description'] = $attrs['title'];
+ unset($attrs['title']);
+ $item->localized_options->attributes = $attrs;
}
- $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 +113,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..82733f4 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->getMenuName();
}
if (isset($this->menuItems[$item['mlid']])) {
@@ -209,16 +209,18 @@ 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']);
+ $attrs = $link->localized_options->attributes;
+ if (!empty($attrs['title'])) {
+ $link['description'] = $attrs['title'];
+ unset($attrs['title']);
+ $link->localized_options->attributes = $attrs;
}
// 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..c3e913d 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(), array('value' => '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(), array('value' => '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 f341681..2d476be 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php
@@ -180,7 +180,7 @@ protected function doTestMenuName() {
$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->getMenuName(), 'original', 'Menu name is "original".');
// Change the menu_name parameter in menu_test.module, then force a menu
// rebuild.
@@ -190,7 +190,7 @@ protected function doTestMenuName() {
$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->getMenuName(), 'changed', 'Menu name was successfully changed after rebuild.');
}
/**
@@ -221,7 +221,7 @@ protected function doTestMenuHidden() {
$links = array();
foreach ($menu_links as $menu_link) {
- $links[$menu_link->router_path] = $menu_link;
+ $links[$menu_link->getRouterPath()] = $menu_link;
}
$parent = $links['menu-test/hidden/menu'];
@@ -273,7 +273,7 @@ protected function doTestMenuHidden() {
$links = array();
foreach ($menu_links as $menu_link) {
- $links[$menu_link->router_path] = $menu_link;
+ $links[$menu_link->getRouterPath()] = $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 f220198..e5ecf24 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2289,6 +2289,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 03f9042..ff3e609 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2936,9 +2936,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 85bfafa..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->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 5dacd11..d1c58e6 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -863,13 +863,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;
}
}
@@ -891,8 +891,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;
}
}
}