Issue #2594425 by Sam152, gapple, naveenvalecha, dubcanada, Nitesh Pawar, Fonski, bircher, Eric115, ricovandevin, pameeela, mishradileep, juusechec, dawehner, jibran, xjm, ifrik, swentel, kim.pepper, Wim Leers, acbramley, 4aficiona2, yoroy, alexpott, ckaotik, andypost, FeyP: Add the option in system menu block to "Expand all items in this tree"

8.7.x
Alex Pott 2018-12-07 12:01:11 +01:00
parent f7f07d81ac
commit f335587290
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
20 changed files with 209 additions and 5 deletions

View File

@ -130,7 +130,7 @@ class MenuLinkDefaultForm implements MenuLinkFormInterface, ContainerInjectionIn
$form['expanded'] = [ $form['expanded'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => t('Show as expanded'), '#title' => t('Show as expanded'),
'#description' => $this->t('If selected and this menu link has children, the menu will always appear expanded.'), '#description' => $this->t('If selected and this menu link has children, the menu will always appear expanded. This option may be overridden for the entire menu tree when placing a menu block.'),
'#default_value' => $this->menuLink->isExpanded(), '#default_value' => $this->menuLink->isExpanded(),
]; ];

View File

@ -120,6 +120,7 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
'provider' => 'system', 'provider' => 'system',
'label_display' => 'visible', 'label_display' => 'visible',
'level' => 1, 'level' => 1,
'expand_all_items' => FALSE,
'depth' => 0, 'depth' => 0,
]; ];
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', -11, $settings); $this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', -11, $settings);

View File

