X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FPlugin%2FContext%2FContextDefinition.php;fp=web%2Fcore%2Flib%2FDrupal%2FCore%2FPlugin%2FContext%2FContextDefinition.php;h=9d8c81f588714182d5cb4de1ea695b73dd7396d8;hp=55336d55c98cb30db0ec2fb0a9b08c802bc6a8f4;hb=0bf8d09d2542548982e81a441b1f16e75873a04f;hpb=74df008bdbb3a11eeea356744f39b802369bda3c diff --git a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php index 55336d55c..9d8c81f58 100644 --- a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php +++ b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php @@ -3,11 +3,6 @@ namespace Drupal\Core\Plugin\Context; use Drupal\Core\DependencyInjection\DependencySerializationTrait; -use Drupal\Core\Entity\ContentEntityStorageInterface; -use Drupal\Core\Entity\Plugin\DataType\EntityAdapter; -use Drupal\Core\Entity\Plugin\Validation\Constraint\BundleConstraint; -use Drupal\Core\Entity\Plugin\Validation\Constraint\EntityTypeConstraint; -use Drupal\Core\Entity\TypedData\EntityDataDefinition; use Drupal\Core\TypedData\TypedDataTrait; /** @@ -15,7 +10,10 @@ use Drupal\Core\TypedData\TypedDataTrait; */ class ContextDefinition implements ContextDefinitionInterface { - use DependencySerializationTrait; + use DependencySerializationTrait { + __sleep as traitSleep; + __wakeup as traitWakeup; + } use TypedDataTrait; @@ -72,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. * @@ -111,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(); + } } /** @@ -207,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; } @@ -215,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; } @@ -223,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; } @@ -231,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; } @@ -273,8 +328,13 @@ class ContextDefinition implements ContextDefinitionInterface { if ($context->hasContextValue()) { $values = [$context->getContextData()]; } - elseif ($definition instanceof static) { - $values = $definition->getSampleValues(); + elseif ($definition instanceof self) { + if ($this->entityContextDefinition) { + $values = $this->entityContextDefinition->getSampleValues(); + } + else { + $values = $definition->getSampleValues(); + } } else { $values = []; @@ -282,7 +342,14 @@ class ContextDefinition implements ContextDefinitionInterface { $validator = $this->getTypedDataManager()->getValidator(); foreach ($values as $value) { - $violations = $validator->validate($value, array_values($this->getConstraintObjects())); + $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; @@ -302,33 +369,6 @@ class ContextDefinition implements ContextDefinitionInterface { * The set of typed data object. */ protected function getSampleValues() { - // @todo Move the entity specific logic out of this class in - // https://www.drupal.org/node/2932462. - // Get the constraints from the context's definition. - $constraints = $this->getConstraintObjects(); - // If constraints include EntityType, we generate an entity or adapter. - if (!empty($constraints['EntityType']) && $constraints['EntityType'] instanceof EntityTypeConstraint) { - $entity_type_manager = \Drupal::entityTypeManager(); - $entity_type_id = $constraints['EntityType']->type; - $storage = $entity_type_manager->getStorage($entity_type_id); - // If the storage can generate a sample entity we might delegate to that. - if ($storage instanceof ContentEntityStorageInterface) { - if (!empty($constraints['Bundle']) && $constraints['Bundle'] instanceof BundleConstraint) { - foreach ($constraints['Bundle']->bundle as $bundle) { - // We have a bundle, we are bundleable and we can generate a sample. - yield EntityAdapter::createFromEntity($storage->createWithSampleValues($bundle)); - } - return; - } - } - - // Either no bundle, or not bundleable, so generate an entity adapter. - $definition = EntityDataDefinition::create($entity_type_id); - yield new EntityAdapter($definition); - return; - } - - // No entity related constraints, so generate a basic typed data object. yield $this->getTypedDataManager()->create($this->getDataDefinition()); } @@ -339,16 +379,13 @@ class ContextDefinition implements ContextDefinitionInterface { * A list of applied constraints for the context definition. */ protected function getConstraintObjects() { - $constraint_definitions = $this->getConstraints(); - - // @todo Move the entity specific logic out of this class in - // https://www.drupal.org/node/2932462. - // If the data type is an entity, manually add one to the constraints array. - if (strpos($this->getDataType(), 'entity:') === 0) { - $entity_type_id = substr($this->getDataType(), 7); - $constraint_definitions['EntityType'] = ['type' => $entity_type_id]; + // 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) { @@ -358,4 +395,41 @@ class ContextDefinition implements ContextDefinitionInterface { 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()); + } + }