Skip to content

Support json_decode assoc #286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/JsonSchema/Constraints/CollectionConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected function validateItems($value, $schema = null, $path = null, $i = null
// Reset errors if needed
if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
$this->errors = $secondErrors;
} else if (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
} elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
$this->errors = $initErrors;
}
}
Expand All @@ -102,7 +102,7 @@ protected function validateItems($value, $schema = null, $path = null, $i = null
}

// Treat when we have more schema definitions than values, not for empty arrays
if(count($value) > 0) {
if (count($value) > 0) {
for ($k = count($value); $k < count($schema->items); $k++) {
$this->checkUndefined(new UndefinedConstraint(), $schema->items[$k], $path, $k);
}
Expand Down
16 changes: 13 additions & 3 deletions src/JsonSchema/Constraints/Constraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace JsonSchema\Constraints;

use JsonSchema\Uri\UriRetriever;
use JsonSchema\Validator;

/**
* The Base Constraints, all Validators should extend this class
Expand Down Expand Up @@ -49,8 +50,7 @@ public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $
*/
public function getUriRetriever()
{
if (is_null($this->uriRetriever))
{
if (is_null($this->uriRetriever)) {
$this->setUriRetriever(new UriRetriever);
}

Expand All @@ -63,7 +63,7 @@ public function getUriRetriever()
public function getFactory()
{
if (!$this->factory) {
$this->factory = new Factory($this->getUriRetriever());
$this->factory = new Factory($this->getUriRetriever(), $this->checkMode);
}

return $this->factory;
Expand Down Expand Up @@ -288,4 +288,14 @@ protected function retrieveUri($uri)
// TODO validate using schema
return $jsonSchema;
}

/**
* Get the type check based on the set check mode.
*
* @return TypeCheck\TypeCheckInterface
*/
protected function getTypeCheck()
{
return $this->getFactory()->getTypeCheck();
}
}
19 changes: 13 additions & 6 deletions src/JsonSchema/Constraints/EnumConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

namespace JsonSchema\Constraints;
use JsonSchema\Validator;

/**
* The EnumConstraint Constraints, validates an element against a given set of possibilities
Expand All @@ -26,17 +27,23 @@ public function check($element, $schema = null, $path = null, $i = null)
if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
return;
}
$type = gettype($element);

foreach ($schema->enum as $enum) {
$type = gettype($element);
$enumType = gettype($enum);
if ($this->checkMode === self::CHECK_MODE_TYPE_CAST && $type == "array" && $enumType == "object") {
if ((object)$element == $enum) {
return;
}
}

if ($type === gettype($enum)) {
if ($type == "object") {
if ($element == $enum)
if ($element == $enum) {
return;
} else {
if ($element === $enum)
return;

}
} elseif ($element === $enum) {
return;
}
}
}
Expand Down
49 changes: 36 additions & 13 deletions src/JsonSchema/Constraints/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use JsonSchema\Exception\InvalidArgumentException;
use JsonSchema\Uri\UriRetriever;
use JsonSchema\Validator;

/**
* Factory for centralize constraint initialization.
Expand All @@ -23,6 +22,16 @@ class Factory
*/
protected $uriRetriever;

/**
* @var int
*/
private $checkMode;

/**
* @var TypeCheck\TypeCheckInterface[]
*/
private $typeCheck = array();

/**
* @var array $constraintMap
*/
Expand All @@ -43,13 +52,14 @@ class Factory
/**
* @param UriRetriever $uriRetriever
*/
public function __construct(UriRetriever $uriRetriever = null)
public function __construct(UriRetriever $uriRetriever = null, $checkMode = Constraint::CHECK_MODE_NORMAL)
{
if (!$uriRetriever) {
$uriRetriever = new UriRetriever();
}

$this->uriRetriever = $uriRetriever;
$this->checkMode = $checkMode;
}

/**
Expand All @@ -60,23 +70,36 @@ public function getUriRetriever()
return $this->uriRetriever;
}

public function getTypeCheck()
{
if (!isset($this->typeCheck[$this->checkMode])) {
if ($this->checkMode === Constraint::CHECK_MODE_TYPE_CAST) {
$this->typeCheck[Constraint::CHECK_MODE_TYPE_CAST] = new TypeCheck\LooseTypeCheck();
} else {
$this->typeCheck[$this->checkMode] = new TypeCheck\StrictTypeCheck();
}
}

return $this->typeCheck[$this->checkMode];
}

/**
* @param string $name
* @param string $class
* @return Factory
*/
public function setConstraintClass($name, $class)
{
// Ensure class exists
if (!class_exists($class)) {
throw new InvalidArgumentException('Unknown constraint ' . $name);
}
// Ensure class is appropriate
if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
throw new InvalidArgumentException('Invalid class ' . $name);
}
$this->constraintMap[$name] = $class;
return $this;
// Ensure class exists
if (!class_exists($class)) {
throw new InvalidArgumentException('Unknown constraint ' . $name);
}
// Ensure class is appropriate
if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
throw new InvalidArgumentException('Invalid class ' . $name);
}
$this->constraintMap[$name] = $class;
return $this;
}

/**
Expand All @@ -89,7 +112,7 @@ public function setConstraintClass($name, $class)
public function createInstanceFor($constraintName)
{
if (array_key_exists($constraintName, $this->constraintMap)) {
return new $this->constraintMap[$constraintName](Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
return new $this->constraintMap[$constraintName]($this->checkMode, $this->uriRetriever, $this);
}
throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
}
Expand Down
8 changes: 4 additions & 4 deletions src/JsonSchema/Constraints/NumberConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ public function check($element, $schema = null, $path = null, $i = null)
if (isset($schema->minimum)) {
if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
$this->addError($path, "Must have a minimum value of " . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum,));
} else if ($element < $schema->minimum) {
} elseif ($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) {
} elseif (isset($schema->minimum) && $element < $schema->minimum) {
$this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
}

Expand All @@ -42,13 +42,13 @@ public function check($element, $schema = null, $path = null, $i = null)
if (isset($schema->maximum)) {
if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
$this->addError($path, "Must have a maximum value of " . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum,));
} else if ($element > $schema->maximum) {
} elseif ($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", 'missingMaximum');
}
} else if (isset($schema->maximum) && $element > $schema->maximum) {
} elseif (isset($schema->maximum) && $element > $schema->maximum) {
$this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
}

Expand Down
6 changes: 3 additions & 3 deletions src/JsonSchema/Constraints/ObjectConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ObjectConstraint extends Constraint
/**
* {@inheritDoc}
*/
function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
public function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
{
if ($element instanceof UndefinedConstraint) {
return;
Expand Down Expand Up @@ -161,13 +161,13 @@ protected function getProperty($element, $property, $fallback = null)
protected function validateMinMaxConstraint($element, $objectDefinition, $path) {
// Verify minimum number of properties
if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
if (count(get_object_vars($element)) < $objectDefinition->minProperties) {
if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
$this->addError($path, "Must contain a minimum of " . $objectDefinition->minProperties . " properties", 'minProperties', array('minProperties' => $objectDefinition->minProperties,));
}
}
// Verify maximum number of properties
if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
if (count(get_object_vars($element)) > $objectDefinition->maxProperties) {
if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
$this->addError($path, "Must contain no more than " . $objectDefinition->maxProperties . " properties", 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties,));
}
}
Expand Down
11 changes: 8 additions & 3 deletions src/JsonSchema/Constraints/SchemaConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ 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)) {
} elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
$inlineSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
if (is_array($inlineSchema)) {
$inlineSchema = json_decode(json_encode($inlineSchema));
}