@ -348,7 +348,7 @@ class MenuLinkContent extends ContentEntityBase implements MenuLinkContentInterf
$fields['expanded'] = BaseFieldDefinition::create('boolean') $fields['expanded'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Show as expanded')) ->setLabel(t('Show as expanded'))
->setDescription(t('If selected and this menu link has children, the menu will always appear expanded.')) ->setDescription(t('If selected and this menu link has children, the menu will always appear expanded. This option may be overridden for the entire menu tree when placing a menu block.'))
->setDefaultValue(FALSE) ->setDefaultValue(FALSE)
->setDisplayOptions('view', [ ->setDisplayOptions('view', [
'label' => 'hidden', 'label' => 'hidden',

View File

@ -864,6 +864,47 @@ class MenuUiTest extends BrowserTestBase {
$this->assertSession()->statusCodeEquals(403); $this->assertSession()->statusCodeEquals(403);
} }
/**
* Test the "expand all items" feature.
*/
public function testExpandAllItems() {
$this->drupalLogin($this->adminUser);
$menu = $this->addCustomMenu();
$node = $this->drupalCreateNode(['type' => 'article']);
// Create three menu items, none of which are expanded.
$parent = $this->addMenuLink('', $node->toUrl()->toString(), $menu->id(), FALSE);
$child_1 = $this->addMenuLink($parent->getPluginId(), $node->toUrl()->toString(), $menu->id(), FALSE);
$child_2 = $this->addMenuLink($parent->getPluginId(), $node->toUrl()->toString(), $menu->id(), FALSE);
// The menu will not automatically show all levels of depth.
$this->drupalGet('<front>');
$this->assertSession()->linkExists($parent->getTitle());
$this->assertSession()->linkNotExists($child_1->getTitle());
$this->assertSession()->linkNotExists($child_2->getTitle());
// Update the menu block to show all levels of depth as expanded.
$block_id = $this->blockPlacements[$menu->id()];
$this->drupalGet('admin/structure/block/manage/' . $block_id);
$this->assertSession()->checkboxNotChecked('settings[expand_all_items]');
$this->drupalPostForm(NULL, [
'settings[depth]' => 2,
'settings[level]' => 1,
'settings[expand_all_items]' => 1,
], t('Save block'));
// Ensure the setting is persisted.
$this->drupalGet('admin/structure/block/manage/' . $block_id);
$this->assertSession()->checkboxChecked('settings[expand_all_items]');
// Ensure all three links are shown, including the children which would
// usually be hidden without the "expand all items" setting.
$this->drupalGet('<front>');
$this->assertSession()->linkExists($parent->getTitle());
$this->assertSession()->linkExists($child_1->getTitle());
$this->assertSession()->linkExists($child_2->getTitle());
}
/** /**
* Returns standard menu link. * Returns standard menu link.
* *

View File

@ -337,6 +337,9 @@ block.settings.system_menu_block:*:
depth: depth:
type: integer type: integer
label: 'Maximum number of levels' label: 'Maximum number of levels'
expand_all_items:
type: boolean
label: 'Expand all items'
block.settings.local_tasks_block: block.settings.local_tasks_block:
type: block_settings type: block_settings

View File

@ -5,7 +5,9 @@ namespace Drupal\system\Plugin\Block;
use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Menu\MenuActiveTrailInterface;
use Drupal\Core\Menu\MenuLinkTreeInterface; use Drupal\Core\Menu\MenuLinkTreeInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
@ -31,6 +33,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
*/ */
protected $menuTree; protected $menuTree;
/**
* The active menu trail service.
*
* @var \Drupal\Core\Menu\MenuActiveTrailInterface
*/
protected $menuActiveTrail;
/** /**
* Constructs a new SystemMenuBlock. * Constructs a new SystemMenuBlock.
* *
@ -42,10 +51,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
* The plugin implementation definition. * The plugin implementation definition.
* @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree
* The menu tree service. * 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) { public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail) {
parent::__construct($configuration, $plugin_id, $plugin_definition); parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->menuTree = $menu_tree; $this->menuTree = $menu_tree;
$this->menuActiveTrail = $menu_active_trail;
} }
/** /**
@ -56,7 +68,8 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
$configuration, $configuration,
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$container->get('menu.link_tree') $container->get('menu.link_tree'),
$container->get('menu.active_trail')
); );
} }
@ -98,6 +111,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
'#required' => TRUE, '#required' => TRUE,
]; ];
$form['menu_levels']['expand_all_items'] = [
'#type' => 'checkbox',
'#title' => $this->t('Expand all menu items'),
'#default_value' => !empty($config['expand_all_items']),
'#description' => $this->t('Override the option found on each menu link used for expanding children and instead display the whole menu tree as expanded.'),
];
return $form; return $form;
} }
@ -117,6 +137,7 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
public function blockSubmit($form, FormStateInterface $form_state) { public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['level'] = $form_state->getValue('level'); $this->configuration['level'] = $form_state->getValue('level');
$this->configuration['depth'] = $form_state->getValue('depth'); $this->configuration['depth'] = $form_state->getValue('depth');
$this->configuration['expand_all_items'] = $form_state->getValue('expand_all_items');
} }
/** /**
@ -124,7 +145,14 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
*/ */
public function build() { public function build() {
$menu_name = $this->getDerivativeId(); $menu_name = $this->getDerivativeId();
$parameters = $this->menuTree->getCurrentRouteMenuTreeParameters($menu_name); if ($this->configuration['expand_all_items']) {
$parameters = new MenuTreeParameters();
$active_trail = $this->menuActiveTrail->getActiveTrailIds($menu_name);
$parameters->setActiveTrail($active_trail);
}
else {
$parameters = $this->menuTree->getCurrentRouteMenuTreeParameters($menu_name);
}
// Adjust the menu tree parameters based on the block's configuration. // Adjust the menu tree parameters based on the block's configuration.
$level = $this->configuration['level']; $level = $this->configuration['level'];
@ -173,6 +201,7 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
return [ return [
'level' => 1, 'level' => 1,
'depth' => 0, 'depth' => 0,
'expand_all_items' => FALSE,
]; ];
} }

View File

@ -178,3 +178,16 @@ function system_post_update_extra_fields(&$sandbox = NULL) {
function system_post_update_states_clear_cache() { function system_post_update_states_clear_cache() {
// Empty post-update hook. // Empty post-update hook.
} }
/**
* Initialize 'expand_all_items' values to system_menu_block.
*/
function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sandbox = NULL) {
\Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'block', function ($block) {
if (strpos($block->getPluginId(), 'system_menu_block:') === 0) {
$block->set('settings.expand_all_items', FALSE);
return TRUE;
}
return FALSE;
});
}

View File

@ -0,0 +1,38 @@
<?php
namespace Drupal\Tests\system\Functional\Update;
use Drupal\block\Entity\Block;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests updating menu blocks configuration.
*
* @group Update
* @group legacy
*/
class MenuBlockPostUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
// Use a more recent fixture for performance, do not run all pre-8.4
// updates when testing this feature.
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
];
}
/**
* Tests updating blocks with default 'expand_all_items' value.
*
* @see system_post_update_add_expand_all_items_key_in_system_menu_block()
*/
public function testPostUpdateMenuBlockFields() {
$this->assertArrayNotHasKey('expand_all_items', Block::load('bartik_account_menu')->get('settings'));
$this->runUpdates();
$this->assertArrayHasKey('expand_all_items', Block::load('bartik_account_menu')->get('settings'));
}
}

