class MenuPerRoleLinkTreeManipulator in Menu Per Role 8
Menu Per Role link tree manipulator service.
Hierarchy
- class \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators
- class \Drupal\menu_per_role\MenuPerRoleLinkTreeManipulator
Expanded class hierarchy of MenuPerRoleLinkTreeManipulator
1 string reference to 'MenuPerRoleLinkTreeManipulator'
1 service uses MenuPerRoleLinkTreeManipulator
File
- src/
MenuPerRoleLinkTreeManipulator.php, line 17
Namespace
Drupal\menu_per_roleView source
class MenuPerRoleLinkTreeManipulator extends DefaultMenuLinkTreeManipulators {
/**
* The router admin context service.
*
* @var \Drupal\Core\Routing\AdminContext
*/
protected $adminContext;
/**
* The config service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $config;
/**
* The list of the admin roles.
*
* @var string[]
*/
protected $adminRoles;
/**
* Sets the admin context.
*
* @param \Drupal\Core\Routing\AdminContext $adminContext
* The router admin context service.
*/
public function setAdminContext(AdminContext $adminContext) : void {
$this->adminContext = $adminContext;
}
/**
* Sets the config service.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* The config service.
*/
public function setConfigFactory(ConfigFactoryInterface $config) : void {
$this->config = $config;
}
/**
* {@inheritdoc}
*/
protected function menuLinkCheckAccess(MenuLinkInterface $instance) {
$result = parent::menuLinkCheckAccess($instance);
$cache_contexts = [
'user.is_super_user',
'route.is_admin',
];
if ($this
->bypassAccessCheck()) {
$result
->andIf(AccessResult::neutral()
->addCacheContexts($cache_contexts));
return $result;
}
if ($instance instanceof MenuLinkContent) {
// Sadly ::getEntity() is protected at the moment.
$function = function () {
// @phpstan-ignore-next-line
return $this
->getEntity();
};
$function = \Closure::bind($function, $instance, get_class($instance));
/** @var \Drupal\menu_link_content\Entity\MenuLinkContent $entity */
$entity = $function();
if (isset($entity->menu_per_role__show_role)) {
$show_role = $entity->menu_per_role__show_role
->getValue();
$show_role = array_column($show_role, 'target_id');
$hidden_role = $entity->menu_per_role__hide_role
->getValue();
$hidden_role = array_column($hidden_role, 'target_id');
// Check whether this role has visibility access (must be present).
if ($show_role && count(array_intersect($show_role, $this->account
->getRoles())) == 0) {
$result = $result
->andIf(AccessResult::forbidden()
->addCacheContexts([
'user.roles',
]));
}
// Check whether this role has visibility access (must not be present).
if ($hidden_role && count(array_intersect($hidden_role, $this->account
->getRoles())) > 0) {
$result = $result
->andIf(AccessResult::forbidden()
->addCacheContexts([
'user.roles',
]));
}
}
}
return $result;
}
/**
* Check if the user can bypass the access check.
*
* @return bool
* TRUE if the Menu Per Role access check should be bypassed.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function bypassAccessCheck() : bool {
$bypass_access_check = FALSE;
$menu_per_role_settings = $this->config
->get('menu_per_role.settings');
$admin_bypass_access_front = $menu_per_role_settings
->get('admin_bypass_access_front');
$admin_bypass_access_admin = $menu_per_role_settings
->get('admin_bypass_access_admin');
$context_is_admin = $this->adminContext
->isAdminRoute();
$user_is_admin = $this
->isUserAdmin();
// Admin user access check bypass.
if ($user_is_admin) {
if ($context_is_admin && $admin_bypass_access_admin || !$context_is_admin && $admin_bypass_access_front) {
$bypass_access_check = TRUE;
}
}
else {
if ($context_is_admin && $this->account
->hasPermission('bypass menu_per_role access admin') || !$context_is_admin && $this->account
->hasPermission('bypass menu_per_role access front')) {
$bypass_access_check = TRUE;
}
}
return $bypass_access_check;
}
/**
* Check if the current user is admin. Either due to uid 1 or admin roles.
*
* @return bool
* TRUE if the user admin. FALSE otherwise.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function isUserAdmin() : bool {
if ($this->account
->id() == 1) {
return TRUE;
}
// Get admin roles only one time.
if (!$this->adminRoles) {
/** @var \Drupal\user\RoleStorageInterface $role_storage */
$role_storage = $this->entityTypeManager
->getStorage('user_role');
/** @var string[] $admin_roles */
$admin_roles = $role_storage
->getQuery()
->condition('is_admin', TRUE)
->execute();
$this->adminRoles = $admin_roles;
}
$account_roles = $this->account
->getRoles(TRUE);
foreach ($account_roles as $account_role) {
if (in_array($account_role, $this->adminRoles)) {
return TRUE;
}
}
return FALSE;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DefaultMenuLinkTreeManipulators:: |
protected | property | The access manager. | |
DefaultMenuLinkTreeManipulators:: |
protected | property | The current user. | |
DefaultMenuLinkTreeManipulators:: |
protected | property | The entity type manager. | |
DefaultMenuLinkTreeManipulators:: |
public | function | Performs access checks of a menu tree. | |
DefaultMenuLinkTreeManipulators:: |
public | function | Performs access checking for nodes in an optimized way. | |
DefaultMenuLinkTreeManipulators:: |
protected | function | Collects the node links in the menu tree. | |
DefaultMenuLinkTreeManipulators:: |
public | function | Flattens the tree to a single level. | |
DefaultMenuLinkTreeManipulators:: |
public | function | Generates a unique index and sorts by it. | |
DefaultMenuLinkTreeManipulators:: |
public | function | Constructs a \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators object. | |
MenuPerRoleLinkTreeManipulator:: |
protected | property | The router admin context service. | |
MenuPerRoleLinkTreeManipulator:: |
protected | property | The list of the admin roles. | |
MenuPerRoleLinkTreeManipulator:: |
protected | property | The config service. | |
MenuPerRoleLinkTreeManipulator:: |
protected | function | Check if the user can bypass the access check. | |
MenuPerRoleLinkTreeManipulator:: |
protected | function | Check if the current user is admin. Either due to uid 1 or admin roles. | |
MenuPerRoleLinkTreeManipulator:: |
protected | function |
Checks access for one menu link instance. Overrides DefaultMenuLinkTreeManipulators:: |
|
MenuPerRoleLinkTreeManipulator:: |
public | function | Sets the admin context. | |
MenuPerRoleLinkTreeManipulator:: |
public | function | Sets the config service. |