protected function MenuLinkContentVisibilityLinkTreeManipulator::menuLinkCheckAccess in Custom Menu Links Visibility 2.x
Checks access for one menu link instance.
Parameters
\Drupal\Core\Menu\MenuLinkInterface $instance: The menu link instance.
Return value
\Drupal\Core\Access\AccessResultInterface The access result.
Overrides DefaultMenuLinkTreeManipulators::menuLinkCheckAccess
File
- src/
MenuLinkContentVisibilityLinkTreeManipulator.php, line 101
Class
- MenuLinkContentVisibilityLinkTreeManipulator
- Defines the access control handler for the menu item.
Namespace
Drupal\menu_link_content_visibilityCode
protected function menuLinkCheckAccess(MenuLinkInterface $instance) {
$access_result = parent::menuLinkCheckAccess($instance);
// Break out early if a menu administrator is running the menu access check,
// or if we are not handling a content menu link.
$is_menu_admin = $this
->getRequest()->attributes
->get('_menu_admin') ?? FALSE;
if ($is_menu_admin || !$instance instanceof MenuLinkContent) {
return $access_result;
}
// Load the menu link entity.
// @todo replace with $instance->getEntity() when no longer protected.
// @see https://www.drupal.org/project/drupal/issues/2997790
$uuid = $instance
->getDerivativeId();
/** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */
$entity = $this->entityRepository
->loadEntityByUuid('menu_link_content', $uuid);
// Load visibility conditions - if any.
$visibility = unserialize($entity
->get('visibility')->value);
if (empty($visibility)) {
return $access_result;
}
$condition_plugin_collection = new ConditionPluginCollection($this->conditionManager, $visibility);
$conditions = [];
$missing_context = FALSE;
$missing_value = FALSE;
foreach ($condition_plugin_collection as $condition_id => $condition) {
// gtag module does something special with contexts, ignore them for now
if (in_array($condition_id, [
'gtag_domain',
'gtag_language',
])) {
continue;
}
if ($condition instanceof ContextAwarePluginInterface) {
try {
$contexts = $this->contextRepository
->getRuntimeContexts(array_values($condition
->getContextMapping()));
$this->contextHandler
->applyContextMapping($condition, $contexts);
$conditions[$condition_id] = $condition;
} catch (MissingValueContextException $e) {
$missing_value = TRUE;
} catch (ContextException $e) {
$missing_context = TRUE;
}
}
}
if ($missing_context) {
// If any context is missing then we might be missing cacheable
// metadata, and don't know based on what conditions the menu link is
// accessible or not. Make sure the result cannot be cached.
$access_result = AccessResult::forbidden()
->setCacheMaxAge(0);
}
elseif ($missing_value) {
// The contexts exist but have no value. Deny access without
// disabling caching. For example the node type condition will have a
// missing context on any non-node route like the frontpage.
$access_result = AccessResult::forbidden();
}
elseif ($this
->resolveConditions($conditions, 'and') === FALSE) {
$reason = count($conditions) > 1 ? "One of the menu link visibility conditions ('%s') denied access." : "The menu link visibility condition '%s' denied access.";
$access_result = AccessResult::forbidden(sprintf($reason, implode("', '", array_keys($conditions))));
}
$this
->mergeCacheabilityFromConditions($access_result, $conditions);
// Ensure that access is evaluated again when the menu link changes.
return $access_result
->addCacheableDependency($entity);
}