View File

@ -282,6 +282,76 @@ class SystemMenuBlockTest extends KernelTestBase {
} }
} }
/**
* Tests the config expanded option.
*
* @dataProvider configExpandedTestCases
*/
public function testConfigExpanded($active_route, $menu_block_level, $expected_items) {
$block = $this->blockManager->createInstance('system_menu_block:' . $this->menu->id(), [
'region' => 'footer',
'id' => 'machinename',
'theme' => 'stark',
'level' => $menu_block_level,
'depth' => 0,
'expand_all_items' => TRUE,
]);
$route = $this->container->get('router.route_provider')->getRouteByName($active_route);
$request = new Request();
$request->attributes->set(RouteObjectInterface::ROUTE_NAME, $active_route);
$request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route);
$this->container->get('request_stack')->push($request);
$block_build = $block->build();
$items = isset($block_build['#items']) ? $block_build['#items'] : [];
$this->assertEquals($expected_items, $this->convertBuiltMenuToIdTree($items));
}
/**
* @return array
*/
public function configExpandedTestCases() {
return [
'All levels' => [
'example5',
1,
[
'test.example1' => [],
'test.example2' => [
'test.example3' => [
'test.example4' => [],
],
],
'test.example5' => [
'test.example7' => [],
],
'test.example6' => [],
'test.example8' => [],
],
],
'Level two in "example 5" branch' => [
'example5',
2,
[
'test.example7' => [],
],
],
'Level three in "example 5" branch' => [
'example5',
3,
[],
],
'Level three in "example 4" branch' => [
'example4',
3,
[
'test.example4' => [],
],
],
];
}
/** /**
* Helper method to allow for easy menu link tree structure assertions. * Helper method to allow for easy menu link tree structure assertions.
* *

View File

@ -20,4 +20,5 @@ settings:
label_display: '0' label_display: '0'
level: 1 level: 1
depth: 1 depth: 1
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: '1' label_display: '1'
level: 1 level: 1
depth: 0 depth: 0
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: '0' label_display: '0'
level: 1 level: 1
depth: 1 depth: 1
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: visible label_display: visible
level: 1 level: 1
depth: 0 depth: 0
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: visible label_display: visible
level: 1 level: 1
depth: 0 depth: 0
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: '0' label_display: '0'
level: 1 level: 1
depth: 1 depth: 1
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: '0' label_display: '0'
level: 1 level: 1
depth: 0 depth: 0
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: '0' label_display: '0'
level: 1 level: 1
depth: 1 depth: 1
expand_all_items: false
visibility: { } visibility: { }

View File

@ -20,4 +20,5 @@ settings:
label_display: visible label_display: visible
level: 1 level: 1
depth: 0 depth: 0
expand_all_items: false
visibility: { } visibility: { }