class ContextHandler
Provides methods to handle sets of contexts.
Hierarchy
- class \Drupal\Core\Plugin\Context\ContextHandler implements \Drupal\Core\Plugin\Context\ContextHandlerInterface
 
Expanded class hierarchy of ContextHandler
2 files declare their use of ContextHandler
- ContextHandlerTest.php in core/
tests/ Drupal/ KernelTests/ Core/ Plugin/ ContextHandlerTest.php  - ContextHandlerTest.php in core/
tests/ Drupal/ Tests/ Core/ Plugin/ ContextHandlerTest.php  
1 string reference to 'ContextHandler'
- core.services.yml in core/
core.services.yml  - core/core.services.yml
 
1 service uses ContextHandler
File
- 
              core/
lib/ Drupal/ Core/ Plugin/ Context/ ContextHandler.php, line 14  
Namespace
Drupal\Core\Plugin\ContextView source
class ContextHandler implements ContextHandlerInterface {
  
  /**
   * {@inheritdoc}
   */
  public function filterPluginDefinitionsByContexts(array $contexts, array $definitions) {
    $checked_requirements = [];
    return array_filter($definitions, function ($plugin_definition) use ($contexts, &$checked_requirements) {
      $context_definitions = $this->getContextDefinitions($plugin_definition);
      if ($context_definitions) {
        // Generate a unique key for the current context definitions. This will
        // allow calling checkRequirements() once for all plugins that have the
        // same context definitions.
        $context_definitions_key = hash('sha256', serialize($context_definitions));
        if (!isset($checked_requirements[$context_definitions_key])) {
          // Check the set of contexts against the requirements.
          $checked_requirements[$context_definitions_key] = $this->checkRequirements($contexts, $context_definitions);
        }
        return $checked_requirements[$context_definitions_key];
      }
      // If this plugin doesn't need any context, it is available to use.
      return TRUE;
    });
  }
  
  /**
   * Returns the context definitions associated with a plugin definition.
   *
   * @param array|\Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface $plugin_definition
   *   The plugin definition.
   *
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]|null
   *   The context definitions, or NULL if the plugin definition does not
   *   support contexts.
   */
  protected function getContextDefinitions($plugin_definition) {
    if ($plugin_definition instanceof ContextAwarePluginDefinitionInterface) {
      return $plugin_definition->getContextDefinitions();
    }
    if (is_array($plugin_definition) && isset($plugin_definition['context_definitions'])) {
      return $plugin_definition['context_definitions'];
    }
    return NULL;
  }
  
  /**
   * {@inheritdoc}
   */
  public function checkRequirements(array $contexts, array $requirements) {
    foreach ($requirements as $requirement) {
      if ($requirement->isRequired() && !$this->getMatchingContexts($contexts, $requirement)) {
        return FALSE;
      }
    }
    return TRUE;
  }
  
  /**
   * {@inheritdoc}
   */
  public function getMatchingContexts(array $contexts, ContextDefinitionInterface $definition) {
    return array_filter($contexts, function (ContextInterface $context) use ($definition) {
      return $definition->isSatisfiedBy($context);
    });
  }
  
  /**
   * {@inheritdoc}
   */
  public function applyContextMapping(ContextAwarePluginInterface $plugin, $contexts, $mappings = []) {
    /** @var \Drupal\Core\Plugin\Context\ContextInterface[] $contexts */
    $mappings += $plugin->getContextMapping();
    // Loop through each of the expected contexts.
    $missing_value = [];
    foreach ($plugin->getContextDefinitions() as $plugin_context_id => $plugin_context_definition) {
      // If this context was given a specific name, use that.
      $context_id = $mappings[$plugin_context_id] ?? $plugin_context_id;
      if (!empty($contexts[$context_id])) {
        // This assignment has been used, remove it.
        unset($mappings[$plugin_context_id]);
        // Plugins have their on context objects, only the value is applied.
        // They also need to know about the cacheability metadata of where that
        // value is coming from, so pass them through to those objects.
        $plugin_context = $plugin->getContext($plugin_context_id);
        if ($plugin_context instanceof ContextInterface && $contexts[$context_id] instanceof CacheableDependencyInterface) {
          $plugin_context->addCacheableDependency($contexts[$context_id]);
        }
        // Pass the value to the plugin if there is one.
        if ($contexts[$context_id]->hasContextValue()) {
          $plugin->setContext($plugin_context_id, $contexts[$context_id]);
        }
        elseif ($plugin_context_definition->isRequired()) {
          // Collect required contexts that exist but are missing a value.
          $missing_value[] = $plugin_context_id;
        }
        // Proceed to the next definition.
        continue;
      }
      try {
        $context = $plugin->getContext($context_id);
      } catch (ContextException $e) {
        $context = NULL;
      }
      if ($context && $context->hasContextValue()) {
        // Ignore mappings if the plugin has a value for a missing context.
        unset($mappings[$plugin_context_id]);
        continue;
      }
      if ($plugin_context_definition->isRequired()) {
        // Collect required contexts that are missing.
        $missing_value[] = $plugin_context_id;
        continue;
      }
      // Ignore mappings for optional missing context.
      unset($mappings[$plugin_context_id]);
    }
    // If there are any mappings that were not satisfied, throw an exception.
    // This is a more severe problem than missing values, so check and throw
    // this first.
    if (!empty($mappings)) {
      throw new ContextException('Assigned contexts were not satisfied: ' . implode(',', array_keys($mappings)));
    }
    // If there are any required contexts without a value, throw an exception.
    if ($missing_value) {
      throw new MissingValueContextException($missing_value);
    }
  }
}
Members
| Title Sort descending | Modifiers | Object type | Summary | Overriden Title | 
|---|---|---|---|---|
| ContextHandler::applyContextMapping | public | function | Prepares a plugin for evaluation. | Overrides ContextHandlerInterface::applyContextMapping | 
| ContextHandler::checkRequirements | public | function | Checks a set of requirements against a set of contexts. | Overrides ContextHandlerInterface::checkRequirements | 
| ContextHandler::filterPluginDefinitionsByContexts | public | function | Determines plugins whose constraints are satisfied by a set of contexts. | Overrides ContextHandlerInterface::filterPluginDefinitionsByContexts | 
| ContextHandler::getContextDefinitions | protected | function | Returns the context definitions associated with a plugin definition. | |
| ContextHandler::getMatchingContexts | public | function | Determines which contexts satisfy the constraints of a given definition. | Overrides ContextHandlerInterface::getMatchingContexts | 
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.