/** * Form constructor to edit an entire menu tree at once. * * Shows for one menu the menu links accessible to the current user and * relevant operations. * * This form constructor can be integrated as a section into another form. It * relies on the following keys in $form_state: * - menu: A menu entity. * - menu_overview_form_parents: An array containing the parent keys to this * form. * Forms integrating this section should call menu_overview_form_submit() from * their form submit handler. */ protected function buildOverviewForm(array &$form, array &$form_state) { // Ensure that menu_overview_form_submit() knows the parents of this form // section. $form['#tree'] = TRUE; $form['#theme'] = 'menu_overview_form'; $form_state += array('menu_overview_form_parents' => array()); $form['#attached']['css'] = array(drupal_get_path('module', 'menu') . '/css/menu.admin.css'); $links = array(); $query = $this->entityQueryFactory->get('menu_link')->condition('menu_name', $this->entity->id()); for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) { $query->sort('p' . $i, 'ASC'); } $result = $query->execute(); if (!empty($result)) { $links = $this->menuLinkStorage->loadMultiple($result); } $delta = max(count($links), 50); // We indicate that a menu administrator is running the menu access check. $this->getRequest()->attributes->set('_menu_admin', TRUE); $tree = $this->menuTree->buildTreeData($links); $this->getRequest()->attributes->set('_menu_admin', FALSE); $form = array_merge($form, $this->buildOverviewTreeForm($tree, $delta)); $form['#empty_text'] = t('There are no menu links yet. <a href="@link">Add link</a>.', array('@link' => url('admin/structure/menu/manage/' . $this->entity->id() . '/add'))); return $form; }
/** * Builds a menu tree. * * This function may be used build the data for a menu tree only, for example * to further massage the data manually before further processing happens. * MenuTree::checkAccess() needs to be invoked afterwards. * * @param string $menu_name * The name of the menu. * @param array $parameters * The parameters passed into static::buildTree() * * @see static::buildTree() */ protected function doBuildTree($menu_name, array $parameters = array()) { $language_interface = $this->languageManager->getCurrentLanguage(); // Build the cache id; sort parents to prevent duplicate storage and remove // default parameter values. if (isset($parameters['expanded'])) { sort($parameters['expanded']); } $tree_cid = 'links:' . $menu_name . ':tree-data:' . $language_interface->id . ':' . hash('sha256', serialize($parameters)); // If we do not have this tree in the static cache, check {cache_menu}. if (!isset($this->menuTree[$tree_cid])) { $cache = $this->cache->get($tree_cid); if ($cache && $cache->data) { $this->menuTree[$tree_cid] = $cache->data; } } if (!isset($this->menuTree[$tree_cid])) { $query = $this->queryFactory->get('menu_link'); for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) { $query->sort('p' . $i, 'ASC'); } $query->condition('menu_name', $menu_name); if (!empty($parameters['expanded'])) { $query->condition('plid', $parameters['expanded'], 'IN'); } elseif (!empty($parameters['only_active_trail'])) { $query->condition('mlid', $parameters['active_trail'], 'IN'); } $min_depth = isset($parameters['min_depth']) ? $parameters['min_depth'] : 1; if ($min_depth != 1) { $query->condition('depth', $min_depth, '>='); } if (isset($parameters['max_depth'])) { $query->condition('depth', $parameters['max_depth'], '<='); } // Add custom query conditions, if any were passed. if (isset($parameters['conditions'])) { foreach ($parameters['conditions'] as $column => $value) { $query->condition($column, $value); } } // Build an ordered array of links using the query result object. $links = array(); if ($result = $query->execute()) { $links = $this->menuLinkStorage->loadMultiple($result); } $active_trail = isset($parameters['active_trail']) ? $parameters['active_trail'] : array(); $tree = $this->doBuildTreeData($links, $active_trail, $min_depth); // Cache the data, if it is not already in the cache. $this->cache->set($tree_cid, $tree, Cache::PERMANENT, array('menu' => $menu_name)); $this->menuTree[$tree_cid] = $tree; } return $this->menuTree[$tree_cid]; }