LazyContextRepository.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace Drupal\Core\Plugin\Context;
  3. use Symfony\Component\DependencyInjection\ContainerInterface;
  4. /**
  5. * Provides a context repository which uses context provider services.
  6. */
  7. class LazyContextRepository implements ContextRepositoryInterface {
  8. /**
  9. * The set of available context providers service IDs.
  10. *
  11. * @var string[]
  12. * Context provider service IDs.
  13. */
  14. protected $contextProviderServiceIDs = [];
  15. /**
  16. * The service container.
  17. *
  18. * @var \Symfony\Component\DependencyInjection\ContainerInterface
  19. */
  20. protected $container;
  21. /**
  22. * The statically cached contexts.
  23. *
  24. * @var \Drupal\Core\Plugin\Context\ContextInterface[]
  25. */
  26. protected $contexts = [];
  27. /**
  28. * Constructs a LazyContextRepository object.
  29. *
  30. * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
  31. * The current service container.
  32. * @param string[] $context_provider_service_ids
  33. * The set of the available context provider service IDs.
  34. */
  35. public function __construct(ContainerInterface $container, array $context_provider_service_ids) {
  36. $this->container = $container;
  37. $this->contextProviderServiceIDs = $context_provider_service_ids;
  38. }
  39. /**
  40. * {@inheritdoc}
  41. */
  42. public function getRuntimeContexts(array $context_ids) {
  43. $contexts = [];
  44. // Create a map of context providers (service IDs) to unqualified context
  45. // IDs.
  46. $context_ids_by_service = [];
  47. foreach ($context_ids as $id) {
  48. if (isset($this->contexts[$id])) {
  49. $contexts[$id] = $this->contexts[$id];
  50. continue;
  51. }
  52. // The IDs have been passed in @{service_id}:{unqualified_context_id}
  53. // format.
  54. // @todo Convert to an assert once https://www.drupal.org/node/2408013 is
  55. // in.
  56. if ($id[0] === '@' && strpos($id, ':') !== FALSE) {
  57. list($service_id, $unqualified_context_id) = explode(':', $id, 2);
  58. // Remove the leading '@'.
  59. $service_id = substr($service_id, 1);
  60. }
  61. else {
  62. throw new \InvalidArgumentException('You must provide the context IDs in the @{service_id}:{unqualified_context_id} format.');
  63. }
  64. $context_ids_by_service[$service_id][] = $unqualified_context_id;
  65. }
  66. // Iterate over all missing context providers (services), gather the
  67. // runtime contexts and assign them as requested.
  68. foreach ($context_ids_by_service as $service_id => $unqualified_context_ids) {
  69. $contexts_by_service = $this->container->get($service_id)->getRuntimeContexts($unqualified_context_ids);
  70. $wanted_contexts = array_intersect_key($contexts_by_service, array_flip($unqualified_context_ids));
  71. foreach ($wanted_contexts as $unqualified_context_id => $context) {
  72. $context_id = '@' . $service_id . ':' . $unqualified_context_id;
  73. $this->contexts[$context_id] = $contexts[$context_id] = $context;
  74. }
  75. }
  76. return $contexts;
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. public function getAvailableContexts() {
  82. $contexts = [];
  83. foreach ($this->contextProviderServiceIDs as $service_id) {
  84. $contexts_by_service = $this->container->get($service_id)->getAvailableContexts();
  85. foreach ($contexts_by_service as $unqualified_context_id => $context) {
  86. $context_id = '@' . $service_id . ':' . $unqualified_context_id;
  87. $contexts[$context_id] = $context;
  88. }
  89. }
  90. return $contexts;
  91. }
  92. }