Unverified Commit f3355872 authored by alexpott's avatar alexpott

Issue #2594425 by Sam152, gapple, naveenvalecha, dubcanada, Nitesh Pawar,...

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"
parent f7f07d81
......@@ -130,7 +130,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
$form['expanded'] = [
'#type' => 'checkbox',
'#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(),
];
......
......@@ -120,6 +120,7 @@ public function testBlockMigration() {
'provider' => 'system',
'label_display' => 'visible',
'level' => 1,
'expand_all_items' => FALSE,
'depth' => 0,
];
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', -11, $settings);
......
......@@ -348,7 +348,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['expanded'] = BaseFieldDefinition::create('boolean')
->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)
->setDisplayOptions('view', [
'label' => 'hidden',
......
......@@ -864,6 +864,47 @@ public function testMenuParentsJsAccess() {
$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.
*
......
......@@ -337,6 +337,9 @@ block.settings.system_menu_block:*:
depth:
type: integer
label: 'Maximum number of levels'
expand_all_items:
type: boolean
label: 'Expand all items'
block.settings.local_tasks_block:
type: block_settings
......
......@@ -5,7 +5,9 @@
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\Menu\MenuTreeParameters;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -31,6 +33,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
*/
protected $menuTree;
/**
* The active menu trail service.
*
* @var \Drupal\Core\Menu\MenuActiveTrailInterface
*/
protected $menuActiveTrail;
/**
* Constructs a new SystemMenuBlock.
*
......@@ -42,10 +51,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
* 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) {
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;
}
/**
......@@ -56,7 +68,8 @@ public static function create(ContainerInterface $container, array $configuratio
$configuration,
$plugin_id,
$plugin_definition,
$container->get('menu.link_tree')
$container->get('menu.link_tree'),
$container->get('menu.active_trail')
);
}
......@@ -98,6 +111,13 @@ public function blockForm($form, FormStateInterface $form_state) {
'#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;
}
......@@ -117,6 +137,7 @@ public static function processMenuLevelParents(&$element, FormStateInterface $fo
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['level'] = $form_state->getValue('level');
$this->configuration['depth'] = $form_state->getValue('depth');
$this->configuration['expand_all_items'] = $form_state->getValue('expand_all_items');
}
/**
......@@ -124,7 +145,14 @@ public function blockSubmit($form, FormStateInterface $form_state) {
*/
public function build() {
$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.
$level = $this->configuration['level'];
......@@ -173,6 +201,7 @@ public function defaultConfiguration() {
return [
'level' => 1,
'depth' => 0,
'expand_all_items' => FALSE,
];
}
......
......@@ -178,3 +178,16 @@ function system_post_update_extra_fields(&$sandbox = NULL) {
function system_post_update_states_clear_cache() {
// 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;
});
}
<?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'));
}
}
......@@ -282,6 +282,76 @@ public function testConfigLevelDepth() {
}
}
/**
* 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.
*
......
......@@ -20,4 +20,5 @@ settings:
label_display: '0'
level: 1
depth: 1
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: '1'
level: 1
depth: 0
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: '0'
level: 1
depth: 1
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: visible
level: 1
depth: 0
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: visible
level: 1
depth: 0
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: '0'
level: 1
depth: 1
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: '0'
level: 1
depth: 0
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: '0'
level: 1
depth: 1
expand_all_items: false
visibility: { }
......@@ -20,4 +20,5 @@ settings:
label_display: visible
level: 1
depth: 0
expand_all_items: false
visibility: { }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment