class SystemAdminMenuBlockAccessCheck

Same name and namespace in other branches
  1. 11.x core/modules/system/src/Access/SystemAdminMenuBlockAccessCheck.php \Drupal\system\Access\SystemAdminMenuBlockAccessCheck

Access check for routes implementing _access_admin_menu_block_page.

Hierarchy

Expanded class hierarchy of SystemAdminMenuBlockAccessCheck

See also

\Drupal\system\EventSubscriber\AccessRouteAlterSubscriber

\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage()

1 string reference to 'SystemAdminMenuBlockAccessCheck'
system.services.yml in core/modules/system/system.services.yml
core/modules/system/system.services.yml
2 services use SystemAdminMenuBlockAccessCheck
access_check.admin_menu_block_page in core/modules/system/system.services.yml
Drupal\system\Access\SystemAdminMenuBlockAccessCheck
access_check.admin_overview_page in core/modules/system/system.services.yml
Drupal\system\Access\SystemAdminMenuBlockAccessCheck

File

core/modules/system/src/Access/SystemAdminMenuBlockAccessCheck.php, line 23

Namespace

Drupal\system\Access
View source
class SystemAdminMenuBlockAccessCheck implements AccessInterface {
  
  /**
   * Constructs a new SystemAdminMenuBlockAccessCheck.
   *
   * @param \Drupal\Core\Access\AccessManagerInterface $accessManager
   *   The access manager.
   * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menuLinkTree
   *   The menu link tree service.
   * @param \Drupal\Core\Routing\AccessAwareRouter $router
   *   The router service.
   * @param \Drupal\Core\Menu\MenuLinkManagerInterface $menuLinkManager
   *   The menu link manager service.
   */
  public function __construct(private readonly AccessManagerInterface $accessManager, private readonly MenuLinkTreeInterface $menuLinkTree, private readonly AccessAwareRouter $router, private readonly MenuLinkManagerInterface $menuLinkManager) {
  }
  
  /**
   * Checks access.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The cron key.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(RouteMatchInterface $route_match, AccountInterface $account) : AccessResultInterface {
    $parameters = $route_match->getParameters()
      ->all();
    $route = $route_match->getRouteObject();
    // Load links in the 'admin' menu matching this route. First, try to find
    // the menu link using all specified parameters.
    $links = $this->menuLinkManager
      ->loadLinksByRoute($route_match->getRouteName(), $parameters, 'admin');
    // If the menu link was not found, try finding it without the parameters
    // that match the route defaults. Depending on whether the parameter is
    // specified in the menu item with a value matching the default, or not
    // specified at all, will change how it is stored in the menu_tree table. In
    // both cases the route match parameters will always include the default
    // parameters. This fallback method of finding the menu item is needed so
    // that menu items will work in either case.
    // @todo Remove this fallback in https://drupal.org/i/3359511.
    if (empty($links)) {
      $parameters_without_defaults = array_filter($parameters, fn($key) => !$route->hasDefault($key) || $route->getDefault($key) !== $parameters[$key], ARRAY_FILTER_USE_KEY);
      $links = $this->menuLinkManager
        ->loadLinksByRoute($route_match->getRouteName(), $parameters_without_defaults, 'admin');
    }
    if (empty($links)) {
      // If we did not find a link then we have no opinion on access.
      return AccessResult::neutral();
    }
    return $this->hasAccessToChildMenuItems(reset($links), $account)
      ->cachePerPermissions();
  }
  
  /**
   * Check that the given route has access to child routes.
   *
   * @param \Drupal\Core\Menu\MenuLinkInterface $link
   *   The menu link.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  protected function hasAccessToChildMenuItems(MenuLinkInterface $link, AccountInterface $account) : AccessResultInterface {
    $parameters = new MenuTreeParameters();
    $parameters->setRoot($link->getPluginId())
      ->excludeRoot()
      ->setTopLevelOnly()
      ->onlyEnabledLinks();
    $route = $this->router
      ->getRouteCollection()
      ->get($link->getRouteName());
    if ($route && empty($route->getRequirement('_access_admin_menu_block_page')) && empty($route->getRequirement('_access_admin_overview_page'))) {
      return AccessResult::allowed();
    }
    foreach ($this->menuLinkTree
      ->load(NULL, $parameters) as $element) {
      if (!$this->accessManager
        ->checkNamedRoute($element->link
        ->getRouteName(), $element->link
        ->getRouteParameters(), $account)) {
        continue;
      }
      // If access is allowed to this element in the tree, check for access to
      // any of its own children.
      if ($this->hasAccessToChildMenuItems($element->link, $account)
        ->isAllowed()) {
        return AccessResult::allowed();
      }
    }
    return AccessResult::neutral();
  }

}

Members

Title Sort descending Modifiers Object type Summary
SystemAdminMenuBlockAccessCheck::access public function Checks access.
SystemAdminMenuBlockAccessCheck::hasAccessToChildMenuItems protected function Check that the given route has access to child routes.
SystemAdminMenuBlockAccessCheck::__construct public function Constructs a new SystemAdminMenuBlockAccessCheck.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.