diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 08c7aff..caa757d 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -870,7 +870,7 @@ function menu_tail_load($arg, &$map, $index) { */ function _menu_link_translate(&$item, $translate = FALSE) { if (!is_array($item['options'])) { - $item['options'] = unserialize($item['options']); + //$item['options'] = unserialize($item['options']); } if ($item['external']) { $item['access'] = 1; @@ -1883,7 +1883,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']['localized_options']->getValue(); $l['href'] = $item['link']['href']; $l['title'] = $item['link']['title']; if ($item['link']['in_active_trail']) { @@ -2651,7 +2651,7 @@ function menu_get_active_breadcrumb() { } foreach ($active_trail as $parent) { - $breadcrumb[] = l($parent['title'], $parent['href'], $parent['localized_options']); + $breadcrumb[] = l($parent['title'], $parent['href'], is_array($parent['localized_options']) ? $parent['localized_options'] : $parent['localized_options']->getValue()); } } return $breadcrumb; @@ -2899,8 +2899,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); @@ -2917,14 +2917,14 @@ 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; + $menu_link->router_path->value = $router_path; + $menu_link->updated->value = (int) $updated; $menu_link_controller->save($menu_link); } } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 7bff76e..2e69daf 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1762,9 +1762,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..073654b --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/MapItem.php @@ -0,0 +1,115 @@ + 'map', + 'label' => t('Array values'), + ); + } + return static::$propertyDefinitions; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Whether a offset exists + * @link http://php.net/manual/en/arrayaccess.offsetexists.php + * @param mixed $offset

+ * An offset to check for. + *

+ * @return boolean true on success or false on failure. + *

+ *

+ * The return value will be casted to boolean if non-boolean was returned. + */ + public function offsetExists($offset) { + return !(isset($this->values[$offset]) && isset($this->properties[$offset])); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Offset to retrieve + * @link http://php.net/manual/en/arrayaccess.offsetget.php + * @param mixed $offset

+ * The offset to retrieve. + *

+ * @return mixed Can return all value types. + */ + public function offsetGet($offset) { + // There is either a property object or a plain value - possibly for a + // not-defined property. If we have a plain value, directly return it. + if (isset($this->values[$offset])) { + return $this->values[$offset]; + } + elseif (isset($this->properties[$offset])) { + return $this->properties[$offset]->getValue(); + } + } + + /** + * (PHP 5 >= 5.0.0)
+ * Offset to set + * @link http://php.net/manual/en/arrayaccess.offsetset.php + * @param mixed $offset

+ * The offset to assign the value to. + *

+ * @param mixed $value

+ * The value to set. + *

+ * @return void + */ + public function offsetSet($offset, $value) { + $this->set($offset, $value); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Offset to unset + * @link http://php.net/manual/en/arrayaccess.offsetunset.php + * @param mixed $offset

+ * The offset to unset. + *

+ * @return void + */ + public function offsetUnset($offset) { + $this->set($offset, NULL); + } + + +} diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index df5f602..c0df0f3 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -210,7 +210,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/%', 'module' => 'menu', )); @@ -223,8 +223,8 @@ function menu_enable() { $link->link_path = 'admin/structure/menu/manage/' . $menu->id(); $query = Drupal::entityQuery('menu_link') - ->condition('link_path', $link->link_path) - ->condition('plid', $link->plid); + ->condition('link_path', $link->link_path->value) + ->condition('plid', $link->plid->value); $result = $query->execute(); if (empty($result)) { 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 8eb4458..a2118a3 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -8,7 +8,7 @@ namespace Drupal\menu_link; use Drupal\Core\Entity\EntityControllerInterface; -use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityFormControllerNG; use Drupal\Core\Language\Language; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Path\AliasManagerInterface; @@ -19,7 +19,7 @@ /** * Form controller for the node edit forms. */ -class MenuLinkFormController extends EntityFormController implements EntityControllerInterface { +class MenuLinkFormController extends EntityFormControllerNG implements EntityControllerInterface { /** * The menu link storage controller. @@ -81,37 +81,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}->value); } // 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->value['query'])) { + $path .= '?' . $this->urlGenerator->httpBuildQuery($menu_link->options->value['query']); } - if (isset($menu_link->options['fragment'])) { - $path .= '#' . $menu_link->options['fragment']; + if (isset($menu_link->options->value['fragment'])) { + $path .= '#' . $menu_link->options->value['fragment']; } - if ($menu_link->module == 'menu') { + if ($menu_link->module->value == 'menu') { $form['link_path'] = array( '#type' => 'textfield', '#title' => t('Path'), @@ -125,33 +125,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->value, $menu_link->options->value), ); } $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->value['attributes']['title']) ? $menu_link->options->value['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'; } @@ -165,13 +165,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.'), ); @@ -181,13 +181,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; } @@ -208,45 +208,45 @@ public function form(array $form, array &$form_state) { protected function actions(array $form, array &$form_state) { $element = parent::actions($form, $form_state); $element['submit']['#button_type'] = 'primary'; - $element['delete']['#access'] = $this->entity->module == 'menu'; + $element['delete']['#access'] = $this->entity->module->value == 'menu'; return $element; } /** - * 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; + $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(); + $menu_link->options->value['query'] = array(); parse_str($parsed_link['query'], $menu_link->options['query']); } else { // Use unset() rather than setting to empty string // to avoid redundant serialized data being stored. - unset($menu_link->options['query']); + unset($menu_link->options->value['query']); } if (isset($parsed_link['fragment'])) { - $menu_link->options['fragment'] = $parsed_link['fragment']; + $menu_link->options->value['fragment'] = $parsed_link['fragment']; } else { - unset($menu_link->options['fragment']); + unset($menu_link->options->value['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); @@ -261,11 +261,12 @@ public function submit(array $form, array &$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->hidden->value = (int) !$menu_link->enabled->value; + // @todo Check out this 'enabled' stuff. +// unset($menu_link->enabled); - $menu_link->options['attributes']['title'] = $menu_link->description; - list($menu_link->menu_name, $menu_link->plid) = explode(':', $menu_link->parent); + $menu_link->options->value['attributes']['title'] = $menu_link->description->value; + list($menu_link->menu_name->value, $menu_link->plid->target_id) = explode(':', $menu_link->parent); return $menu_link; } @@ -274,13 +275,9 @@ public function submit(array $form, array &$form_state) { * 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'); @@ -292,7 +289,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 c185dc4..999385b 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. @@ -85,7 +84,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. @@ -94,5 +93,5 @@ 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()); } 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 43d54ce..ebfd73a 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; @@ -15,12 +15,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. @@ -44,16 +41,7 @@ class MenuLinkStorageController extends DatabaseStorageController implements Men protected $routeProvider; /** - * Overrides DatabaseStorageController::__construct(). - * - * @param string $entity_type - * The entity type for which the instance is created. - * @param array $entity_info - * An array of entity info for the entity type. - * @param \Drupal\Core\Database\Connection $database - * The database connection to be used. - * @param \Symfony\Cmf\Component\Routing\RouteProviderInterface $route_provider - * The route provider service. + * {@inheritdoc} */ public function __construct($entity_type, array $entity_info, Connection $database, RouteProviderInterface $route_provider) { parent::__construct($entity_type, $entity_info, $database); @@ -90,7 +78,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); @@ -101,50 +89,60 @@ 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); + foreach ($queried_entities as &$record) { + $record->options = unserialize($record->options); // Use the weight property from the menu link. - $menu_link->router_item['weight'] = $menu_link->weight; + $record->router_item['weight'] = $record->weight; // By default use the menu_name as type. - $menu_link->bundle = $menu_link->menu_name; + $record->bundle = $record->menu_name; // For all links that have an associated route, load the route object now // and save it on the object. That way we avoid a select N+1 problem later. - if ($menu_link->route_name) { - $routes[$menu_link->id()] = $menu_link->route_name; + if ($record->route_name) { + $routes[$record->{$this->idKey}] = $record->route_name; } } + parent::attachLoad($queried_entities, $load_revision); + // Now mass-load any routes needed and associate them. if ($routes) { $route_objects = $this->routeProvider->getRoutesByNames($routes); foreach ($routes as $entity_id => $route) { // Not all stored routes will be valid on load. if (isset($route_objects[$route])) { - $menu_links[$entity_id]->setRouteObject($route_objects[$route]); + $queried_entities[$entity_id]->setRouteObject($route_objects[$route]); } } } + } + + /** + * {@inheritdoc} + */ + protected function mapFromStorageRecords(array $records, $load_revision = FALSE) { + $entities = parent::mapFromStorageRecords($records, $load_revision); + + foreach ($entities as &$entity) { + foreach (static::$routerItemFields as $router_field) { + $entity->offsetSet($router_field, $records[$entity->id()]->{$router_field}); + } + } - parent::attachLoad($menu_links, $load_revision); + return $entities; } /** * 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. @@ -152,13 +150,19 @@ 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()); } if ($entity->isNew()) { - $entity->mlid = $this->database->insert($this->entityInfo['base_table'])->fields(array('menu_name' => 'tools'))->execute(); + $entity->mlid->value = $this->database->insert($this->entityInfo['base_table'])->fields(array('menu_name' => 'tools'))->execute(); $entity->enforceIsNew(); } @@ -174,19 +178,45 @@ 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->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); @@ -227,6 +257,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() @@ -237,16 +271,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; } /** @@ -270,13 +300,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) { @@ -286,7 +316,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(); } } @@ -299,20 +329,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; } /** @@ -321,14 +351,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()); } @@ -336,7 +366,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 @@ -349,10 +379,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(); @@ -376,7 +406,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, '/')); @@ -387,7 +417,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(); @@ -400,4 +430,176 @@ public function getParentFromHierarchy(EntityInterface $entity) { return $parent; } + /** + * {@inheritdoc} + */ + public function baseFieldDefinitions() { + $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', + ); + $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', + ); + $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', + ); + $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', + ); + $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', + ); + $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', + ); + $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', + ); + $properties['weight'] = array( + 'label' => t('Weight'), + 'description' => t('Link weight among links in the same menu at the same depth.'), + 'type' => 'integer_field', + ); + $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', + ); + // @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', + ); + + // @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/Plugin/Core/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php index 7f227f8..245b9a4 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php @@ -7,17 +7,16 @@ namespace Drupal\menu_link\Plugin\Core\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\Language\Language; +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. @@ -48,14 +47,14 @@ * } * ) */ -class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { +class MenuLink extends EntityNG implements \ArrayAccess, MenuLinkInterface { /** * The link's menu name. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $menu_name = 'tools'; + public $menu_name; /** * The link's bundle. @@ -67,21 +66,21 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { /** * The menu link ID. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $mlid; /** * The menu link UUID. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $uuid; /** * The parent link ID. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $plid; @@ -96,89 +95,89 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { * For links corresponding to a Drupal path (external = 0), this connects the * link to a {menu_router}.path for joins. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $router_path; /** * The entity label. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $link_title = ''; + 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 + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $options = array(); + public $options; /** * The name of the module that generated this link. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $module = 'menu'; + public $module; /** * A flag for whether the link should be rendered in menus. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $hidden = 0; + public $hidden; /** * A flag to indicate if the link points to a full URL starting with a * protocol, like http:// (1 = external, 0 = internal). * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $external; /** * Flag indicating whether any links have this link as a parent. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $has_children = 0; + public $has_children; /** * 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 + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $expanded = 0; + public $expanded; /** * Link weight among links in the same menu at the same depth. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $weight = 0; + public $weight; /** * The depth relative to the top level. A link with plid == 0 will have * depth == 1. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $depth; /** * A flag to indicate that the user has manually created or edited the link. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $customized = 0; + public $customized; /** * The first entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface * * @todo Investigate whether the p1, p2, .. pX properties can be moved to a * single array property. @@ -188,74 +187,93 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { /** * The second entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p2; /** * The third entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p3; /** * The fourth entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p4; /** * The fifth entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p5; /** * The sixth entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p6; /** * The seventh entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p7; /** * The eighth entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p8; /** * The ninth entity ID in the materialized path. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $p9; /** * The menu link modification timestamp. * - * @var int + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $updated = 0; + public $updated; /** * The name of the route associated with this menu link, if any. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $route_name; /** + * Default values for the menu link. + * + * @var array + */ + protected $values = array( + 'langcode' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => Language::LANGCODE_NOT_SPECIFIED))), + 'menu_name' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 'tools'))), + 'link_title' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => ''))), + 'options' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => array()))), + 'module' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 'menu'))), + 'hidden' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + 'has_children' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + 'expanded' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + 'weight' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + 'customized' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + 'updated' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), + ); + + /** * The route object associated with this menu link, if any. * * @var \Symfony\Component\Routing\Route @@ -263,10 +281,35 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { protected $routeObject; /** - * Overrides Entity::id(). + * Crap coming from the old routing system. + * + * @todo Remove when we rip out the old routing system. + * + * @var array + */ + protected $oldRouterItem = array(); + + /** + * Properties of the old routing system. + * + * @todo Remove when we rip out the old routing system. + * + * @var array + */ + 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', + ); + + /** + * {@inheritdoc} */ public function id() { - return $this->mlid; + return $this->get('mlid')->value; } /** @@ -277,11 +320,46 @@ public function bundle() { } /** + * {@inheritdoc} + */ + protected function init() { + parent::init(); + // We unset all defined properties, so magic getters apply. + unset($this->menu_name); + unset($this->mlid); + unset($this->uuid); + unset($this->plid); + unset($this->link_path); + unset($this->router_path); + unset($this->link_title); + unset($this->options); + unset($this->module); + unset($this->hidden); + unset($this->external); + unset($this->has_children); + unset($this->expanded); + unset($this->weight); + unset($this->depth); + unset($this->customized); + unset($this->p1); + unset($this->p2); + unset($this->p3); + unset($this->p4); + unset($this->p5); + unset($this->p6); + unset($this->p7); + unset($this->p8); + unset($this->p9); + unset($this->updated); + unset($this->route_name); + } + + /** * Overrides Entity::createDuplicate(). */ public function createDuplicate() { $duplicate = parent::createDuplicate(); - $duplicate->plid = NULL; + $duplicate->get('plid')->offsetGet(0)->set('value', NULL); return $duplicate; } @@ -289,12 +367,12 @@ public function createDuplicate() { * {@inheritdoc} */ public function getRoute() { - if (!$this->route_name) { + if (!$this->route_name->value) { 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->route_name->value); } return $this->routeObject; } @@ -316,11 +394,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->router_path->value]; $new_link = self::buildFromRouterItem($router_item); // Merge existing menu link's ID and 'has_children' property. foreach (array('mlid', 'has_children') as $key) { - $new_link->{$key} = $this->{$key}; + $new_link->{$key}->value = $this->{$key}->value; } $new_link->save(); return $new_link; @@ -351,31 +429,70 @@ 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); +// return isset($this->{$offset}); } /** - * 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 == 'localized_options' || $offset == 'options') { + return $this->{$offset}[0]; + } + 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 ($this->getPropertyDefinition($offset)) { + $this->{$offset}->value = $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'; + } } /** @@ -389,10 +506,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->has_children->value) { + $children = $storage_controller->loadByProperties(array('plid' => $entity->plid->target_id)); foreach ($children as $child) { - $child->plid = $entity->plid; + $child->plid->target_id = $entity->plid->target_id; $storage_controller->save($child); } } @@ -411,8 +528,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->menu_name->value])) { + $affected_menus[$entity->menu_name->value] = $entity->menu_name->value; } } @@ -428,63 +545,64 @@ 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->link_path->value) || $this->link_path->value == '') ? 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->plid->target_id = $parent->id(); + $this->menu_name->value = $parent->menu_name->value; } // If no corresponding parent link was found, move the link to the top-level. else { - $this->plid = 0; + $this->plid->target_id = 0; } // Directly fill parents for top-level links. - if ($this->plid == 0) { - $this->p1 = $this->id(); + if ($this->plid->target_id == 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->has_children->value && $this->original) { $limit = MENU_MAX_DEPTH - $storage_controller->findChildrenRelativeDepth($this->original) - 1; } else { $limit = MENU_MAX_DEPTH - 1; } - if ($parent->depth > $limit) { + if ($parent->depth->value > $limit) { return FALSE; } - $this->depth = $parent->depth + 1; + $this->depth->value = $parent->depth->value + 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->plid->target_id != $this->original->plid->target_id || $this->menu_name->value != $this->original->menu_name->value)) { $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 (empty($this->router_path->value) || empty($this->original) || (isset($this->original) && $this->original->link_path->value != $this->link_path->value)) { + if ($this->external->value) { + $this->router_path->value = ''; } 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->link_path->value, MENU_MAX_PARTS); + $this->router_path->value = _menu_find_router_path($this->link_path->value); } } // Find the route_name. - if (!isset($this->route_name)) { - $this->route_name = $this::findRouteName($this->link_path); + if (!isset($this->route_name->value)) { + $this->route_name->value = $this::findRouteName($this->link_path->value); } } @@ -495,9 +613,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->menu_name->value); + if (isset($this->original) && $this->menu_name->value != $this->original->menu_name->value) { + menu_cache_clear($this->original->menu_name->value); } // Now clear the cache. @@ -528,41 +646,41 @@ public static function findRouteName($link_path) { */ public function setParents(EntityInterface $parent) { $i = 1; - while ($i < $this->depth) { + while ($i < $this->depth->value) { $p = 'p' . $i++; - $this->{$p} = $parent->{$p}; + $this->{$p}->value = $parent->{$p}->value; } $p = 'p' . $i++; // The parent (p1 - p9) corresponding to the depth always equals the mlid. - $this->{$p} = $this->id(); + $this->{$p}->value = $this->id(); while ($i <= MENU_MAX_DEPTH) { $p = 'p' . $i++; - $this->{$p} = 0; + $this->{$p}->value = 0; } } /** * {@inheritdoc} */ - public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()) { + public function findParent(MenuLinkStorageControllerInterface $storage_controller, array $parent_candidates = array()) { $parent = FALSE; // This item is explicitely top-level, skip the rest of the parenting. - if (isset($this->plid) && empty($this->plid)) { + if (isset($this->plid->target_id) && empty($this->plid->target_id)) { return $parent; } // If we have a parent link ID, try to use that. $candidates = array(); - if (isset($this->plid)) { - $candidates[] = $this->plid; + if (isset($this->plid->target_id)) { + $candidates[] = $this->plid->target_id; } // 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--) { + if (!empty($this->depth->value) && $this->depth->value > 1) { + for ($depth = $this->depth->value - 1; $depth >= 1; $depth--) { $parent_property = "p$depth"; - $candidates[] = $this->$parent_property; + $candidates[] = $this->$parent_property->value; } } @@ -581,12 +699,11 @@ 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->module->value == 'system') { $parent = $storage_controller->getParentFromHierarchy($this); } return $parent; } - } diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index c22c97f..514f1d1 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -55,7 +55,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'; } }