ContextHandler.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace Drupal\Core\Plugin\Context;
  3. use Drupal\Component\Plugin\Exception\ContextException;
  4. use Drupal\Core\Cache\CacheableDependencyInterface;
  5. use Drupal\Core\Plugin\ContextAwarePluginInterface;
  6. /**
  7. * Provides methods to handle sets of contexts.
  8. */
  9. class ContextHandler implements ContextHandlerInterface {
  10. /**
  11. * {@inheritdoc}
  12. */
  13. public function filterPluginDefinitionsByContexts(array $contexts, array $definitions) {
  14. return array_filter($definitions, function ($plugin_definition) use ($contexts) {
  15. // If this plugin doesn't need any context, it is available to use.
  16. if (!isset($plugin_definition['context'])) {
  17. return TRUE;
  18. }
  19. // Check the set of contexts against the requirements.
  20. return $this->checkRequirements($contexts, $plugin_definition['context']);
  21. });
  22. }
  23. /**
  24. * {@inheritdoc}
  25. */
  26. public function checkRequirements(array $contexts, array $requirements) {
  27. foreach ($requirements as $requirement) {
  28. if ($requirement->isRequired() && !$this->getMatchingContexts($contexts, $requirement)) {
  29. return FALSE;
  30. }
  31. }
  32. return TRUE;
  33. }
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public function getMatchingContexts(array $contexts, ContextDefinitionInterface $definition) {
  38. return array_filter($contexts, function (ContextInterface $context) use ($definition) {
  39. return $definition->isSatisfiedBy($context);
  40. });
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public function applyContextMapping(ContextAwarePluginInterface $plugin, $contexts, $mappings = []) {
  46. /** @var $contexts \Drupal\Core\Plugin\Context\ContextInterface[] */
  47. $mappings += $plugin->getContextMapping();
  48. // Loop through each of the expected contexts.
  49. $missing_value = [];
  50. foreach ($plugin->getContextDefinitions() as $plugin_context_id => $plugin_context_definition) {
  51. // If this context was given a specific name, use that.
  52. $context_id = isset($mappings[$plugin_context_id]) ? $mappings[$plugin_context_id] : $plugin_context_id;
  53. if (!empty($contexts[$context_id])) {
  54. // This assignment has been used, remove it.
  55. unset($mappings[$plugin_context_id]);
  56. // Plugins have their on context objects, only the value is applied.
  57. // They also need to know about the cacheability metadata of where that
  58. // value is coming from, so pass them through to those objects.
  59. $plugin_context = $plugin->getContext($plugin_context_id);
  60. if ($plugin_context instanceof ContextInterface && $contexts[$context_id] instanceof CacheableDependencyInterface) {
  61. $plugin_context->addCacheableDependency($contexts[$context_id]);
  62. }
  63. // Pass the value to the plugin if there is one.
  64. if ($contexts[$context_id]->hasContextValue()) {
  65. $plugin->setContextValue($plugin_context_id, $contexts[$context_id]->getContextData());
  66. }
  67. elseif ($plugin_context_definition->isRequired()) {
  68. // Collect required contexts that exist but are missing a value.
  69. $missing_value[] = $plugin_context_id;
  70. }
  71. }
  72. elseif ($plugin_context_definition->isRequired()) {
  73. // Collect required contexts that are missing.
  74. $missing_value[] = $plugin_context_id;
  75. }
  76. else {
  77. // Ignore mappings for optional missing context.
  78. unset($mappings[$plugin_context_id]);
  79. }
  80. }
  81. // If there are any required contexts without a value, throw an exception.
  82. if ($missing_value) {
  83. throw new ContextException(sprintf('Required contexts without a value: %s.', implode(', ', $missing_value)));
  84. }
  85. // If there are any mappings that were not satisfied, throw an exception.
  86. if (!empty($mappings)) {
  87. throw new ContextException('Assigned contexts were not satisfied: ' . implode(',', array_keys($mappings)));
  88. }
  89. }
  90. }