function BlockAccessControlHandler::checkAccess

Same name in other branches
  1. 9 core/modules/block/src/BlockAccessControlHandler.php \Drupal\block\BlockAccessControlHandler::checkAccess()
  2. 10 core/modules/block/src/BlockAccessControlHandler.php \Drupal\block\BlockAccessControlHandler::checkAccess()
  3. 11.x core/modules/block/src/BlockAccessControlHandler.php \Drupal\block\BlockAccessControlHandler::checkAccess()

Overrides EntityAccessControlHandler::checkAccess

File

core/modules/block/src/BlockAccessControlHandler.php, line 74

Class

BlockAccessControlHandler
Defines the access control handler for the block entity type.

Namespace

Drupal\block

Code

protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    
    /** @var \Drupal\block\BlockInterface $entity */
    if ($operation != 'view') {
        return parent::checkAccess($entity, $operation, $account);
    }
    // Don't grant access to disabled blocks.
    if (!$entity->status()) {
        return AccessResult::forbidden()->addCacheableDependency($entity);
    }
    else {
        $conditions = [];
        $missing_context = FALSE;
        $missing_value = FALSE;
        foreach ($entity->getVisibilityConditions() as $condition_id => $condition) {
            if ($condition instanceof ContextAwarePluginInterface) {
                try {
                    $contexts = $this->contextRepository
                        ->getRuntimeContexts(array_values($condition->getContextMapping()));
                    $this->contextHandler
                        ->applyContextMapping($condition, $contexts);
                } catch (MissingValueContextException $e) {
                    $missing_value = TRUE;
                } catch (ContextException $e) {
                    $missing_context = TRUE;
                }
            }
            $conditions[$condition_id] = $condition;
        }
        if ($missing_context) {
            // If any context is missing then we might be missing cacheable
            // metadata, and don't know based on what conditions the block is
            // accessible or not. Make sure the result cannot be cached.
            $access = 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 = AccessResult::forbidden();
        }
        elseif ($this->resolveConditions($conditions, 'and') !== FALSE) {
            // Delegate to the plugin.
            $block_plugin = $entity->getPlugin();
            try {
                if ($block_plugin instanceof ContextAwarePluginInterface) {
                    $contexts = $this->contextRepository
                        ->getRuntimeContexts(array_values($block_plugin->getContextMapping()));
                    $this->contextHandler
                        ->applyContextMapping($block_plugin, $contexts);
                }
                $access = $block_plugin->access($account, TRUE);
            } catch (MissingValueContextException $e) {
                // The contexts exist but have no value. Deny access without
                // disabling caching.
                $access = AccessResult::forbidden();
            } catch (ContextException $e) {
                // If any context is missing then we might be missing cacheable
                // metadata, and don't know based on what conditions the block is
                // accessible or not. Make sure the result cannot be cached.
                $access = AccessResult::forbidden()->setCacheMaxAge(0);
            }
        }
        else {
            $reason = count($conditions) > 1 ? "One of the block visibility conditions ('%s') denied access." : "The block visibility condition '%s' denied access.";
            $access = AccessResult::forbidden(sprintf($reason, implode("', '", array_keys($conditions))));
        }
        $this->mergeCacheabilityFromConditions($access, $conditions);
        // Ensure that access is evaluated again when the block changes.
        return $access->addCacheableDependency($entity);
    }
}

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