Context.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. namespace Drupal\Core\Plugin\Context;
  3. use Drupal\Component\Plugin\Context\Context as ComponentContext;
  4. use Drupal\Component\Plugin\Exception\ContextException;
  5. use Drupal\Core\Cache\CacheableDependencyInterface;
  6. use Drupal\Core\Cache\CacheableMetadata;
  7. use Drupal\Core\DependencyInjection\DependencySerializationTrait;
  8. use Drupal\Core\TypedData\TypedDataInterface;
  9. use Drupal\Core\TypedData\TypedDataTrait;
  10. /**
  11. * A Drupal specific context wrapper class.
  12. */
  13. class Context extends ComponentContext implements ContextInterface {
  14. use TypedDataTrait;
  15. use DependencySerializationTrait;
  16. /**
  17. * The data associated with the context.
  18. *
  19. * @var \Drupal\Core\TypedData\TypedDataInterface
  20. */
  21. protected $contextData;
  22. /**
  23. * The definition to which a context must conform.
  24. *
  25. * @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface
  26. */
  27. protected $contextDefinition;
  28. /**
  29. * The cacheability metadata.
  30. *
  31. * @var \Drupal\Core\Cache\CacheableMetadata
  32. */
  33. protected $cacheabilityMetadata;
  34. /**
  35. * Create a context object.
  36. *
  37. * @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context_definition
  38. * The context definition.
  39. * @param mixed|null $context_value
  40. * The context value object.
  41. */
  42. public function __construct(ContextDefinitionInterface $context_definition, $context_value = NULL) {
  43. parent::__construct($context_definition, NULL);
  44. $this->cacheabilityMetadata = new CacheableMetadata();
  45. if (!is_null($context_value)) {
  46. $this->setContextValue($context_value);
  47. }
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function getContextValue() {
  53. if (!isset($this->contextData)) {
  54. $definition = $this->getContextDefinition();
  55. $default_value = $definition->getDefaultValue();
  56. if (isset($default_value)) {
  57. // Keep the default value here so that subsequent calls don't have to
  58. // look it up again.
  59. $this->setContextValue($default_value);
  60. }
  61. elseif ($definition->isRequired()) {
  62. $type = $definition->getDataType();
  63. throw new ContextException("The '$type' context is required and not present.");
  64. }
  65. return $default_value;
  66. }
  67. return $this->getTypedDataManager()->getCanonicalRepresentation($this->contextData);
  68. }
  69. /**
  70. * {@inheritdoc}
  71. */
  72. public function hasContextValue() {
  73. return (bool) $this->contextData || parent::hasContextValue();
  74. }
  75. /**
  76. * Sets the context value.
  77. *
  78. * @param mixed $value
  79. * The value of this context, matching the context definition.
  80. */
  81. protected function setContextValue($value) {
  82. // Add the value as a cacheable dependency only if implements the interface
  83. // to prevent it from disabling caching with a max-age 0.
  84. if ($value instanceof CacheableDependencyInterface) {
  85. $this->addCacheableDependency($value);
  86. }
  87. if ($value instanceof TypedDataInterface) {
  88. $this->contextData = $value;
  89. }
  90. else {
  91. $this->contextData = $this->getTypedDataManager()->create($this->contextDefinition->getDataDefinition(), $value);
  92. }
  93. }
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public function getConstraints() {
  98. return $this->contextDefinition->getConstraints();
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function getContextData() {
  104. if (!isset($this->contextData)) {
  105. $definition = $this->getContextDefinition();
  106. $default_value = $definition->getDefaultValue();
  107. // Store the default value so that subsequent calls don't have to look
  108. // it up again.
  109. $this->contextData = $this->getTypedDataManager()->create($definition->getDataDefinition(), $default_value);
  110. }
  111. return $this->contextData;
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. public function getContextDefinition() {
  117. return $this->contextDefinition;
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function validate() {
  123. return $this->getContextData()->validate();
  124. }
  125. /**
  126. * {@inheritdoc}
  127. */
  128. public function addCacheableDependency($dependency) {
  129. $this->cacheabilityMetadata = $this->cacheabilityMetadata->merge(CacheableMetadata::createFromObject($dependency));
  130. return $this;
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function getCacheContexts() {
  136. return $this->cacheabilityMetadata->getCacheContexts();
  137. }
  138. /**
  139. * {@inheritdoc}
  140. */
  141. public function getCacheTags() {
  142. return $this->cacheabilityMetadata->getCacheTags();
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function getCacheMaxAge() {
  148. return $this->cacheabilityMetadata->getCacheMaxAge();
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public static function createFromContext(ContextInterface $old_context, $value) {
  154. $context = new static($old_context->getContextDefinition(), $value);
  155. $context->addCacheableDependency($old_context);
  156. if (method_exists($old_context, 'getTypedDataManager')) {
  157. $context->setTypedDataManager($old_context->getTypedDataManager());
  158. }
  159. return $context;
  160. }
  161. }