class RecursiveContextualValidator in Zircon Profile 8
Same name in this branch
- 8 vendor/symfony/validator/Validator/RecursiveContextualValidator.php \Symfony\Component\Validator\Validator\RecursiveContextualValidator
- 8 core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php \Drupal\Core\TypedData\Validation\RecursiveContextualValidator
Same name and namespace in other branches
- 8.0 core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php \Drupal\Core\TypedData\Validation\RecursiveContextualValidator
Defines a recursive contextual validator for Typed Data.
For both list and complex data it call recursively out to the properties / elements of the list.
This class calls out to some methods on the execution context marked as internal. These methods are internal to the validator (which is implemented by this class) but should not be called by users. See http://symfony.com/doc/current/contributing/code/bc.html for more information about @internal.
Hierarchy
- class \Drupal\Core\TypedData\Validation\RecursiveContextualValidator implements ContextualValidatorInterface
Expanded class hierarchy of RecursiveContextualValidator
See also
\Drupal\Core\TypedData\Validation\RecursiveValidator::startContext()
\Drupal\Core\TypedData\Validation\RecursiveValidator::inContext()
File
- core/
lib/ Drupal/ Core/ TypedData/ Validation/ RecursiveContextualValidator.php, line 35 - Contains \Drupal\Core\TypedData\Validation\RecursiveContextualValidator.
Namespace
Drupal\Core\TypedData\ValidationView source
class RecursiveContextualValidator implements ContextualValidatorInterface {
/**
* The execution context.
*
* @var \Symfony\Component\Validator\Context\ExecutionContextInterface
*/
protected $context;
/**
* The metadata factory.
*
* @var \Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface
*/
protected $metadataFactory;
/**
* The constraint validator factory.
*
* @var \Symfony\Component\Validator\ConstraintValidatorFactoryInterface
*/
protected $constraintValidatorFactory;
/**
* Creates a validator for the given context.
*
* @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context
* The factory for creating new contexts.
* @param \Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface $metadata_factory
* The metadata factory.
* @param \Symfony\Component\Validator\ConstraintValidatorFactoryInterface $validator_factory
* The constraint validator factory.
* @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
* The typed data manager.
*/
public function __construct(ExecutionContextInterface $context, MetadataFactoryInterface $metadata_factory, ConstraintValidatorFactoryInterface $validator_factory, TypedDataManagerInterface $typed_data_manager) {
$this->context = $context;
$this->metadataFactory = $metadata_factory;
$this->constraintValidatorFactory = $validator_factory;
$this->typedDataManager = $typed_data_manager;
}
/**
* {@inheritdoc}
*/
public function atPath($path) {
// @todo This method is not used at the moment, see
// https://www.drupal.org/node/2482527
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($data, $constraints = NULL, $groups = NULL, $is_root_call = TRUE) {
if (isset($groups)) {
throw new \LogicException('Passing custom groups is not supported.');
}
if (!$data instanceof TypedDataInterface) {
throw new \InvalidArgumentException('The passed value must be a typed data object.');
}
// You can pass a single constraint or an array of constraints.
// Make sure to deal with an array in the rest of the code.
if (isset($constraints) && !is_array($constraints)) {
$constraints = array(
$constraints,
);
}
$this
->validateNode($data, $constraints, $is_root_call);
return $this;
}
/**
* Validates a Typed Data node in the validation tree.
*
* If no constraints are passed, the data is validated against the
* constraints specified in its data definition. If the data is complex or a
* list and no constraints are passed, the contained properties or list items
* are validated recursively.
*
* @param \Drupal\Core\TypedData\TypedDataInterface $data
* The data to validated.
* @param \Symfony\Component\Validator\Constraint[]|null $constraints
* (optional) If set, an array of constraints to validate.
* @param bool $is_root_call
* (optional) Whether its the most upper call in the type data tree.
*
* @return $this
*/
protected function validateNode(TypedDataInterface $data, $constraints = NULL, $is_root_call = FALSE) {
$previous_value = $this->context
->getValue();
$previous_object = $this->context
->getObject();
$previous_metadata = $this->context
->getMetadata();
$previous_path = $this->context
->getPropertyPath();
$metadata = $this->metadataFactory
->getMetadataFor($data);
$cache_key = spl_object_hash($data);
$property_path = $is_root_call ? '' : PropertyPath::append($previous_path, $data
->getName());
// Pass the canonical representation of the data as validated value to
// constraint validators, such that they do not have to care about Typed
// Data.
$value = $this->typedDataManager
->getCanonicalRepresentation($data);
$this->context
->setNode($value, $data, $metadata, $property_path);
if (isset($constraints) || !$this->context
->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP)) {
if (!isset($constraints)) {
$this->context
->markGroupAsValidated($cache_key, Constraint::DEFAULT_GROUP);
$constraints = $metadata
->findConstraints(Constraint::DEFAULT_GROUP);
}
$this
->validateConstraints($value, $cache_key, $constraints);
}
// If the data is a list or complex data, validate the contained list items
// or properties. However, do not recurse if the data is empty.
if (($data instanceof ListInterface || $data instanceof ComplexDataInterface) && !$data
->isEmpty()) {
foreach ($data as $name => $property) {
$this
->validateNode($property);
}
}
$this->context
->setNode($previous_value, $previous_object, $previous_metadata, $previous_path);
return $this;
}
/**
* Validates a node's value against all constraints in the given group.
*
* @param mixed $value
* The validated value.
* @param string $cache_key
* The cache key used internally to ensure we don't validate the same
* constraint twice.
* @param \Symfony\Component\Validator\Constraint[] $constraints
* The constraints which should be ensured for the given value.
*/
protected function validateConstraints($value, $cache_key, $constraints) {
foreach ($constraints as $constraint) {
// Prevent duplicate validation of constraints, in the case
// that constraints belong to multiple validated groups
if (isset($cache_key)) {
$constraint_hash = spl_object_hash($constraint);
if ($this->context
->isConstraintValidated($cache_key, $constraint_hash)) {
continue;
}
$this->context
->markConstraintAsValidated($cache_key, $constraint_hash);
}
$this->context
->setConstraint($constraint);
$validator = $this->constraintValidatorFactory
->getInstance($constraint);
$validator
->initialize($this->context);
$validator
->validate($value, $constraint);
}
}
/**
* {@inheritdoc}
*/
public function getViolations() {
return $this->context
->getViolations();
}
/**
* {@inheritdoc}
*/
public function validateProperty($object, $propertyName, $groups = NULL) {
if (isset($groups)) {
throw new \LogicException('Passing custom groups is not supported.');
}
if (!is_object($object)) {
throw new \InvalidArgumentException('Passing class name is not supported.');
}
elseif (!$object instanceof TypedDataInterface) {
throw new \InvalidArgumentException('The passed in object has to be typed data.');
}
elseif (!$object instanceof ListInterface && !$object instanceof ComplexDataInterface) {
throw new \InvalidArgumentException('Passed data does not contain properties.');
}
return $this
->validateNode($object
->get($propertyName), NULL, TRUE);
}
/**
* {@inheritdoc}
*/
public function validatePropertyValue($object, $property_name, $value, $groups = NULL) {
if (!is_object($object)) {
throw new \InvalidArgumentException('Passing class name is not supported.');
}
elseif (!$object instanceof TypedDataInterface) {
throw new \InvalidArgumentException('The passed in object has to be typed data.');
}
elseif (!$object instanceof ListInterface && !$object instanceof ComplexDataInterface) {
throw new \InvalidArgumentException('Passed data does not contain properties.');
}
$data = $object
->get($property_name);
$metadata = $this->metadataFactory
->getMetadataFor($data);
$constraints = $metadata
->findConstraints(Constraint::DEFAULT_GROUP);
return $this
->validate($value, $constraints, $groups, TRUE);
}
}
Members
Name![]() |
Modifiers | Type | Description | Overrides |
---|---|---|---|---|
RecursiveContextualValidator:: |
protected | property | The constraint validator factory. | |
RecursiveContextualValidator:: |
protected | property | The execution context. | |
RecursiveContextualValidator:: |
protected | property | The metadata factory. | |
RecursiveContextualValidator:: |
public | function |
Appends the given path to the property path of the context. Overrides ContextualValidatorInterface:: |
|
RecursiveContextualValidator:: |
public | function |
Returns the violations that have been generated so far in the context
of the validator. Overrides ContextualValidatorInterface:: |
|
RecursiveContextualValidator:: |
public | function |
Validates a value against a constraint or a list of constraints. Overrides ContextualValidatorInterface:: |
|
RecursiveContextualValidator:: |
protected | function | Validates a node's value against all constraints in the given group. | |
RecursiveContextualValidator:: |
protected | function | Validates a Typed Data node in the validation tree. | |
RecursiveContextualValidator:: |
public | function |
Validates a property of an object against the constraints specified
for this property. Overrides ContextualValidatorInterface:: |
|
RecursiveContextualValidator:: |
public | function |
Validates a value against the constraints specified for an object's
property. Overrides ContextualValidatorInterface:: |
|
RecursiveContextualValidator:: |
public | function | Creates a validator for the given context. |