summaryrefslogtreecommitdiff
path: root/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints
diff options
context:
space:
mode:
authorEole <josselin.35@live.fr>2016-01-21 10:29:26 +0100
committerEole <josselin.35@live.fr>2016-01-21 10:29:26 +0100
commita44cc1d2e3c0f147e91a5c052ac7fd879e34e706 (patch)
treebdd6f72e0ba732c4fcc0479d1cfcf4d0baa5885d /server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints
parent35db27b0e62b4cdcb03b0d21bceb4efc769e6161 (diff)
Init Server Composer Components
Diffstat (limited to 'server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints')
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php112
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php291
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php60
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php46
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php81
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php181
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php83
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php149
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php37
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php57
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php145
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php307
12 files changed, 1549 insertions, 0 deletions
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
new file mode 100644
index 0000000..b43bace
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The CollectionConstraint Constraints, validates an array against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class CollectionConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value, $schema = null, $path = null, $i = null)
+ {
+ // Verify minItems
+ if (isset($schema->minItems) && count($value) < $schema->minItems) {
+ $this->addError($path, "There must be a minimum of " . $schema->minItems . " items in the array", 'minItems', array('minItems' => $schema->minItems,));
+ }
+
+ // Verify maxItems
+ if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
+ $this->addError($path, "There must be a maximum of " . $schema->maxItems . " items in the array", 'maxItems', array('maxItems' => $schema->maxItems,));
+ }
+
+ // Verify uniqueItems
+ if (isset($schema->uniqueItems) && $schema->uniqueItems) {
+ $unique = $value;
+ if (is_array($value) && count($value)) {
+ $unique = array_map(function($e) { return var_export($e, true); }, $value);
+ }
+ if (count(array_unique($unique)) != count($value)) {
+ $this->addError($path, "There are no duplicates allowed in the array", 'uniqueItems');
+ }
+ }
+
+ // Verify items
+ if (isset($schema->items)) {
+ $this->validateItems($value, $schema, $path, $i);
+ }
+ }
+
+ /**
+ * Validates the items
+ *
+ * @param array $value
+ * @param \stdClass $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateItems($value, $schema = null, $path = null, $i = null)
+ {
+ if (is_object($schema->items)) {
+ // just one type definition for the whole array
+ foreach ($value as $k => $v) {
+ $initErrors = $this->getErrors();
+
+ // First check if its defined in "items"
+ $this->checkUndefined($v, $schema->items, $path, $k);
+
+ // Recheck with "additionalItems" if the first test fails
+ if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
+ $secondErrors = $this->getErrors();
+ $this->checkUndefined($v, $schema->additionalItems, $path, $k);
+ }
+
+ // Reset errors if needed
+ if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
+ $this->errors = $secondErrors;
+ } else if (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
+ $this->errors = $initErrors;
+ }
+ }
+ } else {
+ // Defined item type definitions
+ foreach ($value as $k => $v) {
+ if (array_key_exists($k, $schema->items)) {
+ $this->checkUndefined($v, $schema->items[$k], $path, $k);
+ } else {
+ // Additional items
+ if (property_exists($schema, 'additionalItems')) {
+ if ($schema->additionalItems !== false) {
+ $this->checkUndefined($v, $schema->additionalItems, $path, $k);
+ } else {
+ $this->addError(
+ $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems,));
+ }
+ } else {
+ // Should be valid against an empty schema
+ $this->checkUndefined($v, new \stdClass(), $path, $k);
+ }
+ }
+ }
+
+ // Treat when we have more schema definitions than values, not for empty arrays
+ if(count($value) > 0) {
+ for ($k = count($value); $k < count($schema->items); $k++) {
+ $this->checkUndefined(new UndefinedConstraint(), $schema->items[$k], $path, $k);
+ }
+ }
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
new file mode 100644
index 0000000..cb3ee80
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
@@ -0,0 +1,291 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Uri\UriRetriever;
+
+/**
+ * The Base Constraints, all Validators should extend this class
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+abstract class Constraint implements ConstraintInterface
+{
+ protected $checkMode = self::CHECK_MODE_NORMAL;
+ protected $uriRetriever;
+ protected $errors = array();
+ protected $inlineSchemaProperty = '$schema';
+
+ const CHECK_MODE_NORMAL = 1;
+ const CHECK_MODE_TYPE_CAST = 2;
+
+ /**
+ * @var null|Factory
+ */
+ private $factory;
+
+ /**
+ * @param int $checkMode
+ * @param UriRetriever $uriRetriever
+ * @param Factory $factory
+ */
+ public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $uriRetriever = null, Factory $factory = null)
+ {
+ $this->checkMode = $checkMode;
+ $this->uriRetriever = $uriRetriever;
+ $this->factory = $factory;
+ }
+
+ /**
+ * @return UriRetriever $uriRetriever
+ */
+ public function getUriRetriever()
+ {
+ if (is_null($this->uriRetriever))
+ {
+ $this->setUriRetriever(new UriRetriever);
+ }
+
+ return $this->uriRetriever;
+ }
+
+ /**
+ * @return Factory
+ */
+ public function getFactory()
+ {
+ if (!$this->factory) {
+ $this->factory = new Factory($this->getUriRetriever());
+ }
+
+ return $this->factory;
+ }
+
+ /**
+ * @param UriRetriever $uriRetriever
+ */
+ public function setUriRetriever(UriRetriever $uriRetriever)
+ {
+ $this->uriRetriever = $uriRetriever;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function addError($path, $message, $constraint='', array $more=null)
+ {
+ $error = array(
+ 'property' => $path,
+ 'message' => $message,
+ 'constraint' => $constraint,
+ );
+
+ if (is_array($more) && count($more) > 0)
+ {
+ $error += $more;
+ }
+
+ $this->errors[] = $error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function addErrors(array $errors)
+ {
+ $this->errors = array_merge($this->errors, $errors);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function isValid()
+ {
+ return !$this->getErrors();
+ }
+
+ /**
+ * Clears any reported errors. Should be used between
+ * multiple validation checks.
+ */
+ public function reset()
+ {
+ $this->errors = array();
+ }
+
+ /**
+ * Bubble down the path
+ *
+ * @param string $path Current path
+ * @param mixed $i What to append to the path
+ *
+ * @return string
+ */
+ protected function incrementPath($path, $i)
+ {
+ if ($path !== '') {
+ if (is_int($i)) {
+ $path .= '[' . $i . ']';
+ } elseif ($i == '') {
+ $path .= '';
+ } else {
+ $path .= '.' . $i;
+ }
+ } else {
+ $path = $i;
+ }
+
+ return $path;
+ }
+
+ /**
+ * Validates an array
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkArray($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('collection');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Validates an object
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ * @param mixed $patternProperties
+ */
+ protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('object');
+ $validator->check($value, $schema, $path, $i, $patternProperties);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Validates the type of a property
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkType($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('type');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a undefined element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkUndefined($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('undefined');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a string element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkString($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('string');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a number element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkNumber($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('number');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a enum element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkEnum($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('enum');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ protected function checkFormat($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('format');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * @param string $uri JSON Schema URI
+ * @return string JSON Schema contents
+ */
+ protected function retrieveUri($uri)
+ {
+ if (null === $this->uriRetriever) {
+ $this->setUriRetriever(new UriRetriever);
+ }
+ $jsonSchema = $this->uriRetriever->retrieve($uri);
+ // TODO validate using schema
+ return $jsonSchema;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
new file mode 100644
index 0000000..34280f4
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The Constraints Interface
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ */
+interface ConstraintInterface
+{
+ /**
+ * returns all collected errors
+ *
+ * @return array
+ */
+ public function getErrors();
+
+ /**
+ * adds errors to this validator
+ *
+ * @param array $errors
+ */
+ public function addErrors(array $errors);
+
+ /**
+ * adds an error
+ *
+ * @param string $path
+ * @param string $message
+ * @param string $constraint the constraint/rule that is broken, e.g.: 'minLength'
+ * @param array $more more array elements to add to the error
+ */
+ public function addError($path, $message, $constraint='', array $more=null);
+
+ /**
+ * checks if the validator has not raised errors
+ *
+ * @return boolean
+ */
+ public function isValid();
+
+ /**
+ * invokes the validation of an element
+ *
+ * @abstract
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ public function check($value, $schema = null, $path = null, $i = null);
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
new file mode 100644
index 0000000..df413e4
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The EnumConstraint Constraints, validates an element against a given set of possibilities
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class EnumConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Only validate enum if the attribute exists
+ if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
+ return;
+ }
+
+ foreach ($schema->enum as $enum) {
+ $type = gettype($element);
+ if ($type === gettype($enum)) {
+ if ($type == "object") {
+ if ($element == $enum)
+ return;
+ } else {
+ if ($element === $enum)
+ return;
+
+ }
+ }
+ }
+
+ $this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true), 'enum', array('enum' => $schema->enum,));
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
new file mode 100644
index 0000000..a4570f6
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Uri\UriRetriever;
+use JsonSchema\Validator;
+
+/**
+ * Factory for centralize constraint initialization.
+ */
+class Factory
+{
+ /**
+ * @var UriRetriever
+ */
+ protected $uriRetriever;
+
+ /**
+ * @param UriRetriever $uriRetriever
+ */
+ public function __construct(UriRetriever $uriRetriever = null)
+ {
+ if (!$uriRetriever) {
+ $uriRetriever = new UriRetriever();
+ }
+
+ $this->uriRetriever = $uriRetriever;
+ }
+
+ /**
+ * @return UriRetriever
+ */
+ public function getUriRetriever()
+ {
+ return $this->uriRetriever;
+ }
+
+ /**
+ * Create a constraint instance for the given constraint name.
+ *
+ * @param string $constraintName
+ * @return ConstraintInterface|ObjectConstraint
+ * @throws InvalidArgumentException if is not possible create the constraint instance.
+ */
+ public function createInstanceFor($constraintName)
+ {
+ switch ($constraintName) {
+ case 'array':
+ case 'collection':
+ return new CollectionConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'object':
+ return new ObjectConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'type':
+ return new TypeConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'undefined':
+ return new UndefinedConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'string':
+ return new StringConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'number':
+ return new NumberConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'enum':
+ return new EnumConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'format':
+ return new FormatConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'schema':
+ return new SchemaConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'validator':
+ return new Validator(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ }
+
+ throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
new file mode 100644
index 0000000..c789753
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * Validates against the "format" property
+ *
+ * @author Justin Rainbow <justin.rainbow@gmail.com>
+ * @link http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23
+ */
+class FormatConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ if (!isset($schema->format)) {
+ return;
+ }
+
+ switch ($schema->format) {
+ case 'date':
+ if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
+ $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'time':
+ if (!$this->validateDateTime($element, 'H:i:s')) {
+ $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'date-time':
+ if (!$this->validateDateTime($element, 'Y-m-d\TH:i:s\Z') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:s.u\Z') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:sP') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:sO')
+ ) {
+ $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'utc-millisec':
+ if (!$this->validateDateTime($element, 'U')) {
+ $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'regex':
+ if (!$this->validateRegex($element)) {
+ $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'color':
+ if (!$this->validateColor($element)) {
+ $this->addError($path, "Invalid color", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'style':
+ if (!$this->validateStyle($element)) {
+ $this->addError($path, "Invalid style", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'phone':
+ if (!$this->validatePhone($element)) {
+ $this->addError($path, "Invalid phone number", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'uri':
+ if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
+ $this->addError($path, "Invalid URL format", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'email':
+ if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) {
+ $this->addError($path, "Invalid email", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'ip-address':
+ case 'ipv4':
+ if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
+ $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'ipv6':
+ if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
+ $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'host-name':
+ case 'hostname':
+ if (!$this->validateHostname($element)) {
+ $this->addError($path, "Invalid hostname", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ default:
+ // Empty as it should be:
+ // The value of this keyword is called a format attribute. It MUST be a string.
+ // A format attribute can generally only validate a given set of instance types.
+ // If the type of the instance to validate is not in this set, validation for
+ // this format attribute and instance SHOULD succeed.
+ // http://json-schema.org/latest/json-schema-validation.html#anchor105
+ break;
+ }
+ }
+
+ protected function validateDateTime($datetime, $format)
+ {
+ $dt = \DateTime::createFromFormat($format, $datetime);
+
+ if (!$dt) {
+ return false;
+ }
+
+ if ($datetime === $dt->format($format)) {
+ return true;
+ }
+
+ // handles the case where a non-6 digit microsecond datetime is passed
+ // which will fail the above string comparison because the passed
+ // $datetime may be '2000-05-01T12:12:12.123Z' but format() will return
+ // '2000-05-01T12:12:12.123000Z'
+ if ((strpos('u', $format) !== -1) && (intval($dt->format('u')) > 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function validateRegex($regex)
+ {
+ return false !== @preg_match('/' . $regex . '/', '');
+ }
+
+ protected function validateColor($color)
+ {
+ if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
+ 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
+ 'red', 'silver', 'teal', 'white', 'yellow'))) {
+ return true;
+ }
+
+ return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
+ }
+
+ protected function validateStyle($style)
+ {
+ $properties = explode(';', rtrim($style, ';'));
+ $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
+
+ return empty($invalidEntries);
+ }
+
+ protected function validatePhone($phone)
+ {
+ return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
+ }
+
+ protected function validateHostname($host)
+ {
+ return preg_match('/^[_a-z]+\.([_a-z]+\.?)+$/i', $host);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
new file mode 100644
index 0000000..0a34bdc
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The NumberConstraint Constraints, validates an number against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class NumberConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Verify minimum
+ if (isset($schema->exclusiveMinimum)) {
+ if (isset($schema->minimum)) {
+ if ($schema->exclusiveMinimum && $element === $schema->minimum) {
+ $this->addError($path, "Must have a minimum value greater than boundary value of " . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum,));
+ } else if ($element < $schema->minimum) {
+ $this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
+ }
+ } else {
+ $this->addError($path, "Use of exclusiveMinimum requires presence of minimum", 'missingMinimum');
+ }
+ } else if (isset($schema->minimum) && $element < $schema->minimum) {
+ $this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
+ }
+
+ // Verify maximum
+ if (isset($schema->exclusiveMaximum)) {
+ if (isset($schema->maximum)) {
+ if ($schema->exclusiveMaximum && $element === $schema->maximum) {
+ $this->addError($path, "Must have a maximum value less than boundary value of " . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum,));
+ } else if ($element > $schema->maximum) {
+ $this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
+ }
+ } else {
+ $this->addError($path, "Use of exclusiveMaximum requires presence of maximum", 'missingMinimum');
+ }
+ } else if (isset($schema->maximum) && $element > $schema->maximum) {
+ $this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
+ }
+
+ // Verify divisibleBy - Draft v3
+ if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
+ $this->addError($path, "Is not divisible by " . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy,));
+ }
+
+ // Verify multipleOf - Draft v4
+ if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
+ $this->addError($path, "Must be a multiple of " . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf,));
+ }
+
+ $this->checkFormat($element, $schema, $path, $i);
+ }
+
+ private function fmod($number1, $number2)
+ {
+ $modulus = fmod($number1, $number2);
+ $precision = abs(0.0000000001);
+ $diff = (float)($modulus - $number2);
+
+ if (-$precision < $diff && $diff < $precision) {
+ return 0.0;
+ }
+
+ $decimals1 = mb_strpos($number1, ".") ? mb_strlen($number1) - mb_strpos($number1, ".") - 1 : 0;
+ $decimals2 = mb_strpos($number2, ".") ? mb_strlen($number2) - mb_strpos($number2, ".") - 1 : 0;
+
+ return (float)round($modulus, max($decimals1, $decimals2));
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
new file mode 100644
index 0000000..0e5cf1b
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The ObjectConstraint Constraints, validates an object against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class ObjectConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
+ {
+ if ($element instanceof UndefinedConstraint) {
+ return;
+ }
+
+ $matches = array();
+ if ($patternProperties) {
+ $matches = $this->validatePatternProperties($element, $path, $patternProperties);
+ }
+
+ if ($definition) {
+ // validate the definition properties
+ $this->validateDefinition($element, $definition, $path);
+ }
+
+ // additional the element properties
+ $this->validateElement($element, $matches, $definition, $path, $additionalProp);
+ }
+
+ public function validatePatternProperties($element, $path, $patternProperties)
+ {
+ $try = array('/','#','+','~','%');
+ $matches = array();
+ foreach ($patternProperties as $pregex => $schema) {
+ $delimiter = '/';
+ // Choose delimiter. Necessary for patterns like ^/ , otherwise you get error
+ foreach ($try as $delimiter) {
+ if (strpos($pregex, $delimiter) === false) { // safe to use
+ break;
+ }
+ }
+
+ // Validate the pattern before using it to test for matches
+ if (@preg_match($delimiter. $pregex . $delimiter, '') === false) {
+ $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex,));
+ continue;
+ }
+ foreach ($element as $i => $value) {
+ if (preg_match($delimiter . $pregex . $delimiter, $i)) {
+ $matches[] = $i;
+ $this->checkUndefined($value, $schema ? : new \stdClass(), $path, $i);
+ }
+ }
+ }
+ return $matches;
+ }
+
+ /**
+ * Validates the element properties
+ *
+ * @param \stdClass $element Element to validate
+ * @param array $matches Matches from patternProperties (if any)
+ * @param \stdClass $objectDefinition ObjectConstraint definition
+ * @param string $path Path to test?
+ * @param mixed $additionalProp Additional properties
+ */
+ public function validateElement($element, $matches, $objectDefinition = null, $path = null, $additionalProp = null)
+ {
+ foreach ($element as $i => $value) {
+
+ $property = $this->getProperty($element, $i, new UndefinedConstraint());
+ $definition = $this->getProperty($objectDefinition, $i);
+
+ // no additional properties allowed
+ if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
+ $this->addError($path, "The property " . $i . " is not defined and the definition does not allow additional properties", 'additionalProp');
+ }
+
+ // additional properties defined
+ if (!in_array($i, $matches) && $additionalProp && !$definition) {
+ if ($additionalProp === true) {
+ $this->checkUndefined($value, null, $path, $i);
+ } else {
+ $this->checkUndefined($value, $additionalProp, $path, $i);
+ }
+ }
+
+ // property requires presence of another
+ $require = $this->getProperty($definition, 'requires');
+ if ($require && !$this->getProperty($element, $require)) {
+ $this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires');
+ }
+
+ if (!$definition) {
+ // normal property verification
+ $this->checkUndefined($value, new \stdClass(), $path, $i);
+ }
+ }
+ }
+
+ /**
+ * Validates the definition properties
+ *
+ * @param \stdClass $element Element to validate
+ * @param \stdClass $objectDefinition ObjectConstraint definition
+ * @param string $path Path?
+ */
+ public function validateDefinition($element, $objectDefinition = null, $path = null)
+ {
+ foreach ($objectDefinition as $i => $value) {
+ $property = $this->getProperty($element, $i, new UndefinedConstraint());
+ $definition = $this->getProperty($objectDefinition, $i);
+ $this->checkUndefined($property, $definition, $path, $i);
+ }
+ }
+
+ /**
+ * retrieves a property from an object or array
+ *
+ * @param mixed $element Element to validate
+ * @param string $property Property to retrieve
+ * @param mixed $fallback Default value if property is not found
+ *
+ * @return mixed
+ */
+ protected function getProperty($element, $property, $fallback = null)
+ {
+ if (is_array($element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) {
+ return array_key_exists($property, $element) ? $element[$property] : $fallback;
+ } elseif (is_object($element)) {
+ return property_exists($element, $property) ? $element->$property : $fallback;
+ }
+
+ return $fallback;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
new file mode 100644
index 0000000..b856a11
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+
+/**
+ * The SchemaConstraint Constraints, validates an element against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class SchemaConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ if ($schema !== null) {
+ // passed schema
+ $this->checkUndefined($element, $schema, '', '');
+ } elseif (property_exists($element, $this->inlineSchemaProperty)) {
+ // inline schema
+ $this->checkUndefined($element, $element->{$this->inlineSchemaProperty}, '', '');
+ } else {
+ throw new InvalidArgumentException('no schema found to verify against');
+ }
+ }
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
new file mode 100644
index 0000000..f57f64c
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The StringConstraint Constraints, validates an string against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class StringConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Verify maxLength
+ if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
+ $this->addError($path, "Must be at most " . $schema->maxLength . " characters long", 'maxLength', array(
+ 'maxLength' => $schema->maxLength,
+ ));
+ }
+
+ //verify minLength
+ if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
+ $this->addError($path, "Must be at least " . $schema->minLength . " characters long", 'minLength', array(
+ 'minLength' => $schema->minLength,
+ ));
+ }
+
+ // Verify a regex pattern
+ if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#', $element)) {
+ $this->addError($path, "Does not match the regex pattern " . $schema->pattern, 'pattern', array(
+ 'pattern' => $schema->pattern,
+ ));
+ }
+
+ $this->checkFormat($element, $schema, $path, $i);
+ }
+
+ private function strlen($string)
+ {
+ if (extension_loaded('mbstring')) {
+ return mb_strlen($string, mb_detect_encoding($string));
+ } else {
+ return strlen($string);
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
new file mode 100644
index 0000000..837cfd8
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
@@ -0,0 +1,145 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use UnexpectedValueException as StandardUnexpectedValueException;
+
+/**
+ * The TypeConstraint Constraints, validates an element against a given type
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class TypeConstraint extends Constraint
+{
+ /**
+ * @var array|string[] type wordings for validation error messages
+ */
+ static $wording = array(
+ 'integer' => 'an integer',
+ 'number' => 'a number',
+ 'boolean' => 'a boolean',
+ 'object' => 'an object',
+ 'array' => 'an array',
+ 'string' => 'a string',
+ 'null' => 'a null',
+ 'any' => NULL, // validation of 'any' is always true so is not needed in message wording
+ 0 => NULL, // validation of a false-y value is always true, so not needed as well
+ );
+
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value = null, $schema = null, $path = null, $i = null)
+ {
+ $type = isset($schema->type) ? $schema->type : null;
+ $isValid = true;
+
+ if (is_array($type)) {
+ // @TODO refactor
+ $validatedOneType = false;
+ $errors = array();
+ foreach ($type as $tp) {
+ $validator = new TypeConstraint($this->checkMode);
+ $subSchema = new \stdClass();
+ $subSchema->type = $tp;
+ $validator->check($value, $subSchema, $path, null);
+ $error = $validator->getErrors();
+
+ if (!count($error)) {
+ $validatedOneType = true;
+ break;
+ }
+
+ $errors = $error;
+ }
+
+ if (!$validatedOneType) {
+ $this->addErrors($errors);
+
+ return;
+ }
+ } elseif (is_object($type)) {
+ $this->checkUndefined($value, $type, $path);
+ } else {
+ $isValid = $this->validateType($value, $type);
+ }
+
+ if ($isValid === false) {
+ if (!isset(self::$wording[$type])) {
+ throw new StandardUnexpectedValueException(
+ sprintf(
+ "No wording for %s available, expected wordings are: [%s]",
+ var_export($type, true),
+ implode(', ', array_filter(self::$wording)))
+ );
+ }
+ $this->addError($path, ucwords(gettype($value)) . " value found, but " . self::$wording[$type] . " is required", 'type');
+ }
+ }
+
+ /**
+ * Verifies that a given value is of a certain type
+ *
+ * @param mixed $value Value to validate
+ * @param string $type TypeConstraint to check against
+ *
+ * @return boolean
+ *
+ * @throws InvalidArgumentException
+ */
+ protected function validateType($value, $type)
+ {
+ //mostly the case for inline schema
+ if (!$type) {
+ return true;
+ }
+
+ if ('integer' === $type) {
+ return is_int($value);
+ }
+
+ if ('number' === $type) {
+ return is_numeric($value) && !is_string($value);
+ }
+
+ if ('boolean' === $type) {
+ return is_bool($value);
+ }
+
+ if ('object' === $type) {
+ return is_object($value);
+ //return ($this::CHECK_MODE_TYPE_CAST == $this->checkMode) ? is_array($value) : is_object($value);
+ }
+
+ if ('array' === $type) {
+ return is_array($value);
+ }
+
+ if ('string' === $type) {
+ return is_string($value);
+ }
+
+ if ('email' === $type) {
+ return is_string($value);
+ }
+
+ if ('null' === $type) {
+ return is_null($value);
+ }
+
+ if ('any' === $type) {
+ return true;
+ }
+
+ throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
new file mode 100644
index 0000000..c033720
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
@@ -0,0 +1,307 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Uri\UriResolver;
+
+/**
+ * The UndefinedConstraint Constraints
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class UndefinedConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value, $schema = null, $path = null, $i = null)
+ {
+ if (is_null($schema)) {
+ return;
+ }
+
+ if (!is_object($schema)) {
+ throw new InvalidArgumentException(
+ 'Given schema must be an object in ' . $path
+ . ' but is a ' . gettype($schema)
+ );
+ }
+
+ $i = is_null($i) ? "" : $i;
+ $path = $this->incrementPath($path, $i);
+
+ // check special properties
+ $this->validateCommonProperties($value, $schema, $path);
+
+ // check allOf, anyOf, and oneOf properties
+ $this->validateOfProperties($value, $schema, $path);
+
+ // check known types
+ $this->validateTypes($value, $schema, $path, $i);
+ }
+
+ /**
+ * Validates the value against the types
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ public function validateTypes($value, $schema = null, $path = null, $i = null)
+ {
+ // check array
+ if (is_array($value)) {
+ $this->checkArray($value, $schema, $path, $i);
+ }
+
+ // check object
+ if (is_object($value) && (isset($schema->properties) || isset($schema->patternProperties) || isset($schema->additionalProperties))) {
+ $this->checkObject(
+ $value,
+ isset($schema->properties) ? $schema->properties : null,
+ $path,
+ isset($schema->additionalProperties) ? $schema->additionalProperties : null,
+ isset($schema->patternProperties) ? $schema->patternProperties : null
+ );
+ }
+
+ // check string
+ if (is_string($value)) {
+ $this->checkString($value, $schema, $path, $i);
+ }
+
+ // check numeric
+ if (is_numeric($value)) {
+ $this->checkNumber($value, $schema, $path, $i);
+ }
+
+ // check enum
+ if (isset($schema->enum)) {
+ $this->checkEnum($value, $schema, $path, $i);
+ }
+ }
+
+ /**
+ * Validates common properties
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateCommonProperties($value, $schema = null, $path = null, $i = "")
+ {
+ // if it extends another schema, it must pass that schema as well
+ if (isset($schema->extends)) {
+ if (is_string($schema->extends)) {
+ $schema->extends = $this->validateUri($schema, $schema->extends);
+ }
+ if (is_array($schema->extends)) {
+ foreach ($schema->extends as $extends) {
+ $this->checkUndefined($value, $extends, $path, $i);
+ }
+ } else {
+ $this->checkUndefined($value, $schema->extends, $path, $i);
+ }
+ }
+
+ // Verify required values
+ if (is_object($value)) {
+ if (!($value instanceof UndefinedConstraint) && isset($schema->required) && is_array($schema->required) ) {
+ // Draft 4 - Required is an array of strings - e.g. "required": ["foo", ...]
+ foreach ($schema->required as $required) {
+ if (!property_exists($value, $required)) {
+ $this->addError((!$path) ? $required : "$path.$required", "The property " . $required . " is required", 'required');
+ }
+ }
+ } else if (isset($schema->required) && !is_array($schema->required)) {
+ // Draft 3 - Required attribute - e.g. "foo": {"type": "string", "required": true}
+ if ( $schema->required && $value instanceof UndefinedConstraint) {
+ $this->addError($path, "Is missing and it is required", 'required');
+ }
+ }
+ }
+
+ // Verify type
+ if (!($value instanceof UndefinedConstraint)) {
+ $this->checkType($value, $schema, $path);
+ }
+
+ // Verify disallowed items
+ if (isset($schema->disallow)) {
+ $initErrors = $this->getErrors();
+
+ $typeSchema = new \stdClass();
+ $typeSchema->type = $schema->disallow;
+ $this->checkType($value, $typeSchema, $path);
+
+ // if no new errors were raised it must be a disallowed value
+ if (count($this->getErrors()) == count($initErrors)) {
+ $this->addError($path, "Disallowed value was matched", 'disallow');
+ } else {
+ $this->errors = $initErrors;
+ }
+ }
+
+ if (isset($schema->not)) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $schema->not, $path, $i);
+
+ // if no new errors were raised then the instance validated against the "not" schema
+ if (count($this->getErrors()) == count($initErrors)) {
+ $this->addError($path, "Matched a schema which it should not", 'not');
+ } else {
+ $this->errors = $initErrors;
+ }
+ }
+
+ // Verify minimum and maximum number of properties
+ if (is_object($value)) {
+ if (isset($schema->minProperties)) {
+ if (count(get_object_vars($value)) < $schema->minProperties) {
+ $this->addError($path, "Must contain a minimum of " . $schema->minProperties . " properties", 'minProperties', array('minProperties' => $schema->minProperties,));
+ }
+ }
+ if (isset($schema->maxProperties)) {
+ if (count(get_object_vars($value)) > $schema->maxProperties) {
+ $this->addError($path, "Must contain no more than " . $schema->maxProperties . " properties", 'maxProperties', array('maxProperties' => $schema->maxProperties,));
+ }
+ }
+ }
+
+ // Verify that dependencies are met
+ if (is_object($value) && isset($schema->dependencies)) {
+ $this->validateDependencies($value, $schema->dependencies, $path);
+ }
+ }
+
+ /**
+ * Validate allOf, anyOf, and oneOf properties
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateOfProperties($value, $schema, $path, $i = "")
+ {
+ // Verify type
+ if ($value instanceof UndefinedConstraint) {
+ return;
+ }
+
+ if (isset($schema->allOf)) {
+ $isValid = true;
+ foreach ($schema->allOf as $allOf) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $allOf, $path, $i);
+ $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
+ }
+ if (!$isValid) {
+ $this->addError($path, "Failed to match all schemas", 'allOf');
+ }
+ }
+
+ if (isset($schema->anyOf)) {
+ $isValid = false;
+ $startErrors = $this->getErrors();
+ foreach ($schema->anyOf as $anyOf) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $anyOf, $path, $i);
+ if ($isValid = (count($this->getErrors()) == count($initErrors))) {
+ break;
+ }
+ }
+ if (!$isValid) {
+ $this->addError($path, "Failed to match at least one schema", 'anyOf');
+ } else {
+ $this->errors = $startErrors;
+ }
+ }
+
+ if (isset($schema->oneOf)) {
+ $allErrors = array();
+ $matchedSchemas = 0;
+ $startErrors = $this->getErrors();
+ foreach ($schema->oneOf as $oneOf) {
+ $this->errors = array();
+ $this->checkUndefined($value, $oneOf, $path, $i);
+ if (count($this->getErrors()) == 0) {
+ $matchedSchemas++;
+ }
+ $allErrors = array_merge($allErrors, array_values($this->getErrors()));
+ }
+ if ($matchedSchemas !== 1) {
+ $this->addErrors(
+ array_merge(
+ $allErrors,
+ array(array(
+ 'property' => $path,
+ 'message' => "Failed to match exactly one schema",
+ 'constraint' => 'oneOf',
+ ),),
+ $startErrors
+ )
+ );
+ } else {
+ $this->errors = $startErrors;
+ }
+ }
+ }
+
+ /**
+ * Validate dependencies
+ *
+ * @param mixed $value
+ * @param mixed $dependencies
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateDependencies($value, $dependencies, $path, $i = "")
+ {
+ foreach ($dependencies as $key => $dependency) {
+ if (property_exists($value, $key)) {
+ if (is_string($dependency)) {
+ // Draft 3 string is allowed - e.g. "dependencies": {"bar": "foo"}
+ if (!property_exists($value, $dependency)) {
+ $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
+ }
+ } else if (is_array($dependency)) {
+ // Draft 4 must be an array - e.g. "dependencies": {"bar": ["foo"]}
+ foreach ($dependency as $d) {
+ if (!property_exists($value, $d)) {
+ $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
+ }
+ }
+ } else if (is_object($dependency)) {
+ // Schema - e.g. "dependencies": {"bar": {"properties": {"foo": {...}}}}
+ $this->checkUndefined($value, $dependency, $path, $i);
+ }
+ }
+ }
+ }
+
+ protected function validateUri($schema, $schemaUri = null)
+ {
+ $resolver = new UriResolver();
+ $retriever = $this->getUriRetriever();
+
+ $jsonSchema = null;
+ if ($resolver->isValid($schemaUri)) {
+ $schemaId = property_exists($schema, 'id') ? $schema->id : null;
+ $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
+ }
+
+ return $jsonSchema;
+ }
+}