class FootermapBlock in footermap: a footer site map 8
Provide a footer-based site map block based on menu items.
Plugin annotation
@Block(
id = "footermap_block",
admin_label = @Translation("Footermap"),
category = @Translation("Sitemap"),
module = "footermap"
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Component\Plugin\ContextAwarePluginBase implements ContextAwarePluginInterface
- class \Drupal\Core\Plugin\ContextAwarePluginBase implements CacheableDependencyInterface, ContextAwarePluginInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Core\Block\BlockBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface uses BlockPluginTrait, ContextAwarePluginAssignmentTrait
- class \Drupal\footermap\Plugin\Block\FootermapBlock implements ContainerFactoryPluginInterface, FootermapInterface
- class \Drupal\Core\Block\BlockBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface uses BlockPluginTrait, ContextAwarePluginAssignmentTrait
- class \Drupal\Core\Plugin\ContextAwarePluginBase implements CacheableDependencyInterface, ContextAwarePluginInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Component\Plugin\ContextAwarePluginBase implements ContextAwarePluginInterface
Expanded class hierarchy of FootermapBlock
1 file declares its use of FootermapBlock
- FootermapBlockTest.php in tests/
src/ Unit/ Plugin/ Block/ FootermapBlockTest.php
File
- src/
Plugin/ Block/ FootermapBlock.php, line 29
Namespace
Drupal\footermap\Plugin\BlockView source
class FootermapBlock extends BlockBase implements ContainerFactoryPluginInterface, FootermapInterface {
/**
* The footermap build render array.
*
* @var array
*/
protected $mapref;
/**
* The menu.link_tree service.
*
* @var \Drupal\Core\Menu\MenuLinkTreeInterface
*/
protected $menuTree;
/**
* The entity_type.manager service.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The entity.repository service.
*
* @var \Drupal\Core\Entity\EntityRepositoryInterface
*/
protected $entityRepository;
/**
* The plugin.manager.menu_link service.
*
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
*/
protected $menuLinkManager;
/**
* The footermap logger channel.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;
/**
* Construct with dependencies injected.
*
* @param array $configuration
* The configuration array.
* @param string $plugin_id
* The block plugin id.
* @param mixed $plugin_definition
* The block plugin definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
* The entity_type.manager service.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
* The entity.repository service.
* @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree
* The menu.link_tree service.
* @param \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager
* The plugin.manager.menu_link service.
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
* The Logger Channel Factory service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_manager, EntityRepositoryInterface $entityRepository, MenuLinkTreeInterface $menu_tree, MenuLinkManagerInterface $menu_link_manager, LoggerChannelFactoryInterface $logger_factory) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->entityRepository = $entityRepository;
$this->menuTree = $menu_tree;
$this->menuLinkManager = $menu_link_manager;
$this->logger = $logger_factory
->get('footermap');
}
/**
* {@inheritdoc}
*/
public function access(AccountInterface $account, $return_as_object = FALSE) {
if ($return_as_object) {
return AccessResultNeutral::allowed();
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('entity_type.manager'), $container
->get('entity.repository'), $container
->get('menu.link_tree'), $container
->get('plugin.manager.menu.link'), $container
->get('logger.factory'));
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
$settings = parent::defaultConfiguration();
$settings['footermap_recurse_limit'] = 0;
$settings['footermap_display_heading'] = 1;
$settings['footermap_avail_menus'] = [];
$settings['footermap_top_menu'] = '';
return $settings;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return [
'languages',
];
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {
$form['footermap_recurse_limit'] = [
'#type' => 'number',
'#title' => $this
->t('Recurse Limit'),
'#description' => $this
->t('Limit the depth of menu items to display. The default is 0, unlimited. This is useful if you have a deep hierarchy of child menu items that you do not want to display in the footermap.'),
'#size' => 3,
'#max_length' => 3,
'#min' => 0,
'#default_value' => $this->configuration['footermap_recurse_limit'],
];
$form['footermap_display_heading'] = [
'#type' => 'radios',
'#title' => $this
->t('Enable Menu Heading'),
'#description' => $this
->t('This will enable the menu-name label (e.g. Navigation, Footer) to be displayed as the heading above each menu column. This is nice if you have your menus setup in distinct blocks or controlled via the recurse-limit property above.'),
'#options' => [
$this
->t('No'),
$this
->t('Yes'),
],
'#default_value' => $this->configuration['footermap_display_heading'],
];
$form['footermap_top_menu'] = [
'#type' => 'textfield',
'#title' => $this
->t('Top-level Menu'),
'#description' => $this
->t('Set the plugin ID to use for the top-level menu. This may be useful if you want a footer map of menu links deep within a menu instead of pulling from each menu. The default is to use from avail-menus below.'),
'#default_value' => $this->configuration['footermap_top_menu'],
];
$form['footermap_avail_menus'] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Available menus'),
'#description' => $this
->t('Select which top-level menus to include in this footer site map.'),
'#options' => $this
->getMenus(),
'#default_value' => $this->configuration['footermap_avail_menus'],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration = $form_state
->getValues();
}
/**
* {@inheritdoc}
*/
public function build() {
$build = [
'#theme' => 'footermap',
'#title' => $this->configuration['label_display'] ? $this->configuration['label'] : '',
'#block' => $this,
'#attributes' => [
'class' => [
'footermap',
'footermap--' . $this
->getPluginId(),
],
],
'#attached' => [
'library' => [
'footermap/footermap',
],
],
];
try {
$build['#footermap'] = $this
->buildMap();
} catch (\Exception $e) {
$this->logger
->error($e
->getMessage());
}
return $build;
}
/**
* {@inheritdoc}
*/
public function buildMap() {
$this->mapref = [];
// Assemble all of the configuration necessary to build footer map.
$col_index = 1;
$depth = $this->configuration['footermap_recurse_limit'] == 0 ? NULL : $this->configuration['footermap_recurse_limit'];
$top_menu_plugin_id = $this->configuration['footermap_top_menu'] == '' ? FALSE : $this->configuration['footermap_top_menu'];
$menus = $this
->getMenus($top_menu_plugin_id);
$parameters = new MenuTreeParameters();
// Set the maximum depth if not unlimited.
if ($this->configuration['footermap_recurse_limit']) {
$parameters
->setMaxDepth($depth);
}
$parameters
->onlyEnabledLinks();
$parameters
->excludeRoot();
// Set root if top menu plugin id set.
if ($top_menu_plugin_id && !empty($menus)) {
$parameters
->setRoot($top_menu_plugin_id);
}
// Menu link manipulator using anonymous session.
$manipulators = [
[
'callable' => 'footermap.anonymous_tree_manipulator:checkAccess',
],
];
foreach ($menus as $menu_name => $menu) {
// Loop through every menu.
if (isset($this->configuration['footermap_avail_menus'][$menu_name]) && $this->configuration['footermap_avail_menus'][$menu_name] === $menu_name) {
// Only build site map for available menus.
$menu_name_class = str_replace('_', '-', $menu_name);
$tree = $this->menuTree
->load($menu_name, $parameters);
$tree = $this->menuTree
->transform($tree, $manipulators);
if (!empty($tree)) {
$this->mapref[$menu_name] = [
'#theme' => 'footermap_header',
// check_plain() during render.
'#title' => $menu,
'#title_display' => $this->configuration['footermap_display_heading'] ? 'visible' : 'hidden',
'#menu_name' => $menu_name,
'#attributes' => [
'class' => [
'footermap-header',
'footermap-header--' . $menu_name_class,
],
],
];
$this
->buildMenu($tree, $this->mapref[$menu_name]);
}
$col_index++;
}
}
return $this->mapref;
}
/**
* {@inheritdoc}
*/
public function buildMenu(array &$tree, array &$mapref) {
foreach ($tree as $key => $item) {
/** @var \Drupal\Core\Menu\MenuLinkInterface $link */
$link = $item->link;
$link_title = $link
->getTitle();
if ($link
->isEnabled() && !empty($link_title) && !$link instanceof InaccessibleMenuLink) {
// Mapref reference becomes child.
if (isset($mapref['#theme']) && $mapref['#theme'] == 'footermap_header') {
$child =& $mapref['#items'];
}
else {
$child =& $mapref;
}
// Get the menu link entity language, but necessary to load menu link
// content entity which is kind of expensive.
if (strpos($link
->getPluginId(), 'menu_link_content') === 0) {
list(, $uuid) = explode(':', $link
->getPluginId(), 2);
$entity = $this->entityRepository
->loadEntityByUuid('menu_link_content', $uuid);
}
$child['menu-' . $key] = [
'#theme' => 'footermap_item',
'#title' => $link
->getTitle(),
'#url' => $link
->getUrlObject(),
'#attributes' => [
'class' => [
'footermap-item',
'footermap-item--depth-' . $item->depth,
],
],
'#level' => $item->depth,
'#weight' => $link
->getWeight(),
];
}
if ($item->hasChildren) {
$child['menu-' . $key]['#children'] = [];
$child['menu-' . $key]['#attributes']['class'][] = 'footermap-item--haschildren';
$this
->buildMenu($item->subtree, $child['menu-' . $key]['#children']);
}
}
}
/**
* Get the menus from config storage.
*
* @param string $plugin_id
* (Optional) A plugin id for a menu link to use as the top of the menu
* tree hierarchy.
*
* @return array
* An associative array of menus keyed by menu id (string) and menu label.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getMenus($plugin_id = NULL) {
$options = [];
// Fetch the menu link by plugin id instead and return that as the menu,
// but use the menu name as the key and the menu link title as the value.
if (isset($plugin_id) && $plugin_id) {
$item = $this->menuLinkManager
->getDefinition($plugin_id, FALSE);
if (!$item) {
return $options;
}
return [
$item['menu_name'] => $item['title'],
];
}
$controller = $this->entityManager
->getStorage('menu');
if ($menus = $controller
->loadMultiple()) {
foreach ($menus as $menu_name => $menu) {
$options[$menu_name] = $menu
->label();
}
asort($options);
}
return $options;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BlockPluginInterface:: |
constant | Indicates the block label (title) should be displayed to end users. | ||
BlockPluginTrait:: |
protected | property | The transliteration service. | |
BlockPluginTrait:: |
protected | function | Returns generic default configuration for block plugins. | |
BlockPluginTrait:: |
protected | function | Indicates whether the block should be shown. | 16 |
BlockPluginTrait:: |
public | function | 3 | |
BlockPluginTrait:: |
public | function | Creates a generic configuration form for all block types. Individual block plugins can add elements to this form by overriding BlockBase::blockForm(). Most block plugins should not override this method unless they need to alter the generic form elements. | 2 |
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | 1 | |
BlockPluginTrait:: |
public | function | 1 | |
BlockPluginTrait:: |
public | function | 3 | |
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | Sets the transliteration service. | |
BlockPluginTrait:: |
public | function | Most block plugins should not override this method. To add submission handling for a specific block type, override BlockBase::blockSubmit(). | |
BlockPluginTrait:: |
protected | function | Wraps the transliteration service. | |
BlockPluginTrait:: |
public | function | Most block plugins should not override this method. To add validation for a specific block type, override BlockBase::blockValidate(). | 1 |
ContextAwarePluginAssignmentTrait:: |
protected | function | Builds a form element for assigning a context to a given slot. | |
ContextAwarePluginAssignmentTrait:: |
protected | function | Wraps the context handler. | |
ContextAwarePluginBase:: |
protected | property | The data objects representing the context of this plugin. | |
ContextAwarePluginBase:: |
private | property | Data objects representing the contexts passed in the plugin configuration. | |
ContextAwarePluginBase:: |
protected | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
The maximum age for which this object may be cached. Overrides CacheableDependencyInterface:: |
7 |
ContextAwarePluginBase:: |
public | function |
The cache tags associated with this object. Overrides CacheableDependencyInterface:: |
4 |
ContextAwarePluginBase:: |
public | function |
This code is identical to the Component in order to pick up a different
Context class. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Gets a mapping of the expected assignment names to their context names. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the value for a defined context. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the values for all defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Set a context on this plugin. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Sets a mapping of the expected assignment names to their context names. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Sets the value for a defined context. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Validates the set values for the defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function | Implements magic __get() method. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FootermapBlock:: |
protected | property | The entity_type.manager service. | |
FootermapBlock:: |
protected | property | The entity.repository service. | |
FootermapBlock:: |
protected | property | The footermap logger channel. | |
FootermapBlock:: |
protected | property | The footermap build render array. | |
FootermapBlock:: |
protected | property | The plugin.manager.menu_link service. | |
FootermapBlock:: |
protected | property | The menu.link_tree service. | |
FootermapBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FootermapBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FootermapBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FootermapBlock:: |
public | function |
Builds and returns the renderable array for this block plugin. Overrides BlockPluginInterface:: |
|
FootermapBlock:: |
public | function |
Build content for footer site map. Overrides FootermapInterface:: |
|
FootermapBlock:: |
public | function |
Recursively build footer site map. Overrides FootermapInterface:: |
|
FootermapBlock:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
FootermapBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FootermapBlock:: |
public | function |
The cache contexts associated with this object. Overrides ContextAwarePluginBase:: |
|
FootermapBlock:: |
protected | function | Get the menus from config storage. | |
FootermapBlock:: |
public | function |
Construct with dependencies injected. Overrides BlockPluginTrait:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginWithFormsTrait:: |
public | function | ||
PluginWithFormsTrait:: |
public | function | ||
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TypedDataTrait:: |
protected | property | The typed data manager used for creating the data types. | |
TypedDataTrait:: |
public | function | Gets the typed data manager. | 2 |
TypedDataTrait:: |
public | function | Sets the typed data manager. | 2 |