- Issue created by @mstrelan
As per β¨ Allow MenuLinkTree manipulators to be altered Needs work there are a number of use cases for altering MenuLinkTree manipulators. Sometimes you just want to provide custom access controls to menu links.
One way to achieve this is to decorate the menu.default_tree_manipulators
service. This works pretty well, but it means you need to implement all the public methods, including checkAccess, checkNodeAccess, generateIndexAndSort, and flatten. There is no guarantee that there won't be another method added in the future.
mymodule.services.yml:
services:
Drupal\my_module\Menu\MyModuleMenuLinkTreeManipulators:
decorates: 'menu.default_tree_manipulators'
autowire: true
MyModuleMenuLinkTreeManipulators.php
<?php
declare(strict_types=1);
namespace Drupal\my_module\Menu;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Menu\DefaultMenuLinkTreeManipulators;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Core\Session\AccountInterface;
/**
* Decorates the menu.default_tree_manipulators service.
*
* @see \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators
*/
final class MyModuleMenuLinkTreeManipulators {
public function __construct(
protected DefaultMenuLinkTreeManipulators $inner,
protected AccountInterface $account,
) {}
/**
* @see DefaultMenuLinkTreeManipulators::checkAccess()
*/
public function checkAccess(array $tree): array {
$tree = $this->inner->checkAccess($tree);
foreach ($tree as $element) {
$this->menuLinkCheckAccess($element);
}
return $tree;
}
/**
* Custom access check.
*/
protected function menuLinkCheckAccess(MenuLinkTreeElement $element): void {
if (isset($element->access) && $element->access->isForbidden()) {
return;
}
if ($element->link->getPluginId() === 'my_module.custom_menu_link') {
$element->access = AccessResult::allowedIfHasPermission($this->account, 'my module permission');
}
foreach ($element->subtree as $branch) {
$this->menuLinkCheckAccess($branch);
}
}
public function checkNodeAccess(array $tree): array {
return $this->inner->checkNodeAccess($tree);
}
public function generateIndexAndSort(array $tree): array {
return $this->inner->generateIndexAndSort($tree);
}
public function flatten(array $tree): array {
return $this->inner->flatten($tree);
}
}
Is this even viable?
Active
11.0 π₯