Code Coverage  | 
     ||||||||||
Classes and Traits  | 
      Functions and Methods  | 
      Lines  | 
     ||||||||
| Total |         | 
      0.00%  | 
      0 / 1  | 
              | 
      0.00%  | 
      0 / 4  | 
      CRAP |         | 
      0.00%  | 
      0 / 64  | 
     
| BlockAccessControlHandler |         | 
      0.00%  | 
      0 / 1  | 
              | 
      0.00%  | 
      0 / 4  | 
      240 |         | 
      0.00%  | 
      0 / 64  | 
     
| createInstance |         | 
      0.00%  | 
      0 / 1  | 
      2 |         | 
      0.00%  | 
      0 / 7  | 
     |||
| __construct |         | 
      0.00%  | 
      0 / 1  | 
      2 |         | 
      0.00%  | 
      0 / 5  | 
     |||
| checkAccess |         | 
      0.00%  | 
      0 / 1  | 
      110 |         | 
      0.00%  | 
      0 / 44  | 
     |||
| mergeCacheabilityFromConditions |         | 
      0.00%  | 
      0 / 1  | 
      12 |         | 
      0.00%  | 
      0 / 8  | 
     |||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\block\BlockAccessControlHandler. | |
| */ | |
| namespace Drupal\block; | |
| use Drupal\Component\Plugin\Exception\ContextException; | |
| use Drupal\Core\Access\AccessResult; | |
| use Drupal\Core\Cache\Cache; | |
| use Drupal\Core\Cache\CacheableDependencyInterface; | |
| use Drupal\Core\Condition\ConditionAccessResolverTrait; | |
| use Drupal\Core\Entity\EntityAccessControlHandler; | |
| use Drupal\Core\Entity\EntityHandlerInterface; | |
| use Drupal\Core\Entity\EntityInterface; | |
| use Drupal\Core\Entity\EntityTypeInterface; | |
| use Drupal\Core\Executable\ExecutableManagerInterface; | |
| use Drupal\Core\Plugin\Context\ContextHandlerInterface; | |
| use Drupal\Core\Plugin\Context\ContextRepositoryInterface; | |
| use Drupal\Core\Plugin\ContextAwarePluginInterface; | |
| use Drupal\Core\Session\AccountInterface; | |
| use Symfony\Component\DependencyInjection\ContainerInterface; | |
| /** | |
| * Defines the access control handler for the block entity type. | |
| * | |
| * @see \Drupal\block\Entity\Block | |
| */ | |
| class BlockAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface { | |
| use ConditionAccessResolverTrait; | |
| /** | |
| * The condition plugin manager. | |
| * | |
| * @var \Drupal\Core\Executable\ExecutableManagerInterface | |
| */ | |
| protected $manager; | |
| /** | |
| * The plugin context handler. | |
| * | |
| * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface | |
| */ | |
| protected $contextHandler; | |
| /** | |
| * The context manager service. | |
| * | |
| * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface | |
| */ | |
| protected $contextRepository; | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { | |
| return new static( | |
| $entity_type, | |
| $container->get('plugin.manager.condition'), | |
| $container->get('context.handler'), | |
| $container->get('context.repository') | |
| ); | |
| } | |
| /** | |
| * Constructs the block access control handler instance | |
| * | |
| * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type | |
| * The entity type definition. | |
| * @param \Drupal\Core\Executable\ExecutableManagerInterface $manager | |
| * The ConditionManager for checking visibility of blocks. | |
| * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler | |
| * The ContextHandler for applying contexts to conditions properly. | |
| * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository | |
| * The lazy context repository service. | |
| */ | |
| public function __construct(EntityTypeInterface $entity_type, ExecutableManagerInterface $manager, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository ) { | |
| parent::__construct($entity_type); | |
| $this->manager = $manager; | |
| $this->contextHandler = $context_handler; | |
| $this->contextRepository = $context_repository; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| 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()->cacheUntilEntityChanges($entity); | |
| } | |
| else { | |
| $conditions = []; | |
| $missing_context = 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 (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. For example, blocks that have a node type | |
| // condition will have a missing context on any non-node route like the | |
| // frontpage. | |
| // @todo Avoid setting max-age 0 for some or all cases, for example by | |
| // treating available contexts without value differently in | |
| // https://www.drupal.org/node/2521956. | |
| $access = AccessResult::forbidden()->setCacheMaxAge(0); | |
| } | |
| 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 (ContextException $e) { | |
| // Setting access to forbidden if any context is missing for the same | |
| // reasons as with conditions (described in the comment above). | |
| // @todo Avoid setting max-age 0 for some or all cases, for example by | |
| // treating available contexts without value differently in | |
| // https://www.drupal.org/node/2521956. | |
| $access = AccessResult::forbidden()->setCacheMaxAge(0); | |
| } | |
| } | |
| else { | |
| $access = AccessResult::forbidden(); | |
| } | |
| $this->mergeCacheabilityFromConditions($access, $conditions); | |
| // Ensure that access is evaluated again when the block changes. | |
| return $access->cacheUntilEntityChanges($entity); | |
| } | |
| } | |
| /** | |
| * Merges cacheable metadata from conditions onto the access result object. | |
| * | |
| * @param \Drupal\Core\Access\AccessResult $access | |
| * The access result object. | |
| * @param \Drupal\Core\Condition\ConditionInterface[] $conditions | |
| * List of visibility conditions. | |
| */ | |
| protected function mergeCacheabilityFromConditions(AccessResult $access, array $conditions) { | |
| foreach ($conditions as $condition) { | |
| if ($condition instanceof CacheableDependencyInterface) { | |
| $access->addCacheTags($condition->getCacheTags()); | |
| $access->addCacheContexts($condition->getCacheContexts()); | |
| $access->setCacheMaxAge(Cache::mergeMaxAges($access->getCacheMaxAge(), $condition->getCacheMaxAge())); | |
| } | |
| } | |
| } | |
| } |