X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FPlugin%2FContext%2FContextDefinition.php;h=9d8c81f588714182d5cb4de1ea695b73dd7396d8;hb=refs%2Fheads%2Fd864;hp=1c252e2961011c8570a3b77fd25a7e49d8ed1a96;hpb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php index 1c252e296..9d8c81f58 100644 --- a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php +++ b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php @@ -10,14 +10,17 @@ use Drupal\Core\TypedData\TypedDataTrait; */ class ContextDefinition implements ContextDefinitionInterface { - use DependencySerializationTrait; + use DependencySerializationTrait { + __sleep as traitSleep; + __wakeup as traitWakeup; + } use TypedDataTrait; /** * The data type of the data. * - * @return string + * @var string * The data type. */ protected $dataType; @@ -25,7 +28,7 @@ class ContextDefinition implements ContextDefinitionInterface { /** * The human-readable label. * - * @return string + * @var string * The label. */ protected $label; @@ -33,7 +36,7 @@ class ContextDefinition implements ContextDefinitionInterface { /** * The human-readable description. * - * @return string|null + * @var string|null * The description, or NULL if no description is available. */ protected $description; @@ -67,6 +70,38 @@ class ContextDefinition implements ContextDefinitionInterface { */ protected $constraints = []; + /** + * An EntityContextDefinition instance, for backwards compatibility. + * + * If this context is created with a data type that starts with 'entity:', + * this property will be an instance of EntityContextDefinition, and certain + * methods of this object will delegate to their overridden counterparts in + * $this->entityContextDefinition. + * + * This property should be kept private so that it is only accessible to this + * class for backwards compatibility reasons. It will be removed in Drupal 9. + * + * @deprecated + * Constructing a context definition for an entity type (i.e., the data type + * begins with 'entity:') is deprecated in Drupal 8.6.0. Instead, use + * the static factory methods of EntityContextDefinition to create context + * definitions for entity types, or the static ::create() method of this + * class for any other data type. See https://www.drupal.org/node/2976400 + * for more information. + * + * @see ::__construct() + * @see ::__sleep() + * @see ::__wakeup() + * @see ::getConstraintObjects() + * @see ::getSampleValues() + * @see ::initializeEntityContextDefinition() + * @see https://www.drupal.org/node/2932462 + * @see https://www.drupal.org/node/2976400 + * + * @var \Drupal\Core\Plugin\Context\EntityContextDefinition + */ + private $entityContextDefinition; + /** * Creates a new context definition. * @@ -106,6 +141,11 @@ class ContextDefinition implements ContextDefinitionInterface { $this->isMultiple = $multiple; $this->description = $description; $this->defaultValue = $default_value; + + if (strpos($data_type, 'entity:') === 0 && !($this instanceof EntityContextDefinition)) { + @trigger_error('Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use ' . __NAMESPACE__ . '\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.', E_USER_DEPRECATED); + $this->initializeEntityContextDefinition(); + } } /** @@ -202,6 +242,11 @@ class ContextDefinition implements ContextDefinitionInterface { * {@inheritdoc} */ public function getConstraints() { + // If the backwards compatibility layer is present, delegate to that. + if ($this->entityContextDefinition) { + return $this->entityContextDefinition->getConstraints(); + } + // @todo Apply defaults. return $this->constraints; } @@ -210,6 +255,11 @@ class ContextDefinition implements ContextDefinitionInterface { * {@inheritdoc} */ public function getConstraint($constraint_name) { + // If the backwards compatibility layer is present, delegate to that. + if ($this->entityContextDefinition) { + return $this->entityContextDefinition->getConstraint($constraint_name); + } + $constraints = $this->getConstraints(); return isset($constraints[$constraint_name]) ? $constraints[$constraint_name] : NULL; } @@ -218,6 +268,11 @@ class ContextDefinition implements ContextDefinitionInterface { * {@inheritdoc} */ public function setConstraints(array $constraints) { + // If the backwards compatibility layer is present, delegate to that. + if ($this->entityContextDefinition) { + $this->entityContextDefinition->setConstraint(); + } + $this->constraints = $constraints; return $this; } @@ -226,6 +281,11 @@ class ContextDefinition implements ContextDefinitionInterface { * {@inheritdoc} */ public function addConstraint($constraint_name, $options = NULL) { + // If the backwards compatibility layer is present, delegate to that. + if ($this->entityContextDefinition) { + $this->entityContextDefinition->addConstraint($constraint_name, $options); + } + $this->constraints[$constraint_name] = $options; return $this; } @@ -252,4 +312,124 @@ class ContextDefinition implements ContextDefinitionInterface { return $definition; } + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(ContextInterface $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 ($this->getDataType() != 'any' && $definition->getDataType() != $this->getDataType()) { + return FALSE; + } + + // Get the value for this context, either directly if possible or by + // introspecting the definition. + if ($context->hasContextValue()) { + $values = [$context->getContextData()]; + } + elseif ($definition instanceof self) { + if ($this->entityContextDefinition) { + $values = $this->entityContextDefinition->getSampleValues(); + } + else { + $values = $definition->getSampleValues(); + } + } + else { + $values = []; + } + + $validator = $this->getTypedDataManager()->getValidator(); + foreach ($values as $value) { + $constraints = array_values($this->getConstraintObjects()); + $violations = $validator->validate($value, $constraints); + foreach ($violations as $delta => $violation) { + // Remove any violation that does not correspond to the constraints. + if (!in_array($violation->getConstraint(), $constraints)) { + $violations->remove($delta); + } + } + // If a value has no violations then the requirement is satisfied. + if (!$violations->count()) { + return TRUE; + } + } + + return FALSE; + } + + /** + * Returns typed data objects representing this context definition. + * + * This should return as many objects as needed to reflect the variations of + * the constraints it supports. + * + * @yield \Drupal\Core\TypedData\TypedDataInterface + * The set of typed data object. + */ + protected function getSampleValues() { + yield $this->getTypedDataManager()->create($this->getDataDefinition()); + } + + /** + * Extracts an array of constraints for a context definition object. + * + * @return \Symfony\Component\Validator\Constraint[] + * A list of applied constraints for the context definition. + */ + protected function getConstraintObjects() { + // If the backwards compatibility layer is present, delegate to that. + if ($this->entityContextDefinition) { + return $this->entityContextDefinition->getConstraintObjects(); + } + + $constraint_definitions = $this->getConstraints(); + + $validation_constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager(); + $constraints = []; + foreach ($constraint_definitions as $constraint_name => $constraint_definition) { + $constraints[$constraint_name] = $validation_constraint_manager->create($constraint_name, $constraint_definition); + } + + return $constraints; + } + + /** + * Implements magic __sleep() method. + */ + public function __sleep() { + return array_diff($this->traitSleep(), ['entityContextDefinition']); + } + + /** + * Implements magic __wakeup() method. + */ + public function __wakeup() { + $this->traitWakeup(); + + if (strpos($this->getDataType(), 'entity:') === 0) { + $this->initializeEntityContextDefinition(); + } + } + + /** + * Initializes $this->entityContextDefinition for backwards compatibility. + * + * This method should be kept private so that it is only accessible to this + * class for backwards compatibility reasons. It will be removed in Drupal 9. + * + * @deprecated + */ + private function initializeEntityContextDefinition() { + $this->entityContextDefinition = EntityContextDefinition::create() + ->setDataType($this->getDataType()) + ->setLabel($this->getLabel()) + ->setRequired($this->isRequired()) + ->setMultiple($this->isMultiple()) + ->setDescription($this->getDescription()) + ->setConstraints($this->getConstraints()) + ->setDefaultValue($this->getDefaultValue()); + } + }