Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
CRAP | |
100.00% |
37 / 37 |
| ContextHandler | |
100.00% |
1 / 1 |
|
100.00% |
5 / 5 |
27 | |
100.00% |
37 / 37 |
| filterPluginDefinitionsByContexts | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| anonymous function | |
100.00% |
1 / 1 |
5 | |
100.00% |
8 / 8 |
|||
| checkRequirements | |
100.00% |
1 / 1 |
4 | |
100.00% |
4 / 4 |
|||
| getMatchingContexts | |
100.00% |
1 / 1 |
5 | |
100.00% |
0 / 0 |
|||
| applyContextMapping | |
100.00% |
1 / 1 |
11 | |
100.00% |
21 / 21 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Plugin\Context\ContextHandler. | |
| */ | |
| namespace Drupal\Core\Plugin\Context; | |
| use Drupal\Component\Plugin\Exception\ContextException; | |
| use Drupal\Core\Cache\CacheableDependencyInterface; | |
| use Drupal\Core\Plugin\ContextAwarePluginInterface; | |
| /** | |
| * Provides methods to handle sets of contexts. | |
| */ | |
| class ContextHandler implements ContextHandlerInterface { | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function filterPluginDefinitionsByContexts(array $contexts, array $definitions) { | |
| return array_filter($definitions, function ($plugin_definition) use ($contexts) { | |
| // If this plugin doesn't need any context, it is available to use. | |
| if (!isset($plugin_definition['context'])) { | |
| return TRUE; | |
| } | |
| // Check the set of contexts against the requirements. | |
| return $this->checkRequirements($contexts, $plugin_definition['context']); | |
| }); | |
| } | |
| /** | |
| * {@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) { | |
| $context_definition = $context->getContextDefinition(); | |
| // If the data types do not match, this context is invalid unless the | |
| // expected data type is any, which means all data types are supported. | |
| if ($definition->getDataType() != 'any' && $definition->getDataType() != $context_definition->getDataType()) { | |
| return FALSE; | |
| } | |
| // If any constraint does not match, this context is invalid. | |
| foreach ($definition->getConstraints() as $constraint_name => $constraint) { | |
| if ($context_definition->getConstraint($constraint_name) != $constraint) { | |
| return FALSE; | |
| } | |
| } | |
| // All contexts with matching data type and contexts are valid. | |
| return TRUE; | |
| }); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function applyContextMapping(ContextAwarePluginInterface $plugin, $contexts, $mappings = array()) { | |
| /** @var $contexts \Drupal\Core\Plugin\Context\ContextInterface[] */ | |
| $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 = isset($mappings[$plugin_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->setContextValue($plugin_context_id, $contexts[$context_id]->getContextData()); | |
| } | |
| elseif ($plugin_context_definition->isRequired()) { | |
| // Collect required contexts that exist but are missing a value. | |
| $missing_value[] = $plugin_context_id; | |
| } | |
| } | |
| elseif ($plugin_context_definition->isRequired()) { | |
| // Collect required contexts that are missing. | |
| $missing_value[] = $plugin_context_id; | |
| } | |
| else { | |
| // Ignore mappings for optional missing context. | |
| unset($mappings[$plugin_context_id]); | |
| } | |
| } | |
| // If there are any required contexts without a value, throw an exception. | |
| if ($missing_value) { | |
| throw new ContextException(sprintf('Required contexts without a value: %s.', implode(', ', $missing_value))); | |
| } | |
| // If there are any mappings that were not satisfied, throw an exception. | |
| if (!empty($mappings)) { | |
| throw new ContextException('Assigned contexts were not satisfied: ' . implode(',', array_keys($mappings))); | |
| } | |
| } | |
| } |