diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index eba234b..f21c0c8 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -642,8 +642,13 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
// @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($item['options']['attributes']['class']) && is_string($item['options']['attributes']['class'])) {
+ if ($link_translate) {
+ $item->localized_options->attributes['class'] = explode(' ', $item->options->attributes['class']);
+ }
+ else {
+ $item['localized_options']['attributes']['class'] = explode(' ', $item['options']['attributes']['class']);
+ }
}
// If we are translating the title of a menu link, and its title is the same
// as the corresponding router item, then we can use the title information
@@ -671,7 +676,11 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
}
// Avoid calling check_plain again on l() function.
if ($title_callback == 'check_plain') {
- $item['localized_options']['html'] = TRUE;
+ if ($link_translate) {
+ $item->localized_options->html = TRUE;
+ } else {
+ $item['localized_options']['html'] = TRUE;
+ }
}
}
}
@@ -705,6 +714,11 @@ 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'];
+ }
}
/**
@@ -863,20 +877,22 @@ function menu_tail_load($arg, &$map, $index) {
* $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.
* $item['href'] is generated from link_path, possibly by to_arg functions.
* $item['title'] is generated from link_title, and may be localized.
+ * $item['options'] is unserialized; it is also changed within the call here
* to $item['localized_options'] by _menu_item_localize().
*/
function _menu_link_translate(&$item, $translate = FALSE) {
- 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['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']);
@@ -892,7 +908,7 @@ function _menu_link_translate(&$item, $translate = FALSE) {
elseif ($translate && ($current_router_item = menu_get_item())) {
// If $translate is TRUE, then this link is in the active trail.
// Only translate paths within the current path.
- if (strpos($current_router_item['path'], $item['link_path']) === 0) {
+ if (strpos($current_router_item['path'], $item->getLinkPath()) === 0) {
$count = count($map);
$map = array_slice($current_router_item['original_map'], 0, $count);
$item['original_map'] = $map;
@@ -900,7 +916,7 @@ function _menu_link_translate(&$item, $translate = FALSE) {
$item['map'] = array_slice($current_router_item['map'], 0, $count);
}
// Reset access to check it (for the first time).
- unset($item['access']);
+ $item->setAccess(NULL);
}
}
}
@@ -908,17 +924,17 @@ function _menu_link_translate(&$item, $translate = FALSE) {
// Skip links containing untranslated arguments.
if (strpos($item['href'], '%') !== FALSE) {
- $item['access'] = FALSE;
+ $item->setAccess(FALSE);
return FALSE;
}
// menu_tree_check_access() may set this ahead of time for links to nodes.
- if (!isset($item['access'])) {
+ if ($item->getAccess() === NULL) {
if ($route = $item->getRoute()) {
- $item['access'] = menu_item_route_access($route, $item['href'], $map);
+ $item->setAccess(menu_item_route_access($route, $item['href'], $map));
}
elseif (!empty($item['load_functions']) && !_menu_load_objects($item, $map)) {
// An error occurred loading an object.
- $item['access'] = FALSE;
+ $item->setAccess(FALSE);
return FALSE;
}
// Apply the access check defined in hook_menu() if there is not route
@@ -928,7 +944,7 @@ function _menu_link_translate(&$item, $translate = FALSE) {
}
}
// For performance, don't localize a link the user can't access.
- if ($item['access']) {
+ if ($item->getAccess()) {
_menu_item_localize($item, $map, TRUE);
}
}
@@ -936,7 +952,7 @@ function _menu_link_translate(&$item, $translate = FALSE) {
// Allow other customizations - e.g. adding a page-specific query string to the
// options array. For performance reasons we only invoke this hook if the link
// has the 'alter' flag set in the options array.
- if (!empty($item['options']->alter)) {
+ if (!empty($item->options->alter)) {
drupal_alter('translated_menu_link', $item, $map);
}
@@ -1088,7 +1104,7 @@ function menu_tree_output($tree) {
// Pull out just the menu links we are going to render so that we
// get an accurate count for the first/last classes.
foreach ($tree as $data) {
- if ($data['link']['access'] && !$data['link']['hidden']) {
+ if ($data['link']->getAccess() && !$data['link']->isHidden()) {
$items[] = $data;
}
}
@@ -1106,47 +1122,48 @@ function menu_tree_output($tree) {
// Set a class for the
-tag. Since $data['below'] may contain local
// tasks, only set 'expanded' class if the link also has children within
// the current menu.
- if ($data['link']['has_children'] && $data['below']) {
+ if ($data['link']->hasChildren() && $data['below']) {
$class[] = 'expanded';
}
- elseif ($data['link']['has_children']) {
+ elseif ($data['link']->hasChildren()) {
$class[] = 'collapsed';
}
else {
$class[] = 'leaf';
}
// Set a class if the link is in the active trail.
- $localized_options = $data['link']['options'];
- if ($data['link']['in_active_trail']) {
+ $localized_attributes = $data['link']->localized_options->attributes;
+ if ($data['link']->in_active_trail->value) {
$class[] = 'active-trail';
- $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()) {
- $localized_options['attributes']['class'][] = 'active';
+ $localized_attributes['class'][] = 'active';
}
- $data['link']['options'] = $localized_options;
+ $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['#options'] = !empty($data['link']['options']) ? $data['link']['options'] : array();
+ $localized_options = $data['link']->localized_options->getValue();
+ $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;
@@ -1354,12 +1371,13 @@ function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail =
// active trail, if it resides in the requested menu. Otherwise,
// we'd needlessly re-run _menu_build_tree() queries for every menu
// on every page.
- if ($active_link['menu_name'] == $menu_name) {
+ if ($active_link->getMenuName() == $menu_name) {
// Use all the coordinates, except the last one because there
// can be no child beyond the last column.
for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
- if ($active_link['p' . $i]) {
- $active_trail[$active_link['p' . $i]] = $active_link['p' . $i];
+ $p_i = 'p' . $i;
+ if ($active_link->{$p_i}->value) {
+ $active_trail[$active_link->{$p_i}->value] = $active_link->{$p_i}->value;
}
}
// If we are asked to build links for the active trail only, skip
@@ -1525,11 +1543,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']) {
@@ -1576,14 +1594,14 @@ function _menu_tree_check_access(&$tree) {
foreach ($tree as $key => $v) {
$item = &$tree[$key]['link'];
_menu_link_translate($item);
- if ($item['access'] || ($item['in_active_trail'] && strpos($item['href'], '%') !== FALSE)) {
+ if ($item->getAccess() || ($item->in_active_trail->value && strpos($item['href'], '%') !== FALSE)) {
if ($tree[$key]['below']) {
_menu_tree_check_access($tree[$key]['below']);
}
// The weights are made a uniform 5 digits by adding 50000 as an offset.
// After _menu_link_translate(), $item['title'] has the localized link title.
// Adding the mlid to the end of the index insures that it is unique.
- $new_tree[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $tree[$key];
+ $new_tree[(50000 + $item->getWeight()) . ' ' . $item['title'] . ' ' . $item->id()] = $tree[$key];
}
}
// Sort siblings in the tree based on the weights and localized titles.
@@ -1634,9 +1652,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 and breadcrumb.
- $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(),
);
@@ -1644,14 +1662,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;
}
}
@@ -1695,7 +1713,7 @@ function theme_menu_link(array $variables) {
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
- $output = l($element['#title'], $element['#href'], $element['#options']);
+ $output = l($element['#title'], $element['#href'], $element['#localized_options']);
return '' . $output . $sub_menu . "\n";
}
@@ -1714,7 +1732,7 @@ function theme_menu_link(array $variables) {
function theme_menu_local_task($variables) {
$link = $variables['element']['#link'];
$link += array(
- 'options' => array(),
+ 'localized_options' => array(),
);
$link_text = $link['title'];
@@ -1724,14 +1742,14 @@ function theme_menu_local_task($variables) {
// If the link does not contain HTML already, check_plain() it now.
// After we set 'html'=TRUE the link will not be sanitized by l().
- if (empty($link['options']['html'])) {
+ if (empty($link['localized_options']['html'])) {
$link['title'] = check_plain($link['title']);
}
- $link['options']['html'] = TRUE;
+ $link['localized_options']['html'] = TRUE;
$link_text = t('!local-task-title!active', array('!local-task-title' => $link['title'], '!active' => $active));
}
- return '' . l($link_text, $link['href'], $link['options']) . '';
+ return '' . l($link_text, $link['href'], $link['localized_options']) . '';
}
/**
@@ -1749,13 +1767,13 @@ function theme_menu_local_action($variables) {
$link = $variables['element']['#link'];
$link += array(
'href' => '',
- 'options' => array(),
+ 'localized_options' => array(),
);
- $link['options']['attributes']['class'][] = 'button';
- $link['options']['attributes']['class'][] = 'button-action';
+ $link['localized_options']['attributes']['class'][] = 'button';
+ $link['localized_options']['attributes']['class'][] = 'button-action';
$output = '';
- $output .= l($link['title'], $link['href'], $link['options']);
+ $output .= l($link['title'], $link['href'], $link['localized_options']);
$output .= "";
return $output;
@@ -1917,12 +1935,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']['options']->getValue();
+ $l = $item['link']->localized_options->getValue();
$l['href'] = $item['link']['href'];
$l['title'] = $item['link']['title'];
- if ($item['link']['in_active_trail']) {
+ if ($item['link']->in_active_trail->value) {
$class = ' active-trail';
$l['attributes']['class'][] = 'active-trail';
}
@@ -1934,7 +1952,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;
@@ -2048,7 +2066,7 @@ function menu_local_tasks($level = 0) {
// would not be marked as active, since l() only compares the href
// with current_path().
if ($link['href'] != current_path()) {
- $link['options']['attributes']['class'][] = 'active';
+ $link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
@@ -2125,7 +2143,7 @@ function menu_local_tasks($level = 0) {
// links to its parent, l() will not mark it as active, as it only
// compares the link's href to current_path().
if ($link['href'] != current_path()) {
- $link['options']['attributes']['class'][] = 'active';
+ $link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
@@ -2471,7 +2489,7 @@ function menu_set_active_trail($new_trail = NULL) {
'title' => t('Home'),
'href' => '',
'link_path' => '',
- 'options' => array(),
+ 'localized_options' => array(),
'type' => 0,
);
@@ -2485,7 +2503,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.
@@ -2496,7 +2514,7 @@ function menu_set_active_trail($new_trail = NULL) {
while ($curr) {
$link = $curr['link'];
- if ($link['in_active_trail']) {
+ if ($link->in_active_trail->value) {
// Add the link to the trail, unless it links to its parent.
if (!($link['type'] & MENU_LINKS_TO_PARENT)) {
// The menu tree for the active trail may contain additional links
@@ -2510,7 +2528,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;
}
}
@@ -2588,10 +2606,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();
}
}
@@ -2604,7 +2622,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.
@@ -2687,7 +2705,7 @@ function menu_get_active_breadcrumb() {
}
foreach ($active_trail as $parent) {
- $l_options = $parent['options'];
+ $l_options = $parent['localized_options'];
$breadcrumb[] = l($parent['title'], $parent['href'], (is_array($l_options) && !empty($l_options)) ? $l_options : array(''));
}
}
@@ -2837,19 +2855,10 @@ function menu_router_build($save = FALSE) {
* The translated path pattern from the route.
*/
function _menu_router_translate_route($route_name) {
- $route = \Drupal::service('router.route_provider')
- ->getRouteByName($route_name);
-
- $path = $route->getPattern();
- $defaults = $route->getDefaults();
-
- // Remove placeholders with default values from the outline, so that they
- // will still match.
- $remove = array_map(function($a) {
- return '/{' . $a . '}';
- }, array_keys($defaults));
- $stripped_path = str_replace($remove, '', $path);
- $outline = preg_replace('#\{(\w+)\}#', '%$1', $stripped_path);
+ $outline = \Drupal::service('router.route_provider')
+ ->getRouteByName($route_name)
+ ->compile()
+ ->getPatternOutline();
return trim($outline, '/');
}
@@ -3126,14 +3135,15 @@ function _menu_router_build($callbacks, $save = FALSE) {
// Look for wildcards in the form allowed to be used in PHP functions,
// because we are using these to construct the load function names.
if (preg_match('/^%(|' . DRUPAL_PHP_FUNCTION_PATTERN . ')$/', $part, $matches)) {
- $match = TRUE;
if (empty($matches[1])) {
+ $match = TRUE;
$load_functions[$k] = NULL;
}
else {
if (function_exists($matches[1] . '_to_arg')) {
$to_arg_functions[$k] = $matches[1] . '_to_arg';
$load_functions[$k] = NULL;
+ $match = TRUE;
}
if (function_exists($matches[1] . '_load')) {
$function = $matches[1] . '_load';
@@ -3141,6 +3151,7 @@ function _menu_router_build($callbacks, $save = FALSE) {
// function when this menu path is checked, if 'load arguments'
// exists.
$load_functions[$k] = isset($item['load arguments']) ? array($function => $item['load arguments']) : $function;
+ $match = TRUE;
}
}
}
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index 66f9ea7..5e94d71 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -616,7 +616,7 @@ public function updateOriginalValues() {
}
/**
- * Implements the magic method for setting object properties.
+ * Implements the magic method for getting object properties.
*
* @todo: A lot of code still uses non-fields (e.g. $entity->content in render
* controllers) by reference. Clean that up.
diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
index dd835bd..4a9c8a0 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
@@ -32,20 +32,22 @@ public function getPropertyDefinitions() {
foreach ($this->properties as $name => $property) {
$definitions[$name] = $property->getDefinition();
}
+
return $definitions;
}
/**
- * Overrides \Drupal\Core\TypedData\TypedData::setValue().
+ * Overrides \Drupal\Core\Entity\Field\FieldItemBase::setValue().
*
* @param array|null $values
* An array of property values.
*/
public function setValue($values, $notify = TRUE) {
+ $this->properties = array();
if (!isset($values)) {
- $this->properties = array();
return;
}
+
if (!is_array($values)) {
if ($values instanceof MapItem) {
$values = $values->getValue();
@@ -54,35 +56,41 @@ public function setValue($values, $notify = TRUE) {
$values = unserialize($values);
}
}
- $this->properties = array();
+
foreach($values as $name => $value) {
- $this->{$name} = $value;
+ $this->properties[$name] = $this->valueToProperty($value, $name);
}
}
public function __get($name) {
if (!isset($this->properties[$name])) {
- $this->{$name} = array();
+ $this->properties[$name] = $this->valueToProperty(array(), $name);
}
+
return $this->properties[$name]->getValue();
}
public function __set($name, $value) {
if (isset($value)) {
if (isset($this->properties[$name])) {
- $this->set($name, $value);
+ $this->properties[$name]->setValue($value);
}
else {
- $def = array('type' => 'any');
- if ($value instanceof TypedData) {
- $def = $value->getDefinition();
- $value = $value->getValue();
- }
- $this->properties[$name] = \Drupal::typedData()->create($def, $value, $name);
+ $this->properties[$name] = $this->valueToProperty($value, $name);
}
}
else {
unset($this->properties[$name]);
}
}
-}
+
+ protected function valueToProperty($value, $name) {
+ $def = array('type' => 'any');
+ if ($value instanceof TypedData) {
+ $def = $value->getDefinition();
+ $value = $value->getValue();
+ }
+
+ return \Drupal::typedData()->create($def, $value, $name, $this);
+ }
+}
\ No newline at end of file
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index ebaff55..529fa5c 100644
--- a/core/modules/contextual/contextual.module
+++ b/core/modules/contextual/contextual.module
@@ -269,9 +269,9 @@ function contextual_pre_render_links($element) {
'href' => $item['href'],
);
// @todo theme_links() should *really* use the same parameters as l().
- $item['options'] += array('query' => array());
- $item['options']['query'] += drupal_get_destination();
- $links[$class] += $item['options'];
+ $item['localized_options'] += array('query' => array());
+ $item['localized_options']['query'] += drupal_get_destination();
+ $links[$class] += $item['localized_options'];
}
$element['#links'] = $links;
diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php
index 87c03f0..43db3a2 100644
--- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php
+++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php
@@ -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->value;
+ $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 c6615e8..6f41606 100644
--- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php
+++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php
@@ -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->value;
+ $form_state['redirect'] = 'admin/structure/menu/manage/' . $new_menu_link->getMenuName();
}
}
diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php
index b8e47f7..68bc6a4 100644
--- a/core/modules/menu/lib/Drupal/menu/MenuFormController.php
+++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php
@@ -297,7 +297,7 @@ protected function buildOverviewTreeForm($tree, $delta) {
$mlid = 'mlid:' . $item['mlid'];
$form[$mlid]['#item'] = $item;
$form[$mlid]['#attributes'] = $item['hidden'] ? array('class' => array('menu-disabled')) : array('class' => array('menu-enabled'));
- $form[$mlid]['title']['#markup'] = l($item['title'], $item['href'], $item['options']);
+ $form[$mlid]['title']['#markup'] = l($item['title'], $item['href'], $item['localized_options']);
if ($item['hidden']) {
$form[$mlid]['title']['#markup'] .= ' (' . t('disabled') . ')';
}
diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php
index 03e4c6d..e0ac0d7 100644
--- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php
+++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php
@@ -88,7 +88,7 @@ function testMenu() {
// 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);
}
diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install
index 4e0d032..5376346 100644
--- a/core/modules/menu/menu.install
+++ b/core/modules/menu/menu.install
@@ -5,8 +5,6 @@
* Install, update and uninstall functions for the menu module.
*/
-use Drupal\Component\Uuid\Uuid;
-
/**
* Implements hook_install().
*/
@@ -18,9 +16,9 @@ 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',
+ 'module' => 'menu'
));
$menus = entity_load_multiple('menu');
@@ -31,8 +29,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 662308c..5dd2d0c 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -351,7 +351,7 @@ function menu_block_view_system_menu_block_alter(array &$build, BlockPluginInter
list(, $menu_name) = explode(':', $block->getPluginId());
if (isset($menus[$menu_name]) && isset($build['content'])) {
foreach (element_children($build['content']) as $key) {
- $build['content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['content'][$key]['#original_link']['menu_name']));
+ $build['content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($build['content'][$key]['#original_link']->getMenuName()));
}
}
}
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 0b44153..5145d85 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
@@ -13,6 +13,7 @@
use Drupal\Core\Entity\EntityNG;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Component\Uuid\Uuid;
use Drupal\menu_link\MenuLinkInterface;
use Drupal\menu_link\MenuLinkStorageControllerInterface;
use Symfony\Component\Routing\Route;
@@ -84,7 +85,7 @@ class MenuLink extends EntityNG implements \ArrayAccess, MenuLinkInterface {
'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', 'route_name',
+ 'position', 'include_file',
);
/**
@@ -106,6 +107,7 @@ public function bundle() {
*/
public function createDuplicate() {
$duplicate = parent::createDuplicate();
+
$duplicate->get('plid')->offsetGet(0)->set('value', NULL);
return $duplicate;
}
@@ -170,6 +172,7 @@ 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);
@@ -192,11 +195,11 @@ public function offsetGet($offset) {
if (in_array($offset, $this->oldRoutingProperties)) {
return $this->oldRouterItem[$offset];
}
- elseif ($offset == 'options' || $offset == 'localized_options') {
- return $this->options->getValue();
+ elseif (in_array($offset, array('options', 'localized_options', 'route_parameters'))) {
+ return $this->get($offset)->getValue();
}
elseif ($this->getPropertyDefinition($offset)) {
- return $this->$offset->value;
+ return $this->get($offset)->value;
}
else {
return $this->$offset;
@@ -210,11 +213,11 @@ public function offsetSet($offset, $value) {
if (in_array($offset, $this->oldRoutingProperties)) {
$this->oldRouterItem[$offset] = $value;
}
- elseif ($offset == 'options' || $offset == 'localized_options') {
+ elseif (in_array($offset, array('options', 'localized_options', 'route_parameters'))) {
if (is_array($value)) {
foreach ($value as $delta => $value_item) {
if (!is_numeric($delta)) {
- $this->options = array($value);
+ $this->{$offset} = array($value);
return;
}
}
@@ -235,10 +238,12 @@ public function offsetUnset($offset) {
if (in_array($offset, $this->oldRoutingProperties)) {
unset($this->oldRouterItem[$offset]);
}
+ elseif ($this->getPropertyDefinition($offset)) {
+ $this->get($offset)->setValue(NULL);
+ }
else {
- $this->{$offset}->value = NULL;
+ $this->get($offset)->setValue(NULL);
}
-// unset($this->{$offset});
}
/**
@@ -361,8 +366,9 @@ public function preSave(EntityStorageControllerInterface $storage_controller) {
$this->setRouterPath(_menu_find_router_path($this->getLinkPath()));
}
}
+
// Find the route_name.
- if ($this->getRouteName()) {
+ if ($this->getRouteName() === NULL) {
if ($result = static::findRouteNameParameters($this->getLinkPath())) {
$this->setRouteName($result[0]);
$this->route_parameters = $result[1];
@@ -480,6 +486,21 @@ public function findParent(MenuLinkStorageControllerInterface $storage_controlle
}
/**
+ * overrides \Drupal\Core\Entity\EntityNG::set()
+ */
+ public function set($property_name, $value, $notify = TRUE) {
+ // work-around entity_form_submit_build_entity() -> entity.set() trying to
+ // set a non-existing fields into MenuLink.
+ $definition = $this->getPropertyDefinition($property_name);
+ if (!$definition) {
+ $this->$property_name = $value;
+ }
+ else {
+ parent::set($property_name, $value, $notify);
+ }
+ }
+
+ /**
* {@inheritdoc}
*/
public function getMenuName() {
@@ -695,6 +716,29 @@ public function setRouteName($route_name) {
return $this;
}
+ public function getAccess() {
+ return $this->get('access')->value;
+ }
+
+ public function setAccess($access) {
+ $this->set('access', $access);
+ return $this;
+ }
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteParams() {
+ return $this->get('route_parameters')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setRouteParams($route_parameters) {
+ $this->set('route_parameters', $route_parameters);
+ return $this;
+ }
+
/**
* {@inheritdoc}
*/
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 7dbbbdb..49c9e9d 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
@@ -256,7 +256,9 @@ public function buildEntity(array $form, array &$form_state) {
// The value of "hidden" is the opposite of the value supplied by the
// "enabled" checkbox.
$entity->hidden->value = (int) !$form_state['values']['enabled'];
- list($entity->menu_name->value, $entity->plid->target_id) = explode(':', $form_state['values']['parent']);
+ $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;
@@ -269,7 +271,7 @@ public function buildEntity(array $form, array &$form_state) {
public function save(array $form, array &$form_state) {
if ($this->entity->save()) {
drupal_set_message(t('The menu link has been saved.'));
- $form_state['redirect'] = 'admin/structure/menu/manage/' . $this->entity->menu_name->value;
+ $form_state['redirect'] = 'admin/structure/menu/manage/' . $this->entity->getMenuName();
}
else {
drupal_set_message(t('There was an error saving the menu link.'), 'error');
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 acb4549..3b307ba 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php
@@ -372,4 +372,23 @@ public function getRouteName();
*/
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 c221df5..6991e1d 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
@@ -61,7 +61,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'));
}
}
@@ -74,6 +74,7 @@ public function create(array $values) {
if (!isset($values['bundle']) && isset($values['menu_name'])) {
$values['bundle'] = $values['menu_name'];
}
+
return parent::create($values);
}
@@ -109,7 +110,7 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
foreach ($queried_entities as &$record) {
$record->options = unserialize($record->options);
- $record->route_parameters = unserialize($record->route_parameters);
+ $record->route_parameters = isset($record->route_parameters) ? unserialize($record->route_parameters) : array();
// Use the weight property from the menu link.
$record->router_item['weight'] = $record->weight;
@@ -154,6 +155,18 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE)
}
/**
+ * Overrides DatabaseStorageControllerNG::mapToStorageRecord().
+ */
+ protected function mapToStorageRecord(EntityInterface $entity) {
+ $record = parent::mapToStorageRecord($entity);
+ foreach (array('options', 'route_parameters') as $property) {
+ $record->$property = $entity->$property->getValue();
+ }
+
+ return $record;
+ }
+
+ /**
* Overrides DatabaseStorageController::save().
*/
public function save(EntityInterface $entity) {
@@ -164,9 +177,6 @@ public function save(EntityInterface $entity) {
$transaction = $this->database->startTransaction();
try {
- // Ensure we are dealing with the actual entity.
- $entity = $entity->getNGEntity();
-
// Sync the changes made in the fields array to the internal values array.
$entity->updateOriginalValues();
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 287b024..804b76b 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -470,8 +470,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 b27acf1..b5eef16 100644
--- a/core/modules/system/lib/Drupal/system/Controller/SystemController.php
+++ b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
@@ -86,13 +86,13 @@ 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'];
+ if (!empty($item->localized_options->attributes['title'])) {
+ $item['description'] = $item->localized_options->attributes['title'];
unset($item->localized_options->attributes['title']);
}
$block = array(
@@ -111,7 +111,7 @@ public function overview() {
// Prepare for sorting as in function _menu_tree_check_access().
// The weight is offset so it is always positive, with a uniform 5-digits.
- $blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
+ $blocks[(50000 + $item->getWeight()) . ' ' . $item['title'] . ' ' . $item->id()] = $block;
}
}
}
diff --git a/core/modules/system/lib/Drupal/system/SystemManager.php b/core/modules/system/lib/Drupal/system/SystemManager.php
index 5c12997..57d893f 100644
--- a/core/modules/system/lib/Drupal/system/SystemManager.php
+++ b/core/modules/system/lib/Drupal/system/SystemManager.php
@@ -209,16 +209,16 @@ public function getAdminBlock($item) {
$menu_links = $this->menuLinkStorage->loadByProperties(array('plid' => $item['mlid'], 'menu_name' => $item['menu_name'], 'hidden' => 0));
foreach ($menu_links as $link) {
_menu_link_translate($link);
- if ($link['access']) {
+ if ($link->getAccess()) {
// The link description, either derived from 'description' in
// hook_menu() or customized via menu module is used as title attribute.
- if (!empty($link['localized_options']['attributes']['title'])) {
- $link['description'] = $link['localized_options']['attributes']['title'];
- unset($link['localized_options']['attributes']['title']);
+ if (!empty($link->localized_options->attributes['title'])) {
+ $link['description'] = $link->localized_options->attributes['title'];
+ unset($link->localized_options->attributes['title']);
}
// Prepare for sorting as in function _menu_tree_check_access().
// The weight is offset so it is always positive, with a uniform 5-digits.
- $key = (50000 + $link['weight']) . ' ' . Unicode::strtolower($link['title']) . ' ' . $link['mlid'];
+ $key = (50000 + $link->getWeight()) . ' ' . Unicode::strtolower($link['title']) . ' ' . $link->id();
$content[$key] = $link;
}
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
index bcf7c96..b05f9e3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
@@ -246,19 +246,19 @@ public function testRouterIntegration() {
'link_path' => 'router_test/test1',
));
$menu_link->save();
- $this->assertEqual($menu_link->route_name, 'router_test.1');
- $this->assertEqual($menu_link->route_parameters, array());
+ $this->assertEqual($menu_link->getRouteName(), 'router_test.1');
+ $this->assertEqual($menu_link->getRouteParams(), array());
$menu_link = entity_create('menu_link', array(
'link_path' => 'router_test/test3/test',
));
$menu_link->save();
- $this->assertEqual($menu_link->route_name, 'router_test.3');
- $this->assertEqual($menu_link->route_parameters, array('value' => 'test'));
+ $this->assertEqual($menu_link->getRouteName(), 'router_test.3');
+ $this->assertEqual($menu_link->getRouteParams(), 'test');
$menu_link = entity_load('menu_link', $menu_link->id());
- $this->assertEqual($menu_link->route_name, 'router_test.3');
- $this->assertEqual($menu_link->route_parameters, array('value' => 'test'));
+ $this->assertEqual($menu_link->getRouteName(), 'router_test.3');
+ $this->assertEqual($menu_link->getRouteParams(), 'test');
}
}
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 3067945..94a9251 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,16 +521,14 @@ 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.
- $l_options = $tree[$key]['link']['localized_options'];
- $l_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']),
);
- $tree[$key]['link']['localized_options'] = $l_options;
}
}
@@ -542,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);