Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 75 |
| SystemMenuBlock | |
0.00% |
0 / 1 |
|
0.00% |
0 / 9 |
132 | |
0.00% |
0 / 75 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| create | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 8 |
|||
| blockForm | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 29 |
|||
| processMenuLevelParents | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| blockSubmit | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| build | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 16 |
|||
| defaultConfiguration | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| getCacheTags | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| getCacheContexts | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\system\Plugin\Block\SystemMenuBlock. | |
| */ | |
| namespace Drupal\system\Plugin\Block; | |
| use Drupal\Core\Block\BlockBase; | |
| use Drupal\Core\Cache\Cache; | |
| use Drupal\Core\Form\FormStateInterface; | |
| use Drupal\Core\Menu\MenuActiveTrailInterface; | |
| use Drupal\Core\Menu\MenuLinkTreeInterface; | |
| use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
| use Symfony\Component\DependencyInjection\ContainerInterface; | |
| /** | |
| * Provides a generic Menu block. | |
| * | |
| * @Block( | |
| * id = "system_menu_block", | |
| * admin_label = @Translation("Menu"), | |
| * category = @Translation("Menus"), | |
| * deriver = "Drupal\system\Plugin\Derivative\SystemMenuBlock" | |
| * ) | |
| */ | |
| class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterface { | |
| /** | |
| * The menu link tree service. | |
| * | |
| * @var \Drupal\Core\Menu\MenuLinkTreeInterface | |
| */ | |
| protected $menuTree; | |
| /** | |
| * The active menu trail service. | |
| * | |
| * @var \Drupal\Core\Menu\MenuActiveTrailInterface | |
| */ | |
| protected $menuActiveTrail; | |
| /** | |
| * Constructs a new SystemMenuBlock. | |
| * | |
| * @param array $configuration | |
| * A configuration array containing information about the plugin instance. | |
| * @param string $plugin_id | |
| * The plugin_id for the plugin instance. | |
| * @param array $plugin_definition | |
| * The plugin implementation definition. | |
| * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree | |
| * The menu tree service. | |
| * @param \Drupal\Core\Menu\MenuActiveTrailInterface $menu_active_trail | |
| * The active menu trail service. | |
| */ | |
| public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail) { | |
| parent::__construct($configuration, $plugin_id, $plugin_definition); | |
| $this->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'] = array( | |
| '#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'] = array( | |
| '#type' => 'select', | |
| '#title' => $this->t('Initial menu level'), | |
| '#default_value' => $config['level'], | |
| '#options' => $options, | |
| '#description' => $this->t('The menu will only be visible if the menu item for the current page is at or below the selected starting level. Select level 1 to always keep this menu visible.'), | |
| '#required' => TRUE, | |
| ); | |
| $options[0] = $this->t('Unlimited'); | |
| $form['menu_levels']['depth'] = array( | |
| '#type' => 'select', | |
| '#title' => $this->t('Maximum number of menu levels to display'), | |
| '#default_value' => $config['depth'], | |
| '#options' => $options, | |
| '#description' => $this->t('The maximum number of menu levels to show, starting from the initial menu level. For example: with an initial level 2 and a maximum number of 3, menu levels 2, 3 and 4 can be displayed.'), | |
| '#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 = array( | |
| array('callable' => 'menu.default_tree_manipulators:checkAccess'), | |
| array('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]); | |
| } | |
| } |