View source
<?php
namespace Drupal\entity_submenu_block\Plugin\Block;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\InaccessibleMenuLink;
use Drupal\Core\Menu\MenuActiveTrailInterface;
use Drupal\system\Plugin\Block\SystemMenuBlock;
use Symfony\Component\DependencyInjection\ContainerInterface;
class EntitySubmenuBlock extends SystemMenuBlock {
protected $menuActiveTrail;
protected $entityTypeManager;
protected $entityDisplayRepository;
protected $entityTypes;
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$static = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$static
->setMenuActiveTrail($container
->get('menu.active_trail'));
$static
->setEntityTypeManager($container
->get('entity_type.manager'));
$static
->setEntityDisplayRepository($container
->get('entity_display.repository'));
$static
->setEntityTypes($container
->get('entity_type.manager')
->getDefinitions());
return $static;
}
public function setMenuActiveTrail(MenuActiveTrailInterface $menuActiveTrail) {
$this->menuActiveTrail = $menuActiveTrail;
}
public function setEntityTypeManager(EntityTypeManagerInterface $entityTypeManager) {
$this->entityTypeManager = $entityTypeManager;
}
public function setEntityDisplayRepository(EntityDisplayRepositoryInterface $entityDisplayRepository) {
$this->entityDisplayRepository = $entityDisplayRepository;
}
public function setEntityTypes(array $entityTypes) {
$this->entityTypes = $entityTypes;
}
public function blockForm($form, FormStateInterface $form_state) {
$form = parent::blockForm($form, $form_state);
unset($form['menu_levels']);
$config = $this
->getConfiguration();
$form['display_non_entities'] = [
'#title' => $this
->t('Display non-entities'),
'#type' => 'checkbox',
'#default_value' => $this
->getConfigurationValue($config, 'display_non_entities'),
];
$form['only_current_language'] = [
'#type' => 'checkbox',
'#title' => t('Only display entities with content in current language'),
'#default_value' => $this
->getConfigurationValue($config, 'only_current_language'),
];
$form['view_modes'] = [
'#title' => $this
->t('View modes'),
'#description' => $this
->t('View modes to be used when submenu items are displayed as content entities'),
'#type' => 'fieldgroup',
'#process' => [
[
get_class(),
'processFieldSets',
],
],
];
foreach ($this
->getEntityTypes() as $entity_type) {
$field = 'view_mode_' . $entity_type;
$view_modes = $this->entityDisplayRepository
->getViewModeOptions($entity_type);
$form['view_modes'][$field] = [
'#title' => $this->entityTypeManager
->getDefinition($entity_type)
->getLabel(),
'#type' => 'select',
'#options' => $view_modes,
'#default_value' => $this
->getConfigurationValue($config, $field, array_keys($view_modes)),
];
}
return $form;
}
public static function processFieldSets(&$element, FormStateInterface $form_state, &$complete_form) {
array_pop($element['#parents']);
return $element;
}
public function blockSubmit($form, FormStateInterface $form_state) {
foreach ([
'display_non_entities',
'only_current_language',
] as $field) {
$this
->setConfigurationValue($field, $form_state
->getValue($field));
}
foreach ($this
->getEntityTypes() as $entity_type) {
$field = 'view_mode_' . $entity_type;
$value = $form_state
->getValue($field);
$this
->setConfigurationValue($field, $value);
}
}
public function build() {
$build = [
'#theme' => 'entity_submenu',
'#menu_name' => NULL,
'#menu_items' => [],
];
$menu_name = $this
->getDerivativeId();
if (empty($this->menuActiveTrail
->getActiveLink($menu_name))) {
return $build;
}
$build['#menu_name'] = $menu_name;
$parameters = $this->menuTree
->getCurrentRouteMenuTreeParameters($menu_name);
$level = count($parameters->activeTrail);
$parameters
->setMinDepth($level);
$parameters
->setMaxDepth($level);
$parameters
->onlyEnabledLinks();
$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);
$config = $this
->getConfiguration();
$language = \Drupal::languageManager()
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
->getId();
foreach ($tree as $element) {
if ($element->link instanceof InaccessibleMenuLink) {
continue;
}
$url = $element->link
->getUrlObject();
if ($url
->isRouted()) {
$routeParams = $url
->getRouteParameters();
reset($routeParams);
$entity_type = key($routeParams);
if (in_array($entity_type, $this
->getEntityTypes())) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($routeParams[$entity_type]);
if ($this
->getConfigurationValue($config, 'only_current_language') == 1) {
$languages = $entity
->getTranslationLanguages();
if (!array_key_exists($language, $languages)) {
continue;
}
}
$build['#menu_items'][] = $this->entityTypeManager
->getViewBuilder($entity_type)
->view($entity, $config['view_mode_' . $entity_type]);
continue;
}
}
if ($this
->getConfigurationValue($config, 'display_non_entities') == 1) {
$build['#menu_items'][] = [
'#theme' => 'entity_submenu_item',
'#url' => $url,
'#title' => $element->link
->getTitle(),
];
}
}
return $build;
}
protected function getConfigurationValue(array $config, $field, array $valid = NULL) {
$value = NULL;
if (isset($config[$field]) && !empty($config[$field])) {
if (is_array($valid)) {
if (in_array($config[$field], $valid)) {
$value = $config[$field];
}
}
else {
$value = $config[$field];
}
}
return $value;
}
protected function getEntityTypes() {
$entity_types = [
'node',
];
foreach ($this->entityTypes as $entity_type => $definition) {
if ($entity_type != 'node' && $this
->isValidEntity($entity_type)) {
$entity_types[] = $entity_type;
}
}
return $entity_types;
}
protected function isValidEntity($entity_type) {
return $this->entityTypes[$entity_type]
->get('field_ui_base_route') && $this->entityTypes[$entity_type]
->hasViewBuilderClass();
}
}