diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index f289cbb..eea5c4d 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -635,14 +635,13 @@ 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'];
// 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']);
+ $item->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
@@ -670,7 +669,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;
+ $item->options->html = TRUE;
}
}
}
@@ -704,11 +703,6 @@ 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'];
- }
}
/**
@@ -867,19 +861,14 @@ 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 (!is_array($item['options'])) {
- $item['options'] = unserialize($item['options']);
- }
if ($item['external']) {
$item['access'] = 1;
$map = array();
$item['href'] = $item['link_path'];
$item['title'] = $item['link_title'];
- $item['localized_options'] = $item['options'];
}
else {
// Complete the path of the menu link with elements from the current path,
@@ -1105,24 +1094,26 @@ function menu_tree_output($tree) {
$class[] = 'leaf';
}
// Set a class if the link is in the active trail.
+ $localized_options = $data['link']['options'];
if ($data['link']['in_active_trail']) {
$class[] = 'active-trail';
- $data['link']['localized_options']['attributes']['class'][] = 'active-trail';
+ $localized_options['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_options['attributes']['class'][] = 'active';
}
+ $data['link']['options'] = $localized_options;
// Allow menu-specific theme overrides.
$element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_');
$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();
+ $element['#options'] = !empty($data['link']['options']) ? $data['link']['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.
@@ -1682,7 +1673,7 @@ function theme_menu_link(array $variables) {
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
- $output = l($element['#title'], $element['#href'], $element['#localized_options']);
+ $output = l($element['#title'], $element['#href'], $element['#options']);
return '
' . $output . $sub_menu . "\n";
}
@@ -1701,7 +1692,7 @@ function theme_menu_link(array $variables) {
function theme_menu_local_task($variables) {
$link = $variables['element']['#link'];
$link += array(
- 'localized_options' => array(),
+ 'options' => array(),
);
$link_text = $link['title'];
@@ -1711,14 +1702,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['localized_options']['html'])) {
+ if (empty($link['options']['html'])) {
$link['title'] = check_plain($link['title']);
}
- $link['localized_options']['html'] = TRUE;
+ $link['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['localized_options']) . '';
+ return '' . l($link_text, $link['href'], $link['options']) . '';
}
/**
@@ -1736,13 +1727,13 @@ function theme_menu_local_action($variables) {
$link = $variables['element']['#link'];
$link += array(
'href' => '',
- 'localized_options' => array(),
+ 'options' => array(),
);
- $link['localized_options']['attributes']['class'][] = 'button';
- $link['localized_options']['attributes']['class'][] = 'button-action';
+ $link['options']['attributes']['class'][] = 'button';
+ $link['options']['attributes']['class'][] = 'button-action';
$output = '';
- $output .= l($link['title'], $link['href'], $link['localized_options']);
+ $output .= l($link['title'], $link['href'], $link['options']);
$output .= "";
return $output;
@@ -1906,7 +1897,7 @@ function menu_navigation_links($menu_name, $level = 0) {
foreach ($tree as $item) {
if (!$item['link']['hidden']) {
$class = '';
- $l = $item['link']['localized_options'];
+ $l = $item['link']['options'];
$l['href'] = $item['link']['href'];
$l['title'] = $item['link']['title'];
if ($item['link']['in_active_trail']) {
@@ -2035,7 +2026,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['localized_options']['attributes']['class'][] = 'active';
+ $link['options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
@@ -2112,7 +2103,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['localized_options']['attributes']['class'][] = 'active';
+ $link['options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
@@ -2458,7 +2449,7 @@ function menu_set_active_trail($new_trail = NULL) {
'title' => t('Home'),
'href' => '',
'link_path' => '',
- 'localized_options' => array(),
+ 'options' => array(),
'type' => 0,
);
@@ -2674,7 +2665,8 @@ function menu_get_active_breadcrumb() {
}
foreach ($active_trail as $parent) {
- $breadcrumb[] = l($parent['title'], $parent['href'], $parent['localized_options']);
+ $l_options = $parent['options'];
+ $breadcrumb[] = l($parent['title'], $parent['href'], (is_array($l_options) && !empty($l_options)) ? $l_options : array(''));
}
}
return $breadcrumb;
@@ -2823,10 +2815,19 @@ function menu_router_build($save = FALSE) {
* The translated path pattern from the route.
*/
function _menu_router_translate_route($route_name) {
- $outline = \Drupal::service('router.route_provider')
- ->getRouteByName($route_name)
- ->compile()
- ->getPatternOutline();
+ $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);
return trim($outline, '/');
}
@@ -2885,6 +2886,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.
@@ -2892,9 +2895,8 @@ function _menu_navigation_links_rebuild($menu) {
->fields('menu_links')
->condition('link_path', $router_item['path'])
->condition('module', 'system')
- ->execute()->fetchAll();
+ ->execute()->fetch();
if ($existing_item) {
- $existing_item = reset($existing_item);
$existing_item->options = unserialize($existing_item->options);
$router_item['mlid'] = $existing_item->mlid;
@@ -2920,8 +2922,8 @@ function _menu_navigation_links_rebuild($menu) {
$existing_item = NULL;
}
- if ($existing_item && $existing_item->customized) {
- $parent_candidates[$existing_item->mlid] = $existing_item;
+ if ($existing_item && $existing_item->customized->value) {
+ $parent_candidates[$existing_item->id()] = $existing_item;
}
else {
$menu_link = MenuLink::buildFromRouterItem($router_item);
@@ -2938,11 +2940,11 @@ function _menu_navigation_links_rebuild($menu) {
// Updated and customized items whose router paths are gone need new ones.
$menu_links = $menu_link_controller->loadUpdatedCustomized($paths);
foreach ($menu_links as $menu_link) {
- $router_path = _menu_find_router_path($menu_link->link_path);
- if (!empty($router_path) && ($router_path != $menu_link->router_path || $menu_link->updated)) {
+ $router_path = _menu_find_router_path($menu_link->link_path->value);
+ if (!empty($router_path) && ($router_path != $menu_link->router_path->value || $menu_link->updated->value)) {
// If the router path and the link path matches, it's surely a working
// item, so we clear the updated flag.
- $updated = $menu_link->updated && $router_path != $menu_link->link_path;
+ $updated = $menu_link->updated->value && $router_path != $menu_link->link_path->value;
$menu_link->router_path = $router_path;
$menu_link->updated = (int) $updated;
@@ -3102,15 +3104,14 @@ 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';
@@ -3118,7 +3119,6 @@ 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/includes/path.inc b/core/includes/path.inc
index 2187dd3..52ab706 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -204,7 +204,7 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
$item['link_path'] = $form_item['link_path'];
$item['link_title'] = $form_item['link_title'];
$item['external'] = FALSE;
- $item['options'] = '';
+ $item['options'] = array();
_menu_link_translate($item);
}
}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index d583eb7..0742c8f 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1704,9 +1704,9 @@ function theme_links($variables) {
// Handle title-only text items.
else {
// Merge in default array properties into $link.
- $link += array(
- 'html' => FALSE,
- );
+ if (!isset($link['html'])) {
+ $link['html'] = FALSE;
+ }
$item = ($link['html'] ? $link['title'] : check_plain($link['title']));
if (isset($link['attributes'])) {
$item = '' . $item . '';
diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
new file mode 100644
index 0000000..dd835bd
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php
@@ -0,0 +1,88 @@
+properties as $name => $property) {
+ $definitions[$name] = $property->getDefinition();
+ }
+ return $definitions;
+ }
+
+ /**
+ * Overrides \Drupal\Core\TypedData\TypedData::setValue().
+ *
+ * @param array|null $values
+ * An array of property values.
+ */
+ public function setValue($values, $notify = TRUE) {
+ if (!isset($values)) {
+ $this->properties = array();
+ return;
+ }
+ if (!is_array($values)) {
+ if ($values instanceof MapItem) {
+ $values = $values->getValue();
+ }
+ else {
+ $values = unserialize($values);
+ }
+ }
+ $this->properties = array();
+ foreach($values as $name => $value) {
+ $this->{$name} = $value;
+ }
+ }
+
+ public function __get($name) {
+ if (!isset($this->properties[$name])) {
+ $this->{$name} = array();
+ }
+ return $this->properties[$name]->getValue();
+ }
+
+ public function __set($name, $value) {
+ if (isset($value)) {
+ if (isset($this->properties[$name])) {
+ $this->set($name, $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);
+ }
+ }
+ else {
+ unset($this->properties[$name]);
+ }
+ }
+}
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 1039b59..e4b4e3f 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -58,7 +58,7 @@ function book_entity_bundle_info() {
function book_menu_link_load($entities) {
foreach ($entities as $entity) {
// Change the bundle of menu links related to a book.
- if (strpos($entity->menu_name, 'book-toc-') === 0) {
+ if (strpos($entity->menu_name->value, 'book-toc-') === 0) {
$entity->bundle = 'book-toc';
}
}
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index 529fa5c..ebaff55 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['localized_options'] += array('query' => array());
- $item['localized_options']['query'] += drupal_get_destination();
- $links[$class] += $item['localized_options'];
+ $item['options'] += array('query' => array());
+ $item['options']['query'] += drupal_get_destination();
+ $links[$class] += $item['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 2815a91..87c03f0 100644
--- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php
+++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkDeleteForm.php
@@ -18,7 +18,7 @@ class MenuLinkDeleteForm extends EntityConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
- return t('Are you sure you want to delete the custom menu link %item?', array('%item' => $this->entity->link_title));
+ return t('Are you sure you want to delete the custom menu link %item?', array('%item' => $this->entity->link_title->value));
}
/**
@@ -28,7 +28,7 @@ public function getCancelRoute() {
return array(
'route_name' => 'menu.menu_edit',
'route_parameters' => array(
- 'menu' => $this->entity->menu_name,
+ 'menu' => $this->entity->menu_name->value,
),
);
}
@@ -41,7 +41,7 @@ public function submit(array $form, array &$form_state) {
$t_args = array('%title' => $this->entity->link_title);
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->menu_name->value;
}
}
diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php
index 5b79ef4..c6615e8 100644
--- a/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php
+++ b/core/modules/menu/lib/Drupal/menu/Form/MenuLinkResetForm.php
@@ -18,7 +18,7 @@ class MenuLinkResetForm extends EntityConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
- return t('Are you sure you want to reset the link %item to its default values?', array('%item' => $this->entity->link_title));
+ return t('Are you sure you want to reset the link %item to its default values?', array('%item' => $this->entity->link_title->value));
}
/**
@@ -28,7 +28,7 @@ public function getCancelRoute() {
return array(
'route_name' => 'menu.menu_edit',
'route_parameters' => array(
- 'menu' => $this->entity->menu_name,
+ 'menu' => $this->entity->menu_name->value,
),
);
}
@@ -53,7 +53,7 @@ public function getConfirmText() {
public function submit(array $form, array &$form_state) {
$new_menu_link = $this->entity->reset();
drupal_set_message(t('The menu link was reset to its default settings.'));
- $form_state['redirect'] = 'admin/structure/menu/manage/' . $new_menu_link->menu_name;
+ $form_state['redirect'] = 'admin/structure/menu/manage/' . $new_menu_link->menu_name->value;
}
}
diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php
index 68bc6a4..b8e47f7 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['localized_options']);
+ $form[$mlid]['title']['#markup'] = l($item['title'], $item['href'], $item['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 f7e0690..03e4c6d 100644
--- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php
+++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php
@@ -82,7 +82,7 @@ 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.
@@ -448,7 +448,7 @@ public function testMenuBundles() {
$unsaved_item = entity_create('menu_link', array('menu_name' => $menu->id(), 'link_title' => $this->randomName(16), 'link_path' => ''));
$this->assertEqual($unsaved_item->bundle(), $menu->id(), 'Unsaved menu link bundle matches the menu');
- $this->assertEqual($unsaved_item->menu_name, $menu->id(), 'Unsaved menu link menu name matches the menu');
+ $this->assertEqual($unsaved_item->menu_name->value, $menu->id(), 'Unsaved menu link menu name matches the menu');
}
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index 08355a1..bf52e50 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -188,7 +188,7 @@ function menu_enable() {
$system_link = reset($system_link);
$base_link = entity_create('menu_link', array(
- 'menu_name' => $system_link->menu_name,
+ 'menu_name' => $system_link->menu_name->value,
'router_path' => 'admin/structure/menu/manage/%menu',
'module' => 'menu',
));
@@ -198,11 +198,11 @@ function menu_enable() {
$link = $base_link->createDuplicate();
$link->plid = $system_link->id();
$link->link_title = $menu->label();
- $link->link_path = 'admin/structure/menu/manage/' . $menu->id();
+ $link->link_path = 'admin/structure/menu/manage/' . $menu->label();
$query = \Drupal::entityQuery('menu_link')
- ->condition('link_path', $link->link_path)
- ->condition('plid', $link->plid);
+ ->condition('link_path', $link->link_path->value)
+ ->condition('plid', $link->plid->value);
$result = $query->execute();
if (empty($result)) {
@@ -601,7 +601,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->menu_name->value);
if ($delta < 50) {
// Old hardcoded value
$delta = 50;
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 d6493f5..d6ddf85 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,16 @@
namespace Drupal\menu_link\Entity;
-use Drupal\menu_link\MenuLinkInterface;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\HttpFoundation\Request;
-
-use Drupal\Core\Entity\Annotation\EntityType;
use Drupal\Core\Annotation\Translation;
-use Drupal\Core\Entity\EntityStorageException;
+use Drupal\Core\Entity\Annotation\EntityType;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityNG;
use Drupal\Core\Entity\EntityStorageControllerInterface;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\Entity;
+use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\menu_link\MenuLinkInterface;
+use Drupal\menu_link\MenuLinkStorageControllerInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
/**
* Defines the menu link entity class.
@@ -49,14 +48,7 @@
* }
* )
*/
-class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface {
-
- /**
- * The link's menu name.
- *
- * @var string
- */
- public $menu_name = 'tools';
+class MenuLink extends EntityNG implements \ArrayAccess, MenuLinkInterface {
/**
* The link's bundle.
@@ -66,215 +58,40 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface {
public $bundle = 'tools';
/**
- * The menu link ID.
- *
- * @var int
- */
- public $mlid;
-
- /**
- * The menu link UUID.
- *
- * @var string
- */
- public $uuid;
-
- /**
- * The parent link ID.
- *
- * @var int
- */
- public $plid;
-
- /**
- * The Drupal path or external path this link points to.
- *
- * @var string
- */
- public $link_path;
-
- /**
- * For links corresponding to a Drupal path (external = 0), this connects the
- * link to a {menu_router}.path for joins.
- *
- * @var string
- */
- public $router_path;
-
- /**
- * The entity label.
- *
- * @var string
- */
- public $link_title = '';
-
- /**
- * A serialized array of options to be passed to the url() or l() function,
- * such as a query string or HTML attributes.
- *
- * @var array
- */
- public $options = array();
-
- /**
- * The name of the module that generated this link.
- *
- * @var string
- */
- public $module = 'menu';
-
- /**
- * A flag for whether the link should be rendered in menus.
- *
- * @var int
- */
- public $hidden = 0;
-
- /**
- * A flag to indicate if the link points to a full URL starting with a
- * protocol, like http:// (1 = external, 0 = internal).
- *
- * @var int
- */
- public $external;
-
- /**
- * Flag indicating whether any links have this link as a parent.
- *
- * @var int
- */
- public $has_children = 0;
-
- /**
- * Flag for whether this link should be rendered as expanded in menus.
- * Expanded links always have their child links displayed, instead of only
- * when the link is in the active trail.
- *
- * @var int
- */
- public $expanded = 0;
-
- /**
- * Link weight among links in the same menu at the same depth.
- *
- * @var int
- */
- public $weight = 0;
-
- /**
- * The depth relative to the top level. A link with plid == 0 will have
- * depth == 1.
- *
- * @var int
- */
- public $depth;
-
- /**
- * A flag to indicate that the user has manually created or edited the link.
- *
- * @var int
- */
- public $customized = 0;
-
- /**
- * The first entity ID in the materialized path.
- *
- * @var int
- *
- * @todo Investigate whether the p1, p2, .. pX properties can be moved to a
- * single array property.
- */
- public $p1;
-
- /**
- * The second entity ID in the materialized path.
- *
- * @var int
- */
- public $p2;
-
- /**
- * The third entity ID in the materialized path.
- *
- * @var int
- */
- public $p3;
-
- /**
- * The fourth entity ID in the materialized path.
- *
- * @var int
- */
- public $p4;
-
- /**
- * The fifth entity ID in the materialized path.
- *
- * @var int
- */
- public $p5;
-
- /**
- * The sixth entity ID in the materialized path.
- *
- * @var int
- */
- public $p6;
-
- /**
- * The seventh entity ID in the materialized path.
- *
- * @var int
- */
- public $p7;
-
- /**
- * The eighth entity ID in the materialized path.
- *
- * @var int
- */
- public $p8;
-
- /**
- * The ninth entity ID in the materialized path.
- *
- * @var int
- */
- public $p9;
-
- /**
- * The menu link modification timestamp.
+ * The route object associated with this menu link, if any.
*
- * @var int
+ * @var \Symfony\Component\Routing\Route
*/
- public $updated = 0;
+ protected $routeObject;
/**
- * The name of the route associated with this menu link, if any.
+ * Crap coming from the old routing system.
*
- * @var string
- */
- public $route_name;
-
- /**
- * The parameters of the route associated with this menu link, if any.
+ * @todo Remove when we rip out the old routing system.
*
* @var array
*/
- public $route_parameters;
+ protected $oldRouterItem = array();
/**
* The route object associated with this menu link, if any.
*
* @var \Symfony\Component\Routing\Route
*/
- protected $routeObject;
+ protected $oldRoutingProperties = array(
+ 'path', 'load_functions', 'to_arg_functions', 'access_callback',
+ 'access_arguments', 'page_callback', 'page_arguments', 'fit',
+ 'number_parts', 'context', 'tab_parent', 'tab_root', 'title',
+ 'title_callback', 'title_arguments', 'theme_callback', 'theme_arguments',
+ 'type', 'description', 'description_callback', 'description_arguments',
+ 'position', 'include_file', 'route_name',
+ );
/**
- * Overrides Entity::id().
+ * {@inheritdoc}
*/
public function id() {
- return $this->mlid;
+ return $this->get('mlid')->value;
}
/**
@@ -289,7 +106,7 @@ public function bundle() {
*/
public function createDuplicate() {
$duplicate = parent::createDuplicate();
- $duplicate->plid = NULL;
+ $duplicate->get('plid')->offsetGet(0)->set('value', NULL);
return $duplicate;
}
@@ -297,12 +114,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;
}
@@ -324,11 +141,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;
@@ -359,31 +176,78 @@ public static function buildFromRouterItem(array $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)) {
+ return $this->oldRouterItem[$offset];
+ }
+ elseif ($offset == 'options' || $offset == 'localized_options') {
+ return $this->options->getValue();
+ }
+ elseif ($this->getPropertyDefinition($offset)) {
+ return $this->$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 ($offset == 'options' || $offset == 'localized_options') {
+ if (is_array($value)) {
+ foreach ($value as $delta => $value_item) {
+ if (!is_numeric($delta)) {
+ $this->options = array($value);
+ return;
+ }
+ }
+ }
+ }
+ elseif ($this->getPropertyDefinition($offset)) {
+ $this->{$offset} = $value;
+ }
+ else {
+ $this->{$offset} = $value;
+ }
}
/**
- * Implements ArrayAccess::offsetUnset().
+ * {@inheritdoc}
*/
public function offsetUnset($offset) {
- unset($this->{$offset});
+ if (in_array($offset, $this->oldRoutingProperties)) {
+ unset($this->oldRouterItem[$offset]);
+ }
+ else {
+ $this->{$offset}->value = NULL;
+ }
+// unset($this->{$offset});
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function preCreate(EntityStorageControllerInterface $storage_controller, array &$values) {
+ if (empty($values['menu_name'])) {
+ $values['menu_name'] = $values['bundle'] = 'tools';
+ }
}
/**
@@ -397,10 +261,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);
}
}
@@ -419,8 +283,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();
}
}
@@ -436,67 +300,69 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
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()) {
+ 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();
}
}
@@ -509,9 +375,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.
@@ -539,50 +405,50 @@ public static function findRouteNameParameters($link_path) {
return array();
}
}
-
+
/**
* {@inheritdoc}
*/
- public function setParents(EntityInterface $parent) {
+ public function setParents(MenuLinkInterface $parent) {
$i = 1;
- while ($i < $this->depth) {
- $p = 'p' . $i++;
- $this->{$p} = $parent->{$p};
+ while ($i < $this->getDepth()) {
+ $p = 'p' . $i;
+ $this->{$p}->value = $parent->getMaterializedPathEntity($i);
+ $i++;
}
$p = 'p' . $i++;
// The parent (p1 - p9) corresponding to the depth always equals the mlid.
- $this->{$p} = $this->id();
+ $this->{$p}->value = $this->id();
while ($i <= MENU_MAX_DEPTH) {
$p = 'p' . $i++;
- $this->{$p} = 0;
+ $this->{$p}->value = 0;
}
}
/**
* {@inheritdoc}
*/
- public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()) {
+ public function findParent(MenuLinkStorageControllerInterface $storage_controller, array $parent_candidates = array()) {
$parent = FALSE;
+ $plid = $this->getParentLinkId();
// This item is explicitely top-level, skip the rest of the parenting.
- if (isset($this->plid) && empty($this->plid)) {
+ if ($plid === 0) {
return $parent;
}
// If we have a parent link ID, try to use that.
$candidates = array();
- if (isset($this->plid)) {
- $candidates[] = $this->plid;
+ if ($plid) {
+ $candidates = array($plid);
}
// Else, if we have a link hierarchy try to find a valid parent in there.
- if (!empty($this->depth) && $this->depth > 1) {
- for ($depth = $this->depth - 1; $depth >= 1; $depth--) {
- $parent_property = "p$depth";
- $candidates[] = $this->$parent_property;
+ if ($this->getDepth() > 1) {
+ for ($depth = $this->getDepth() - 1; $depth >= 1; $depth--) {
+ $candidates[] = $this->getMaterializedPathEntity($depth);
}
}
-
foreach ($candidates as $mlid) {
if (isset($parent_candidates[$mlid])) {
$parent = $parent_candidates[$mlid];
@@ -598,12 +464,431 @@ 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() {
+ return $this->get('options')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setOptions(array $options) {
+ $this->set('options', $options);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getModule() {
+ return $this->get('module')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setModule($module) {
+ $this->set('module', $module);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setExpanded($expanded) {
+ $this->set('expanded', $expanded ? 1 : 0);
+ }
+
+ /**v
+ */
+ public function isExpanded() {
+ return (bool) $this->get('expanded')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isExternal() {
+ return (bool) $this->get('external')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCustomized($customized) {
+ $this->set('customized', $customized);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCustomized() {
+ return (bool) $this->get('customized')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setHidden($hidden) {
+ $this->set('hidden', $hidden ? 1 : 0);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isHidden() {
+ return (bool)$this->get('hidden')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasChildren() {
+ return (bool)$this->get('has_children')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDepth() {
+ return $this->get('depth')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getWeight() {
+ return $this->get('weight')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setWeight($weight) {
+ $this->set('weight', $weight);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMaterializedPathEntity($depth) {
+ if ($depth < 1 || $depth > 9) {
+ return NULL;
+ }
+ return $this->get('p' . $depth)->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getChangedTime() {
+ return $this->get('updated')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteName() {
+ return $this->get('route_name')->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setRouteName($route_name) {
+ $this->set('route_name', $route_name);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function baseFieldDefinitions($entity_type) {
+ $properties['menu_name'] = array(
+ 'label' => t('Menu name'),
+ 'description' => t('The menu name. All links with the same menu name (such as "tools") are part of the same menu.'),
+ 'type' => 'string_field',
+ 'settings' => array(
+ 'default_value' => 'tools',
+ ),
+ );
+ $properties['mlid'] = array(
+ 'label' => t('Menu link ID'),
+ 'description' => t('The menu link ID.'),
+ 'type' => 'integer_field',
+ 'read-only' => TRUE,
+ );
+ $properties['uuid'] = array(
+ 'label' => t('UUID'),
+ 'description' => t('The menu link UUID.'),
+ 'type' => 'uuid_field',
+ 'read-only' => TRUE,
+ );
+ $properties['plid'] = array(
+ 'label' => t('Parent ID'),
+ 'description' => t('The parent menu link ID.'),
+ 'type' => 'entity_reference_field',
+ 'settings' => array('target_type' => 'menu_link'),
+ );
+ $properties['link_path'] = array(
+ 'label' => t('Link path'),
+ 'description' => t('The Drupal path or external path this link points to.'),
+ 'type' => 'string_field',
+ );
+ $properties['router_path'] = array(
+ 'label' => t('Router path'),
+ 'description' => t('For links corresponding to a Drupal path (external = 0), this connects the link to a {menu_router}.path.'),
+ 'type' => 'string_field',
+ );
+ $properties['langcode'] = array(
+ 'label' => t('Language code'),
+ 'description' => t('The menu link language code.'),
+ 'type' => 'language_field',
+ );
+ $properties['link_title'] = array(
+ 'label' => t('Title'),
+ 'description' => t('The text displayed for the link, which may be modified by a title callback stored in {menu_router}.'),
+ 'type' => 'string_field',
+ 'settings' => array(
+ 'default_value' => '',
+ ),
+ );
+ $properties['options'] = array(
+ 'label' => t('Options'),
+ 'description' => t('A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.'),
+ 'type' => 'map_field',
+ );
+ $properties['module'] = array(
+ 'label' => t('Module'),
+ 'description' => t('The name of the module that generated this link.'),
+ 'type' => 'string_field',
+ 'settings' => array(
+ 'default_value' => 'menu',
+ ),
+ );
+ $properties['hidden'] = array(
+ 'label' => t('Hidden'),
+ 'description' => t('A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link).'),
+ 'type' => 'boolean_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ $properties['external'] = array(
+ 'label' => t('External'),
+ 'description' => t('A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).'),
+ 'type' => 'boolean_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ $properties['has_children'] = array(
+ 'label' => t('Has children'),
+ 'description' => t('Flag indicating whether any links have this link as a parent (1 = children exist, 0 = no children).'),
+ 'type' => 'boolean_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ $properties['expanded'] = array(
+ 'label' => t('Expanded'),
+ 'description' => t('Flag for whether this link should be rendered as expanded in menus - expanded links always have their child links displayed, instead of only when the link is in the active trail (1 = expanded, 0 = not expanded).'),
+ 'type' => 'boolean_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ $properties['weight'] = array(
+ 'label' => t('Weight'),
+ 'description' => t('Link weight among links in the same menu at the same depth.'),
+ 'type' => 'integer_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ $properties['depth'] = array(
+ 'label' => t('Depth'),
+ 'description' => t('The depth relative to the top level. A link with plid == 0 will have depth == 1.'),
+ 'type' => 'integer_field',
+ );
+ $properties['customized'] = array(
+ 'label' => t('Customized'),
+ 'description' => t('A flag to indicate that the user has manually created or edited the link (1 = customized, 0 = not customized).'),
+ 'type' => 'boolean_field',
+ 'settings' => array(
+ 'default_value' => 0,
+ ),
+ );
+ // @todo Declaring these pX properties as integer for the moment, we need to
+ // investigate if using 'entity_reference_field' cripples performance.
+ $properties['p1'] = array(
+ 'label' => t('Parent 1'),
+ 'description' => t('The first mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p2'] = array(
+ 'label' => t('Parent 2'),
+ 'description' => t('The second mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p3'] = array(
+ 'label' => t('Parent 3'),
+ 'description' => t('The third mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p4'] = array(
+ 'label' => t('Parent 4'),
+ 'description' => t('The fourth mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p5'] = array(
+ 'label' => t('Parent 5'),
+ 'description' => t('The fifth mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p6'] = array(
+ 'label' => t('Parent 6'),
+ 'description' => t('The sixth mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p7'] = array(
+ 'label' => t('Parent 7'),
+ 'description' => t('The seventh mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p8'] = array(
+ 'label' => t('Parent 8'),
+ 'description' => t('The eighth mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['p9'] = array(
+ 'label' => t('Parent 9'),
+ 'description' => t('The ninth mlid in the materialized path.'),
+ 'type' => 'integer_field',
+ );
+ $properties['updated'] = array(
+ 'label' => t('Updated'),
+ 'description' => t('Flag that indicates that this link was generated during the update from Drupal 5.'),
+ 'type' => 'boolean_field',
+ );
+ $properties['route_name'] = array(
+ 'label' => t('Route name'),
+ 'description' => t('The machine name of a defined Symfony Route this menu item represents.'),
+ 'type' => 'string_field',
+ );
+ $properties['route_parameters'] = array(
+ 'label' => t('Route parameters'),
+ 'description' => t('A serialized array of route parameters of this menu link.'),
+ 'type' => 'map_field',
+ );
+
+ // @todo Most of these should probably go away.
+ $properties['access'] = array(
+ 'label' => t('(old router) Access'),
+ 'description' => t(''),
+ 'type' => 'boolean_field',
+ 'computed' => TRUE,
+ );
+ $properties['in_active_trail'] = array(
+ 'label' => t('In active trail'),
+ 'description' => t(''),
+ 'type' => 'boolean_field',
+ 'computed' => TRUE,
+ );
+ $properties['localized_options'] = array(
+ 'label' => t('Localized options'),
+ 'description' => t(''),
+ 'type' => 'map_field',
+ 'computed' => TRUE,
+ );
+ return $properties;
+ }
}
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php
index a1c2c69..e710775 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkAccessController.php
@@ -27,11 +27,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
switch ($operation) {
case 'reset':
// Reset allowed for items defined via hook_menu() and customized.
- return $entity->module == 'system' && $entity->customized;
+ return $entity->module->value == 'system' && $entity->customized->value;
case 'delete':
// Only items created by the menu module can be deleted.
- return $entity->module == 'menu' || $entity->updated == 1;
+ return $entity->module->value == 'menu' || $entity->updated->value == 1;
}
}
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
index 8aea21d..7dbbbdb 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
@@ -7,7 +7,8 @@
namespace Drupal\menu_link;
-use Drupal\Core\Entity\EntityFormController;
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Entity\EntityFormControllerNG;
use Drupal\Core\Language\Language;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\Core\Routing\UrlGenerator;
@@ -17,7 +18,7 @@
/**
* Form controller for the node edit forms.
*/
-class MenuLinkFormController extends EntityFormController {
+class MenuLinkFormController extends EntityFormControllerNG {
/**
* The menu link storage controller.
@@ -79,37 +80,37 @@ public function form(array $form, array &$form_state) {
if (!$menu_link->isNew()) {
// Get the human-readable menu title from the given menu name.
$titles = menu_get_menus();
- $current_title = $titles[$menu_link->menu_name];
+ $current_title = $titles[$menu_link->menu_name->value];
// Get the current breadcrumb and add a link to that menu's overview page.
$breadcrumb = menu_get_active_breadcrumb();
- $breadcrumb[] = l($current_title, 'admin/structure/menu/manage/' . $menu_link->menu_name);
+ $breadcrumb[] = l($current_title, 'admin/structure/menu/manage/' . $menu_link->menu_name->value);
drupal_set_breadcrumb($breadcrumb);
}
$form['link_title'] = array(
'#type' => 'textfield',
'#title' => t('Menu link title'),
- '#default_value' => $menu_link->link_title,
+ '#default_value' => $menu_link->link_title->value,
'#description' => t('The text to be used for this link in the menu.'),
'#required' => TRUE,
);
foreach (array('link_path', 'mlid', 'module', 'has_children', 'options') as $key) {
- $form[$key] = array('#type' => 'value', '#value' => $menu_link->{$key});
+ $form[$key] = array('#type' => 'value', '#value' => $menu_link->{$key}->getValue());
}
// Any item created or edited via this interface is considered "customized".
$form['customized'] = array('#type' => 'value', '#value' => 1);
// We are not using url() when constructing this path because it would add
// $base_path.
- $path = $menu_link->link_path;
- if (isset($menu_link->options['query'])) {
- $path .= '?' . $this->urlGenerator->httpBuildQuery($menu_link->options['query']);
+ $path = $menu_link->link_path->value;
+ if (isset($menu_link->options->query)) {
+ $path .= '?' . $this->urlGenerator->httpBuildQuery($menu_link->options->query);
}
- if (isset($menu_link->options['fragment'])) {
- $path .= '#' . $menu_link->options['fragment'];
+ if (isset($menu_link->options->fragment)) {
+ $path .= '#' . $menu_link->options->fragment;
}
- if ($menu_link->module == 'menu') {
+ if ($menu_link->module->value == 'menu') {
$form['link_path'] = array(
'#type' => 'textfield',
'#title' => t('Path'),
@@ -123,33 +124,33 @@ public function form(array $form, array &$form_state) {
$form['_path'] = array(
'#type' => 'item',
'#title' => t('Path'),
- '#description' => l($menu_link->link_title, $menu_link->href, $menu_link->options),
+ '#description' => l($menu_link->link_title->value, $menu_link->href, $menu_link['options']),
);
}
$form['description'] = array(
'#type' => 'textarea',
'#title' => t('Description'),
- '#default_value' => isset($menu_link->options['attributes']['title']) ? $menu_link->options['attributes']['title'] : '',
+ '#default_value' => isset($menu_link->options->attributes['title']) ? $menu_link->options->attributes['title'] : '',
'#rows' => 1,
'#description' => t('Shown when hovering over the menu link.'),
);
$form['enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Enabled'),
- '#default_value' => !$menu_link->hidden,
+ '#default_value' => !$menu_link->hidden->value,
'#description' => t('Menu links that are not enabled will not be listed in any menu.'),
);
$form['expanded'] = array(
'#type' => 'checkbox',
'#title' => t('Show as expanded'),
- '#default_value' => $menu_link->expanded,
+ '#default_value' => $menu_link->expanded->value,
'#description' => t('If selected and this menu link has children, the menu will always appear expanded.'),
);
// Generate a list of possible parents (not including this link or descendants).
$options = menu_parent_options(menu_get_menus(), $menu_link);
- $default = $menu_link->menu_name . ':' . $menu_link->plid;
+ $default = $menu_link->menu_name->value . ':' . $menu_link->plid->target_id;
if (!isset($options[$default])) {
$default = 'tools:0';
}
@@ -163,13 +164,13 @@ public function form(array $form, array &$form_state) {
);
// Get number of items in menu so the weight selector is sized appropriately.
- $delta = $this->menuLinkStorageController->countMenuLinks($menu_link->menu_name);
+ $delta = $this->menuLinkStorageController->countMenuLinks($menu_link->menu_name->value);
$form['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
// Old hardcoded value.
'#delta' => max($delta, 50),
- '#default_value' => $menu_link->weight,
+ '#default_value' => $menu_link->weight->value,
'#description' => t('Optional. In the menu, the heavier links will sink and the lighter links will be positioned nearer the top.'),
);
@@ -179,13 +180,13 @@ public function form(array $form, array &$form_state) {
// be configured individually.
if ($this->moduleHandler->moduleExists('language')) {
$language_configuration = language_get_default_configuration('menu_link', $menu_link->bundle());
- $default_langcode = ($menu_link->isNew() ? $language_configuration['langcode'] : $menu_link->langcode);
+ $default_langcode = ($menu_link->isNew() ? $language_configuration['langcode'] : $menu_link->langcode->value);
$language_show = $language_configuration['language_show'];
}
// Without Language module menu links inherit the menu language and no
// language selector is shown.
else {
- $default_langcode = ($menu_link->isNew() ? entity_load('menu', $menu_link->menu_name)->langcode : $menu_link->langcode);
+ $default_langcode = ($menu_link->isNew() ? entity_load('menu', $menu_link->menu_name->value)->langcode : $menu_link->langcode->value);
$language_show = FALSE;
}
@@ -212,74 +213,63 @@ 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) {
+ $normal_path = $this->pathAliasManager->getSystemPath($menu_link->link_path->value);
+ if ($menu_link->link_path->value != $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;
$form_state['values']['link_path'] = $normal_path;
+ $menu_link->link_path->value = $normal_path;
}
- if (!url_is_external($menu_link->link_path)) {
- $parsed_link = parse_url($menu_link->link_path);
+ if (!url_is_external($menu_link->link_path->value)) {
+ $parsed_link = parse_url($menu_link->link_path->value);
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->link_path->value != $parsed_link['path']) {
+ $menu_link->link_path->value = $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->link_path->value) || !drupal_valid_path($menu_link->link_path->value, 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->value)));
}
parent::validate($form, $form_state);
}
- /**
- * Overrides EntityFormController::submit().
- */
- public function submit(array $form, array &$form_state) {
- // Build the menu link object from the submitted values.
- $menu_link = parent::submit($form, $form_state);
-
+ public function buildEntity(array $form, array &$form_state) {
+ $entity = parent::buildEntity($form, $form_state);
// The value of "hidden" is the opposite of the value supplied by the
// "enabled" checkbox.
- $menu_link->hidden = (int) !$menu_link->enabled;
- unset($menu_link->enabled);
-
- $menu_link->options['attributes']['title'] = $menu_link->description;
- list($menu_link->menu_name, $menu_link->plid) = explode(':', $menu_link->parent);
-
- return $menu_link;
+ $entity->hidden->value = (int) !$form_state['values']['enabled'];
+ list($entity->menu_name->value, $entity->plid->target_id) = explode(':', $form_state['values']['parent']);
+ $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->menu_name->value;
}
else {
drupal_set_message(t('There was an error saving the menu link.'), 'error');
@@ -291,7 +281,6 @@ public function save(array $form, array &$form_state) {
* Overrides EntityFormController::delete().
*/
public function delete(array $form, array &$form_state) {
- $menu_link = $this->entity;
- $form_state['redirect'] = 'admin/structure/menu/item/' . $menu_link->id() . '/delete';
+ $form_state['redirect'] = 'admin/structure/menu/item/' . $this->entity->id() . '/delete';
}
}
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php
index b8e639e..acb4549 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,282 @@ public function setParents(EntityInterface $parent);
* A menu link entity structure of the possible parent or FALSE if no valid
* parent has been found.
*/
- public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array());
+ public function findParent(MenuLinkStorageControllerInterface $storage_controller, array $parent_candidates = array());
+
+ /**
+ * Returns the menu name of this menu link.
+ *
+ * @return string
+ * The name of the menu.
+ */
+ public function getMenuName();
+
+ /**
+ * Sets the menu name of this menu link.
+ *
+ * @param string $menu_name
+ * The name of the menu.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setMenuName($menu_name);
+
+ /**
+ * Returns the parent menu link ID of this menu link.
+ *
+ * @return int
+ * The parent link ID of the menu.
+ */
+ public function getParentLinkId();
+
+ /**
+ * Sets the parent menu link id of this menu link.
+ *
+ * @param int $plid
+ * The parent link ID of the menu.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setParentLinkId($plid);
+
+ /**
+ * Returns the Drupal path or external path this link points to.
+ *
+ * @return string
+ * The Drupal path or external path this link points to.
+ */
+ public function getLinkPath();
+
+ /**
+ * Sets the Drupal path or external path this link points to.
+ *
+ * @param string $link_path
+ * The the Drupal path or external path this link points to.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setLinkPath($link_path);
+
+ /**
+ * Returns the title of this menu link.
+ *
+ * @return string
+ * The title of this menu link.
+ */
+ public function getLinkTitle();
+
+ /**
+ * Sets the title of this menu link.
+ *
+ * @param string $link_title
+ * The title of this menu link.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setLinkTitle($link_title);
+
+ /**
+ * Returns the menu router path for this link.
+ *
+ * @return string
+ * The menu router path for this link.
+ */
+ public function getRouterPath();
+
+ /**
+ * Sets the Drupal path or external path this link points to.
+ *
+ * @param string $router_path
+ * The menu router path for this link.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setRouterPath($router_path);
+
+ /**
+ * Returns the menu link options.
+ *
+ * @return array
+ * The menu link options, to be passed to to l() or url().
+ */
+ public function getOptions();
+
+ /**
+ * Sets the menu link options.
+ *
+ * @todo: Add a method to add options?
+ *
+ * @param array $options
+ * The menu link options.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setOptions(array $options);
+
+ /**
+ * Returns the name of the module that generated this link.
+ *
+ * @return string
+ * The name of the module that generated this link.
+ */
+ public function getModule();
+
+ /**
+ * Sets the name of the module that generated this link.
+ *
+ * @param string $module
+ * The name of the module that generated this link.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setModule($module);
+
+ /**
+ * Sets whether the menu link is expanded.
+ *
+ * @param bool $expanded
+ * TRUE if the menu link is expanded, FALSE if not.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setExpanded($expanded);
+
+ /**
+ * Returns whether the menu link is expanded
+ *
+ * @return string
+ * TRUE if the menu link is expanded, FALSE if not.
+ */
+ public function isExpanded();
+
+ /**
+ * Returns whether the menu link is external.
+ *
+ * @return string
+ * TRUE if the menu link is external, FALSE if not.
+ */
+ public function isExternal();
+
+ /**
+ * Sets if the menu link is customized.
+ *
+ * @param bool $customized
+ * TRUE if the menu link is customized, FALSE if not.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setCustomized($customized);
+
+ /**
+ * Returns whether the menu link is customized.
+ *
+ * @return string
+ * TRUE if the menu link is customized, FALSE if not.
+ */
+ public function isCustomized();
+
+ /**
+ * Sets whether the menu link is hidden.
+ *
+ * @param bool $hidden
+ * TRUE if the menu link is hidden, FALSE if not.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setHidden($hidden);
+
+ /**
+ * Returns whether the menu link is hidden.
+ *
+ * @return string
+ * TRUE if the menu link is hidden, FALSE if not.
+ */
+ public function isHidden();
+
+ /**
+ * Returns whether the menu link is expanded
+ *
+ * @return string
+ * TRUE if the menu link has children, FALSE if not.
+ */
+ public function hasChildren();
+
+ /**
+ * Returns the depth relative to the top level of this link.
+ *
+ * A link with parent ID 0 will have depth of 1.
+ *
+ * @return int
+ * The menu link depth.
+ */
+ public function getDepth();
+
+ /**
+ * Returns the weight among menu links with the same depth.
+ *
+ * @return int
+ * The menu link weight.
+ */
+ public function getWeight();
+
+ /**
+ * Sets the weight among menu links with the same depth.
+ *
+ *ยท@param int $weight
+ * The menu link weight.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setWeight($weight);
+
+ /**
+ * Returns the nth depth entity ID of the materialized path.
+ *
+ * @param int $depth
+ * Indicates the depth of entity ID of the materialized path that should be
+ * returned, between 1 and 9.
+ *
+ * @return int
+ * Nth Entity ID of the materialized path.
+ */
+ public function getMaterializedPathEntity($depth);
+
+ /**
+ * Returns the menu link modification timestamp.
+ *
+ * @return int
+ * Menu link modification timestamp.
+ */
+ public function getChangedTime();
+
+ /**
+ * Returns the route name associated with this menu link, if any.
+ *
+ * @return string|null
+ * The route name of this menu link.
+ */
+ public function getRouteName();
+
+ /**
+ * Sets the route name associated with this menu link.
+ *
+ * @param string|null $route_name
+ * The route name associated with this menu link.
+ *
+ * @return \Drupal\menu_link\MenuLinkInterface
+ * The called menu link entity.
+ */
+ public function setRouteName($route_name);
+
}
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 7330147..c221df5 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
@@ -7,7 +7,7 @@
namespace Drupal\menu_link;
-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;
@@ -16,12 +16,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.
@@ -94,7 +91,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);
@@ -105,51 +102,61 @@ 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 = unserialize($record->route_parameters);
// 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);
- parent::attachLoad($menu_links, $load_revision);
+ foreach ($entities as &$entity) {
+ foreach (static::$routerItemFields as $router_field) {
+ $entity->offsetSet($router_field, $records[$entity->id()]->{$router_field});
+ }
+ }
+
+ return $entities;
}
/**
* 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.
@@ -157,6 +164,12 @@ 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();
+
// Load the stored entity, if any.
if (!$entity->isNew() && !isset($entity->original)) {
$entity->original = entity_load_unchanged($this->entityType, $entity->id());
@@ -179,20 +192,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);
@@ -234,6 +273,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()
@@ -244,16 +287,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;
}
/**
@@ -277,13 +316,13 @@ public function loadModuleAdminTasks() {
*/
public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE) {
// If plid == 0, there is nothing to update.
- if ($entity->plid) {
+ if ($entity->plid->target_id) {
// Check if at least one visible child exists in the table.
$query = \Drupal::entityQuery($this->entityType);
$query
- ->condition('menu_name', $entity->menu_name)
+ ->condition('menu_name', $entity->menu_name->value)
->condition('hidden', 0)
- ->condition('plid', $entity->plid)
+ ->condition('plid', $entity->plid->target_id)
->count();
if ($exclude) {
@@ -293,7 +332,7 @@ public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE)
$parent_has_children = ((bool) $query->execute()) ? 1 : 0;
$this->database->update('menu_links')
->fields(array('has_children' => $parent_has_children))
- ->condition('mlid', $entity->plid)
+ ->condition('mlid', $entity->plid->target_id)
->execute();
}
}
@@ -306,20 +345,20 @@ public function findChildrenRelativeDepth(EntityInterface $entity) {
// make sense to convert to EFQ?
$query = $this->database->select('menu_links');
$query->addField('menu_links', 'depth');
- $query->condition('menu_name', $entity->menu_name);
+ $query->condition('menu_name', $entity->menu_name->value);
$query->orderBy('depth', 'DESC');
$query->range(0, 1);
$i = 1;
$p = 'p1';
- while ($i <= MENU_MAX_DEPTH && $entity->{$p}) {
- $query->condition($p, $entity->{$p});
+ while ($i <= MENU_MAX_DEPTH && $entity->{$p}->value) {
+ $query->condition($p, $entity->{$p}->value);
$p = 'p' . ++$i;
}
$max_depth = $query->execute()->fetchField();
- return ($max_depth > $entity->depth) ? $max_depth - $entity->depth : 0;
+ return ($max_depth > $entity->depth->value) ? $max_depth - $entity->depth->value : 0;
}
/**
@@ -328,14 +367,14 @@ public function findChildrenRelativeDepth(EntityInterface $entity) {
public function moveChildren(EntityInterface $entity) {
$query = $this->database->update($this->entityInfo['base_table']);
- $query->fields(array('menu_name' => $entity->menu_name));
+ $query->fields(array('menu_name' => $entity->menu_name->value));
$p = 'p1';
$expressions = array();
- for ($i = 1; $i <= $entity->depth; $p = 'p' . ++$i) {
- $expressions[] = array($p, ":p_$i", array(":p_$i" => $entity->{$p}));
+ for ($i = 1; $i <= $entity->depth->value; $p = 'p' . ++$i) {
+ $expressions[] = array($p, ":p_$i", array(":p_$i" => $entity->{$p}->value));
}
- $j = $entity->original->depth + 1;
+ $j = $entity->original->depth->value + 1;
while ($i <= MENU_MAX_DEPTH && $j <= MENU_MAX_DEPTH) {
$expressions[] = array('p' . $i++, 'p' . $j++, array());
}
@@ -343,7 +382,7 @@ public function moveChildren(EntityInterface $entity) {
$expressions[] = array('p' . $i++, 0, array());
}
- $shift = $entity->depth - $entity->original->depth;
+ $shift = $entity->depth->value - $entity->original->depth->value;
if ($shift > 0) {
// The order of expressions must be reversed so the new values don't
// overwrite the old ones before they can be used because "Single-table
@@ -356,10 +395,10 @@ public function moveChildren(EntityInterface $entity) {
}
$query->expression('depth', 'depth + :depth', array(':depth' => $shift));
- $query->condition('menu_name', $entity->original->menu_name);
+ $query->condition('menu_name', $entity->original->menu_name->value);
$p = 'p1';
- for ($i = 1; $i <= MENU_MAX_DEPTH && $entity->original->{$p}; $p = 'p' . ++$i) {
- $query->condition($p, $entity->original->{$p});
+ for ($i = 1; $i <= MENU_MAX_DEPTH && $entity->original->{$p}->value; $p = 'p' . ++$i) {
+ $query->condition($p, $entity->original->{$p}->value);
}
$query->execute();
@@ -383,7 +422,7 @@ public function countMenuLinks($menu_name) {
* {@inheritdoc}
*/
public function getParentFromHierarchy(EntityInterface $entity) {
- $parent_path = $entity->link_path;
+ $parent_path = $entity->link_path->value;
do {
$parent = FALSE;
$parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
@@ -394,7 +433,7 @@ public function getParentFromHierarchy(EntityInterface $entity) {
->condition('module', 'system')
// We always respect the link's 'menu_name'; inheritance for router
// items is ensured in _menu_router_build().
- ->condition('menu_name', $entity->menu_name)
+ ->condition('menu_name', $entity->menu_name->value)
->condition('link_path', $parent_path);
$result = $query->execute();
diff --git a/core/modules/menu_link/menu_link.api.php b/core/modules/menu_link/menu_link.api.php
index bfb8a2e..f5ec959 100644
--- a/core/modules/menu_link/menu_link.api.php
+++ b/core/modules/menu_link/menu_link.api.php
@@ -32,7 +32,7 @@
*/
function hook_menu_link_load($menu_links) {
foreach ($menu_links as $menu_link) {
- if ($menu_link->href == 'devel/cache/clear') {
+ if ($menu_link->href->value == 'devel/cache/clear') {
$menu_link->options['query'] = drupal_get_destination();
}
}
@@ -49,17 +49,17 @@ function hook_menu_link_load($menu_links) {
*/
function hook_menu_link_presave(\Drupal\menu_link\Entity\MenuLink $menu_link) {
// Make all new admin links hidden (a.k.a disabled).
- if (strpos($menu_link->link_path, 'admin') === 0 && $menu_link->isNew()) {
+ if (strpos($menu_link->link_path->value, 'admin') === 0 && $menu_link->isNew()) {
$menu_link->hidden = 1;
}
// Flag a link to be altered by hook_menu_link_load().
- if ($menu_link->link_path == 'devel/cache/clear') {
+ if ($menu_link->link_path->value == 'devel/cache/clear') {
$menu_link->options['alter'] = TRUE;
}
// Flag a menu link to be altered by hook_menu_link_load(), but only if it is
// derived from a menu router item; i.e., do not alter a custom menu link
// pointing to the same path that has been created by a user.
- if ($menu_link->link_path == 'user' && $menu_link->module == 'system') {
+ if ($menu_link->link_path->value == 'user' && $menu_link->module == 'system') {
$menu_link->options['alter'] = TRUE;
}
}
@@ -82,7 +82,7 @@ function hook_menu_link_insert(\Drupal\menu_link\Entity\MenuLink $menu_link) {
// In our sample case, we track menu items as editing sections
// of the site. These are stored in our table as 'disabled' items.
$record['mlid'] = $menu_link->id();
- $record['menu_name'] = $menu_link->menu_name;
+ $record['menu_name'] = $menu_link->menu_name->value;
$record['status'] = 0;
drupal_write_record('menu_example', $record);
}
@@ -104,9 +104,9 @@ function hook_menu_link_insert(\Drupal\menu_link\Entity\MenuLink $menu_link) {
function hook_menu_link_update(\Drupal\menu_link\Entity\MenuLink $menu_link) {
// If the parent menu has changed, update our record.
$menu_name = db_query("SELECT menu_name FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $menu_link->id()))->fetchField();
- if ($menu_name != $menu_link->menu_name) {
+ if ($menu_name != $menu_link->menu_name->value) {
db_update('menu_example')
- ->fields(array('menu_name' => $menu_link->menu_name))
+ ->fields(array('menu_name' => $menu_link->menu_name->value))
->condition('mlid', $menu_link->id())
->execute();
}
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php
index a0012dc..6f0008f 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/LinkDelete.php
@@ -33,7 +33,7 @@ public function getFormID() {
* {@inheritdoc}
*/
public function getQuestion() {
- return t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->menuLink->link_title));
+ return t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->menuLink->link_title->value));
}
/**
@@ -43,7 +43,7 @@ public function getCancelRoute() {
return array(
'route_name' => 'shortcut.set_customize',
'route_parameters' => array(
- 'shortcut_set' => str_replace('shortcut-', '', $this->menuLink->menu_name),
+ 'shortcut_set' => str_replace('shortcut-', '', $this->menuLink->menu_name->value),
),
);
}
@@ -68,10 +68,10 @@ public function buildForm(array $form, array &$form_state, MenuLink $menu_link =
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
- menu_link_delete($this->menuLink->mlid);
- $set_name = str_replace('shortcut-', '' , $this->menuLink->menu_name);
+ menu_link_delete($this->menuLink->id());
+ $set_name = str_replace('shortcut-', '' , $this->menuLink->menu_name->value);
$form_state['redirect'] = 'admin/config/user-interface/shortcut/manage/' . $set_name;
- drupal_set_message(t('The shortcut %title has been deleted.', array('%title' => $this->menuLink->link_title)));
+ drupal_set_message(t('The shortcut %title has been deleted.', array('%title' => $this->menuLink->link_title->value)));
}
}
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php
index 29da4a8..97aafee 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/SetCustomize.php
@@ -38,13 +38,13 @@ public function form(array $form, array &$form_state) {
foreach ($this->entity->links as $link) {
$mlid = $link->id();
$form['shortcuts']['links'][$mlid]['#attributes']['class'][] = 'draggable';
- $form['shortcuts']['links'][$mlid]['name']['#markup'] = l($link->link_title, $link->link_path);
- $form['shortcuts']['links'][$mlid]['#weight'] = $link->weight;
+ $form['shortcuts']['links'][$mlid]['name']['#markup'] = l($link->link_title->value, $link->link_path->value);
+ $form['shortcuts']['links'][$mlid]['#weight'] = $link->weight->value;
$form['shortcuts']['links'][$mlid]['weight'] = array(
'#type' => 'weight',
- '#title' => t('Weight for @title', array('@title' => $link->link_title)),
+ '#title' => t('Weight for @title', array('@title' => $link->link_title->value)),
'#title_display' => 'invisible',
- '#default_value' => $link->weight,
+ '#default_value' => $link->weight->value,
'#attributes' => array('class' => array('shortcut-weight')),
);
@@ -88,7 +88,7 @@ protected function actions(array $form, array &$form_state) {
*/
public function save(array $form, array &$form_state) {
foreach ($this->entity->links as $link) {
- $link->weight = $form_state['values']['shortcuts']['links'][$link->mlid]['weight'];
+ $link->weight = $form_state['values']['shortcuts']['links'][$link->id()]['weight'];
$link->save();
}
drupal_set_message(t('The shortcut set has been updated.'));
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
index bd2d194..e14b042 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
@@ -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->link_path), 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->link_title->value, '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 e47b5ed..41ad670 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -56,7 +56,7 @@ function shortcut_entity_bundle_info() {
function shortcut_menu_link_load($entities) {
foreach ($entities as $entity) {
// Change the bundle of menu links related to a shortcut.
- if (strpos($entity->menu_name, 'shortcut-') === 0) {
+ if (strpos($entity->menu_name->value, 'shortcut-') === 0) {
$entity->bundle = 'shortcut';
}
}
@@ -235,9 +235,9 @@ function shortcut_link_access($menu_link) {
*/
function shortcut_menu_link_delete($menu_link) {
// If the deleted menu link was in a shortcut set, remove it.
- if (strpos($menu_link->menu_name, 'shortcut-') === 0) {
- $shortcut = entity_load('shortcut_set', str_replace('shortcut-', '', $menu_link->menu_name));
- unset($shortcut->links[$menu_link->uuid]);
+ if (strpos($menu_link->menu_name->value, 'shortcut-') === 0) {
+ $shortcut = entity_load('shortcut_set', str_replace('shortcut-', '', $menu_link->menu_name->value));
+ unset($shortcut->links[$menu_link->uuid()]);
$shortcut->save();
}
}
diff --git a/core/modules/system/lib/Drupal/system/Controller/SystemController.php b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
index 470b5bb..2469157 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();
@@ -93,9 +93,13 @@ public function overview() {
// 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']);
+ unset($item->localized_options->attributes['title']);
}
- $block = $item;
+ $block = array(
+ 'title' => $item->getLinkTitle(),
+ 'description' => $item['description'],
+ 'position' => $item['position'],
+ );
$block['content'] = array(
'#theme' => 'admin_block_content',
'#content' => $this->systemManager->getAdminBlock($item),
diff --git a/core/modules/system/lib/Drupal/system/SystemManager.php b/core/modules/system/lib/Drupal/system/SystemManager.php
index 619642e..5c12997 100644
--- a/core/modules/system/lib/Drupal/system/SystemManager.php
+++ b/core/modules/system/lib/Drupal/system/SystemManager.php
@@ -198,7 +198,7 @@ public function getAdminBlock($item) {
$menu_links = $this->menuLinkStorage->loadByProperties(array('router_path' => $item['path'], 'module' => 'system'));
$menu_link = reset($menu_links);
$item['mlid'] = $menu_link->id();
- $item['menu_name'] = $menu_link->menu_name;
+ $item['menu_name'] = $menu_link->menu_name->value;
}
if (isset($this->menuItems[$item['mlid']])) {
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 61aa89a..87b89eb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php
@@ -323,7 +323,7 @@ function testMenuName() {
$menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test'));
$menu_link = reset($menu_links);
- $this->assertEqual($menu_link->menu_name, 'original', 'Menu name is "original".');
+ $this->assertEqual($menu_link->menu_name->value, 'original', 'Menu name is "original".');
// Change the menu_name parameter in menu_test.module, then force a menu
// rebuild.
@@ -333,7 +333,7 @@ function testMenuName() {
$menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test'));
$menu_link = reset($menu_links);
- $this->assertEqual($menu_link->menu_name, 'changed', 'Menu name was successfully changed after rebuild.');
+ $this->assertEqual($menu_link->menu_name->value, 'changed', 'Menu name was successfully changed after rebuild.');
}
/**
@@ -364,7 +364,7 @@ function testMenuHidden() {
$links = array();
foreach ($menu_links as $menu_link) {
- $links[$menu_link->router_path] = $menu_link;
+ $links[$menu_link->router_path->value] = $menu_link;
}
$parent = $links['menu-test/hidden/menu'];
@@ -416,7 +416,7 @@ function testMenuHidden() {
$links = array();
foreach ($menu_links as $menu_link) {
- $links[$menu_link->router_path] = $menu_link;
+ $links[$menu_link->router_path->value] = $menu_link;
}
$parent = $links['menu-test/hidden/block'];
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php
index 263e2fc..6714e13 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php
@@ -20,6 +20,13 @@
class TreeAccessTest extends DrupalUnitTestBase {
/**
+ * Modules to enable.
+ *
+ * @var array
+ */
+ public static $modules = array('menu_link');
+
+ /**
* A list of menu links used for this test.
*
* @var array
@@ -93,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..e771e4f 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('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 5f6d62f..305e9ac 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -334,7 +334,7 @@ function theme_admin_block_content($variables) {
}
$output .= '';
foreach ($content as $item) {
- $output .= '- ' . l($item['title'], $item['href'], $item['localized_options']) . '
';
+ $output .= '- ' . l($item['link_title'], $item['link_path'], $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 378bad0..18755e0 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2263,6 +2263,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/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 604e04d..6eb483d 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -507,7 +507,8 @@ 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(
+ $l_options = $tree[$key]['link']['localized_options'];
+ $l_options['attributes'] = array(
'id' => 'toolbar-link-' . str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['link_path']),
'class' => array(
'toolbar-icon',
@@ -515,6 +516,7 @@ function toolbar_menu_navigation_links(&$tree) {
),
'title' => check_plain($item['link']['description']),
);
+ $tree[$key]['link']['localized_options'] = $l_options;
}
}
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 3bc4534..8898f86 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -885,13 +885,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;
}
}
@@ -913,8 +913,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;
}
}
}