/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { if (is_object($schema->items)) { // 8.2.3.1. If items is a schema, then the child instance must be // valid against this schema, regardless of its index, and // regardless of the value of "additionalItems". foreach ($instance as $index => $item) { $context->enterNode($index); $walker->applyConstraints($item, $schema->items, $context); $context->leaveNode(); } } else { // "items" is an array $itemSize = count($schema->items); foreach ($instance as $index => $item) { $context->enterNode($index); // 8.2.3.2. If the index is less than, or equal to, the size of // "items", the child instance must be valid against the // corresponding schema in the "items" array; otherwise, it must // be valid against the schema defined by "additionalItems". // // NOTE: this is adapted for 0-based indexation. if ($index < $itemSize) { $walker->applyConstraints($item, $schema->items[$index], $context); } elseif ($schema->additionalItems === false) { $context->addViolation('additional items are not allowed'); } else { $walker->applyConstraints($item, $schema->additionalItems, $context); } $context->leaveNode(); } } }
/** * Validates an instance against a given schema and returns a list * of violations, if any. If the schema contains relative remote * references, its (absolute) URI must be passed as argument. * * @param mixed $instance * @param stdClass $schema * @param string $schemaUri * * @return array */ public function validate($instance, stdClass $schema, $schemaUri = '') { $parseContext = new Context(); $constraintContext = new Context(); // todo: keep ref of already resolved/parsed schemas $schema = $this->walker->resolveReferences($schema, new Uri($schemaUri)); $schema = $this->walker->parseSchema($schema, $parseContext); $this->walker->applyConstraints($instance, $schema, $constraintContext); return $constraintContext->getViolations(); }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { // implementation of the algorithms described in 5.4.4.4 and in 8.3 foreach ($instance as $property => $value) { $schemas = []; if (isset($schema->properties->{$property})) { $schemas[] = $schema->properties->{$property}; } foreach ($schema->patternProperties as $regex => $propertySchema) { if (Utils::matchesRegex($property, $regex)) { $schemas[] = $propertySchema; } } if (empty($schemas)) { if (is_object($schema->additionalProperties)) { $schemas[] = $schema->additionalProperties; } elseif ($schema->additionalProperties === false) { $context->addViolation('additional property "%s" is not allowed', [$property]); } } $context->enterNode($property); foreach ($schemas as $childSchema) { $walker->applyConstraints($value, $childSchema, $context); } $context->leaveNode(); } }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { $accumulatingContext = $context->duplicate(false); $hasMatch = false; $hasDoubleMatch = false; foreach ($schema->oneOf as $subSchema) { $subContext = $context->duplicate(false); $walker->applyConstraints($instance, $subSchema, $subContext); if ($subContext->countViolations() === 0) { if (!$hasMatch) { $hasMatch = true; } else { $hasDoubleMatch = true; break; } } else { $accumulatingContext->mergeViolations($subContext); } } if (!$hasMatch) { $context->mergeViolations($accumulatingContext); } if (!$hasMatch || $hasDoubleMatch) { $context->addViolation('instance must match exactly one of the schemas listed in oneOf'); } }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { $altContext = $context->duplicate(); $walker->applyConstraints($instance, $schema->not, $altContext); if ($altContext->countViolations() === $context->countViolations()) { $context->addViolation('should not match schema in "not"'); } }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { $originalCount = $context->countViolations(); foreach ($schema->allOf as $subSchema) { $walker->applyConstraints($instance, $subSchema, $context); } if ($context->countViolations() > $originalCount) { $context->addViolation('instance must match all the schemas listed in allOf'); } }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { $accumulatingContext = $context->duplicate(); $hasMatch = false; foreach ($schema->anyOf as $subSchema) { $originalCount = $accumulatingContext->countViolations(); $walker->applyConstraints($instance, $subSchema, $accumulatingContext); if ($accumulatingContext->countViolations() === $originalCount) { $hasMatch = true; break; } } if (!$hasMatch) { $context->mergeViolations($accumulatingContext); $context->addViolation('instance must match at least one of the schemas listed in anyOf'); } }
/** * {@inheritdoc} */ public function apply($instance, stdClass $schema, Context $context, Walker $walker) { foreach ($schema->dependencies as $property => $value) { if (property_exists($instance, $property)) { if (is_object($value)) { // Schema dependencies (see §5.4.5.2.1) $walker->applyConstraints($instance, $value, $context); } else { // Property dependencies (see §5.4.5.2.2) foreach ($value as $propertyDependency) { if (!property_exists($instance, $propertyDependency)) { $context->addViolation('dependency property "%s" is missing', [$propertyDependency]); } } } } } }