// inline schema
$this->checkUndefined($element, $element->{$this->inlineSchemaProperty}, '', '');
$this->checkUndefined($element, $inlineSchema, '', '');
} else {
throw new InvalidArgumentException('no schema found to verify against');
}
}
}
}
59 changes: 59 additions & 0 deletions src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace JsonSchema\Constraints\TypeCheck;

class LooseTypeCheck implements TypeCheckInterface
{
public static function isObject($value)
{
return
is_object($value) ||
(is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
}

public static function isArray($value)
{
return
is_array($value) &&
(count($value) == 0 || !self::isAssociativeArray($value));
}

public static function propertyGet($value, $property)
{
if (is_object($value)) {
return $value->{$property};
}

return $value[$property];
}

public static function propertyExists($value, $property)
{
if (is_object($value)) {
return property_exists($value, $property);
}

return array_key_exists($property, $value);
}

public static function propertyCount($value)
{
if (is_object($value)) {
return count(get_object_vars($value));
}

return count($value);
}

/**
* Check if the provided array is associative or not
*
* @param array $arr
*
* @return bool
*/
private static function isAssociativeArray($arr)
{
return (array_keys($arr) !== range(0, count($arr) - 1));
}
}
31 changes: 31 additions & 0 deletions src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace JsonSchema\Constraints\TypeCheck;

class StrictTypeCheck implements TypeCheckInterface
{
public static function isObject($value)
{
return is_object($value);
}

public static function isArray($value)
{
return is_array($value);
}

public static function propertyGet($value, $property)
{
return $value->{$property};
}

public static function propertyExists($value, $property)
{
return property_exists($value, $property);
}

public static function propertyCount($value)
{
return count(get_object_vars($value));
}
}
16 changes: 16 additions & 0 deletions src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace JsonSchema\Constraints\TypeCheck;

interface TypeCheckInterface
{
public static function isObject($value);

public static function isArray($value);

public static function propertyGet($value, $property);

public static function propertyExists($value, $property);

public static function propertyCount($value);
}
5 changes: 2 additions & 3 deletions src/JsonSchema/Constraints/TypeConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,11 @@ protected function validateType($value, $type)
}

if ('object' === $type) {
return is_object($value);
//return ($this::CHECK_MODE_TYPE_CAST == $this->checkMode) ? is_array($value) : is_object($value);
return $this->getTypeCheck()->isObject($value);
}

if ('array' === $type) {
return is_array($value);
return $this->getTypeCheck()->isArray($value);
}

if ('string' === $type) {
Expand Down
Loading