From 616d6b26b67edd375ca3a2593113e2cc71348dcb Mon Sep 17 00:00:00 2001 From: William Hearn Date: Sun, 29 Oct 2017 18:19:14 -0400 Subject: [PATCH] Issue #2919579: Patch Menu Block with various upstream --- config/schema/menu_block.schema.yml | 3 + src/Plugin/Block/MenuBlock.php | 195 ++++++++++++++++++++++++++++++++---- 2 files changed, 180 insertions(+), 18 deletions(-) diff --git a/config/schema/menu_block.schema.yml b/config/schema/menu_block.schema.yml index ad08127..4aacad7 100644 --- a/config/schema/menu_block.schema.yml +++ b/config/schema/menu_block.schema.yml @@ -14,6 +14,9 @@ block.settings.menu_block:*: parent: type: string label: 'Parent menu link' + render_parent: + type: boolean + label: 'Render parent menu link' suggestion: type: string label: 'Theme suggestion' diff --git a/src/Plugin/Block/MenuBlock.php b/src/Plugin/Block/MenuBlock.php index ca63dae..27f1940 100644 --- a/src/Plugin/Block/MenuBlock.php +++ b/src/Plugin/Block/MenuBlock.php @@ -41,17 +41,90 @@ class MenuBlock extends SystemMenuBlock { '#description' => $this->t('All menu links that have children will "Show as expanded".'), ]; + $form['advanced']['expand_only_active_trails'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Expand only active tree'), + '#default_value' => $config['expand_only_active_trails'], + '#description' => $this->t('All menu links that are in active trails will "Show as expanded".'), + '#states' => [ + 'visible' => [ + ':input[name="settings[expand]"]' => ['checked' => TRUE], + ] + ] + ]; + $menu_name = $this->getDerivativeId(); $menus = Menu::loadMultiple(array($menu_name)); $menus[$menu_name] = $menus[$menu_name]->label(); /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */ $menu_parent_selector = \Drupal::service('menu.parent_form_selector'); - $form['advanced']['parent'] = $menu_parent_selector->parentSelectElement($config['parent'], '', $menus); + if (strpos($config['parent'], 'active_trail') === FALSE) { + $form['advanced']['parent'] = $menu_parent_selector->parentSelectElement($config['parent'], '', $menus); + } + else { + $form['advanced']['parent'] = [ + '#type' => 'select', + '#options' => $menu_parent_selector->getParentSelectOptions('', $menus), + '#default_value' => $config['parent'], + ]; + } + $form['advanced']['parent']['#options'] += [ + $menu_name . ':active_trail' => $this->t('')->render(), + $menu_name . ':active_trail_parent' => $this->t('')->render(), + $menu_name . ':active_trail_custom' => $this->t('')->render(), + ]; $form['advanced']['parent'] += [ '#title' => $this->t('Fixed parent item'), '#description' => $this->t('Alter the options in “Menu levels” to be relative to the fixed parent item. The block will only contain children of the selected menu link.'), + '#attributes' => [ + 'class' => ['active-trail'], + ], + ]; + + $form['advanced']['custom_level'] = [ + '#type' => 'select', + '#title' => $this->t('Set custom depth, set dynamically relative to the active trail.'), + '#default_value' => $config['custom_level'], + '#options' => range(0, 9), + '#states' => [ + 'visible' => [ + '.active-trail' => ['value' => $menu_name . ':active_trail_custom'], + ], + ], + ]; + + $form['advanced']['hide_children'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Hide children of parent in active trail?'), + '#default_value' => $config['hide_children'], + '#states' => [ + 'visible' => [ + '.active-trail' => [ + ['value' => $menu_name . ':active_trail'], + ['value' => $menu_name . ':active_trail_parent'], + ['value' => $menu_name . ':active_trail_custom'], + ], + ], + ], + ]; + + $form['advanced']['render_parent'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Render parent item'), + '#default_value' => $config['render_parent'], + '#description' => $this->t('Parent menu link will be rendered together with children items.'), + '#states' => array( + 'disabled' => array( + ':input[name="settings[level]"]' => array('!value' => '1'), + ), + 'checked' => array( + ':input[name="settings[level]"]' => array('value' => '1'), + ':input[name="settings[render_parent]"]' => array('checked' => TRUE), + + ), + ), ]; $form['style'] = [ @@ -106,9 +179,13 @@ class MenuBlock extends SystemMenuBlock { */ public function blockSubmit($form, FormStateInterface $form_state) { $this->configuration['level'] = $form_state->getValue('level'); + $this->configuration['custom_level'] = $form_state->getValue('custom_level'); + $this->configuration['hide_children'] = $form_state->getValue('hide_children'); $this->configuration['depth'] = $form_state->getValue('depth'); $this->configuration['expand'] = $form_state->getValue('expand'); + $this->configuration['expand_only_active_trails'] = $form_state->getValue('expand_only_active_trails'); $this->configuration['parent'] = $form_state->getValue('parent'); + $this->configuration['render_parent'] = $form_state->getValue('render_parent'); $this->configuration['follow'] = $form_state->getValue('follow'); $this->configuration['suggestion'] = $form_state->getValue('suggestion'); } @@ -122,13 +199,26 @@ class MenuBlock extends SystemMenuBlock { // Adjust the menu tree parameters based on the block's configuration. $level = $this->configuration['level']; + $custom_level = $this->configuration['custom_level']; $depth = $this->configuration['depth']; $expand = $this->configuration['expand']; + $expand_only_active_trails = $this->configuration['expand_only_active_trails']; $parent = $this->configuration['parent']; + $render_parent = $this->configuration['render_parent']; + $hide_children = $this->configuration['hide_children']; $follow = $this->configuration['follow']; + $trail_ids = $parameters->activeTrail; + $trail_ids = array_reverse(array_filter($trail_ids)); + + if ($parent == $menu_name . ':' . 'active_trail_custom') { + $level = $this->setActiveTrailLevel($level, $custom_level, $trail_ids); + } $max_depth = $level + $depth - 1; - $parameters->setMinDepth($level); + // Parent item will be included by default if mi depth is NULL. + if (!($render_parent && (int) $level === 1)) { + $parameters->setMinDepth($level); + } if ($follow) { $level += count($parameters->activeTrail) - 1; @@ -149,29 +239,50 @@ class MenuBlock extends SystemMenuBlock { $parameters->setMaxDepth(min($max_depth, $this->menuTree->maxDepth())); } // If expandedParents is empty, the whole menu tree is built. - if ($expand) { + if ($expand && !$expand_only_active_trails) { $parameters->expandedParents = array(); } // When a fixed parent item is set, root the menu tree at the given ID. if ($menuLinkID = str_replace($menu_name . ':', '', $parent)) { - $parameters->setRoot($menuLinkID); - - // If the starting level is 1, we always want the child links to appear, - // but the requested tree may be empty if the tree does not contain the - // active trail. - if ($level === 1 || $level === '1') { - // Check if the tree contains links. - $tree = $this->menuTree->load(NULL, $parameters); - if (empty($tree)) { - // Change the request to expand all children and limit the depth to - // the immediate children of the root. - $parameters->expandedParents = array(); - $parameters->setMinDepth(1); - $parameters->setMaxDepth(1); - // Re-load the tree. + if (strpos($menuLinkID, 'custom') == FALSE) { + // Active trail or Active trail parent option. + if (strpos($menuLinkID, 'active_trail') !== FALSE) { + // $trail_ids = $this->menuActiveTrail->getActiveTrailIds($menu_name); + // $trail_ids = array_reverse(array_filter($trail_ids)); + if ($menuLinkID == 'active_trail') { + $menuLinkID = end($trail_ids); + } + // Active trail parent. + else { + array_pop($trail_ids); + $menuLinkID = end($trail_ids); + } + } + if ($menuLinkID) { + $parameters->setRoot($menuLinkID); + } + + // If the starting level is 1, we always want the child links to appear, + // but the requested tree may be empty if the tree does not contain the + // active trail. + if ($level === 1 || $level === '1') { + // Check if the tree contains links. $tree = $this->menuTree->load(NULL, $parameters); + if (empty($tree)) { + // Change the request to expand all children and limit the depth to + // the immediate children of the root. + $parameters->expandedParents = array(); + // Parent item will be included by default if mi depth is NULL. + if (!$render_parent) { + $parameters->setMinDepth(1); + } + $parameters->setMaxDepth(1); + // Re-load the tree. + $tree = $this->menuTree->load(NULL, $parameters); + } } } + // end custom } // Load the tree if we haven't already. @@ -182,7 +293,13 @@ class MenuBlock extends SystemMenuBlock { array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); + $tree = $this->menuTree->transform($tree, $manipulators); + // Hide parent children if it is set in config. + if ($hide_children) { + $tree = $this->hideParentChildren($tree); + } + $build = $this->menuTree->build($tree); if (!empty($build['#theme'])) { @@ -197,14 +314,56 @@ class MenuBlock extends SystemMenuBlock { } /** + * Set the menu level relative to the active trail. + */ + public function setActiveTrailLevel($level, $custom_level, $trail_ids) { + $dynamic_level = count($trail_ids) - $custom_level; + if ($dynamic_level >= 1) { + $level = $dynamic_level; + } + + return $level; + } + + /** + * Hide the children of the active parent. + */ + public function hideParentChildren($tree) { + $not_active_items = []; + $unset = FALSE; + if (count($tree)) { + foreach ($tree as $id => $branch) { + if (!$branch->inActiveTrail) { + $not_active_items[$id] = $id; + } + if ($branch->inActiveTrail && $branch->hasChildren) { + $unset = TRUE; + } + } + } + + if ($unset) { + foreach ($not_active_items as $not_active_item) { + unset($tree[$not_active_item]); + } + } + + return $tree; + } + + /** * {@inheritdoc} */ public function defaultConfiguration() { return [ 'level' => 1, + 'custom_level' => 1, + 'hide_children' => 0, 'depth' => 0, 'expand' => 0, + 'expand_only_active_trails' => 0, 'parent' => $this->getDerivativeId() . ':', + 'render_parent' => 0, 'follow' => 0, 'suggestion' => strtr($this->getDerivativeId(), '-', '_'), ]; -- 2.5.4 (Apple Git-61)