X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Fsystem%2Fsrc%2FPlugin%2FBlock%2FSystemMenuBlock.php;fp=web%2Fcore%2Fmodules%2Fsystem%2Fsrc%2FPlugin%2FBlock%2FSystemMenuBlock.php;h=c142c86c8ee83116a6dca9a36d3360ce69591e3a;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hp=0000000000000000000000000000000000000000;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad;p=yaffs-website diff --git a/web/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/web/core/modules/system/src/Plugin/Block/SystemMenuBlock.php new file mode 100644 index 000000000..c142c86c8 --- /dev/null +++ b/web/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -0,0 +1,196 @@ +menuTree = $menu_tree; + $this->menuActiveTrail = $menu_active_trail; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('menu.link_tree'), + $container->get('menu.active_trail') + ); + } + + /** + * {@inheritdoc} + */ + public function blockForm($form, FormStateInterface $form_state) { + $config = $this->configuration; + + $defaults = $this->defaultConfiguration(); + $form['menu_levels'] = [ + '#type' => 'details', + '#title' => $this->t('Menu levels'), + // Open if not set to defaults. + '#open' => $defaults['level'] !== $config['level'] || $defaults['depth'] !== $config['depth'], + '#process' => [[get_class(), 'processMenuLevelParents']], + ]; + + $options = range(0, $this->menuTree->maxDepth()); + unset($options[0]); + + $form['menu_levels']['level'] = [ + '#type' => 'select', + '#title' => $this->t('Initial visibility level'), + '#default_value' => $config['level'], + '#options' => $options, + '#description' => $this->t('The menu is only visible if the menu item for the current page is at this level or below it. Use level 1 to always display this menu.'), + '#required' => TRUE, + ]; + + $options[0] = $this->t('Unlimited'); + + $form['menu_levels']['depth'] = [ + '#type' => 'select', + '#title' => $this->t('Number of levels to display'), + '#default_value' => $config['depth'], + '#options' => $options, + '#description' => $this->t('This maximum number includes the initial level.'), + '#required' => TRUE, + ]; + + return $form; + } + + /** + * Form API callback: Processes the menu_levels field element. + * + * Adjusts the #parents of menu_levels to save its children at the top level. + */ + public static function processMenuLevelParents(&$element, FormStateInterface $form_state, &$complete_form) { + array_pop($element['#parents']); + return $element; + } + + /** + * {@inheritdoc} + */ + public function blockSubmit($form, FormStateInterface $form_state) { + $this->configuration['level'] = $form_state->getValue('level'); + $this->configuration['depth'] = $form_state->getValue('depth'); + } + + /** + * {@inheritdoc} + */ + public function build() { + $menu_name = $this->getDerivativeId(); + $parameters = $this->menuTree->getCurrentRouteMenuTreeParameters($menu_name); + + // Adjust the menu tree parameters based on the block's configuration. + $level = $this->configuration['level']; + $depth = $this->configuration['depth']; + $parameters->setMinDepth($level); + // When the depth is configured to zero, there is no depth limit. When depth + // is non-zero, it indicates the number of levels that must be displayed. + // Hence this is a relative depth that we must convert to an actual + // (absolute) depth, that may never exceed the maximum depth. + if ($depth > 0) { + $parameters->setMaxDepth(min($level + $depth - 1, $this->menuTree->maxDepth())); + } + + $tree = $this->menuTree->load($menu_name, $parameters); + $manipulators = [ + ['callable' => 'menu.default_tree_manipulators:checkAccess'], + ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'], + ]; + $tree = $this->menuTree->transform($tree, $manipulators); + return $this->menuTree->build($tree); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'level' => 1, + 'depth' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + // Even when the menu block renders to the empty string for a user, we want + // the cache tag for this menu to be set: whenever the menu is changed, this + // menu block must also be re-rendered for that user, because maybe a menu + // link that is accessible for that user has been added. + $cache_tags = parent::getCacheTags(); + $cache_tags[] = 'config:system.menu.' . $this->getDerivativeId(); + return $cache_tags; + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + // ::build() uses MenuLinkTreeInterface::getCurrentRouteMenuTreeParameters() + // to generate menu tree parameters, and those take the active menu trail + // into account. Therefore, we must vary the rendered menu by the active + // trail of the rendered menu. + // Additional cache contexts, e.g. those that determine link text or + // accessibility of a menu, will be bubbled automatically. + $menu_name = $this->getDerivativeId(); + return Cache::mergeContexts(parent::getCacheContexts(), ['route.menu_active_trails:' . $menu_name]); + } + +}