Skip to content

Commit

Permalink
New way of handling references (#277)
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Safarov authored and bighappyface committed Aug 15, 2016
1 parent ef13b9b commit 1296583
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 348 deletions.
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,11 @@ See [json-schema](http://json-schema.org/) for more details.
```php
<?php

// Get the schema and data as objects
// If you use $ref or if you are unsure, resolve those references here
// This modifies the $schema object
$refResolver = new JsonSchema\RefResolver(new JsonSchema\Uri\UriRetriever(), new JsonSchema\Uri\UriResolver());
$schema = $refResolver->resolve('file://' . realpath('schema.json'));

$data = json_decode(file_get_contents('data.json'));

// Validate
$validator = new JsonSchema\Validator();
$validator->check($data, $schema);
$validator = new JsonSchema\Validator;
$validator->check($data, (object)['$ref' => 'file://' . realpath('schema.json')]);

if ($validator->isValid()) {
echo "The supplied JSON validates against the schema.\n";
Expand Down
62 changes: 34 additions & 28 deletions src/JsonSchema/Constraints/Constraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

namespace JsonSchema\Constraints;

use JsonSchema\SchemaStorage;
use JsonSchema\Uri\UriRetriever;
use JsonSchema\Validator;
use JsonSchema\UriRetrieverInterface;
use JsonSchema\Entity\JsonPointer;

/**
Expand All @@ -21,6 +22,7 @@
*/
abstract class Constraint implements ConstraintInterface
{
protected $schemaStorage;
protected $checkMode = self::CHECK_MODE_NORMAL;
protected $uriRetriever;
protected $errors = array();
Expand All @@ -35,19 +37,25 @@ abstract class Constraint implements ConstraintInterface
private $factory;

/**
* @param int $checkMode
* @param UriRetriever $uriRetriever
* @param Factory $factory
* @param int $checkMode
* @param SchemaStorage $schemaStorage
* @param UriRetrieverInterface $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;
public function __construct(
$checkMode = self::CHECK_MODE_NORMAL,
SchemaStorage $schemaStorage = null,
UriRetrieverInterface $uriRetriever = null,
Factory $factory = null
) {
$this->checkMode = $checkMode;
$this->uriRetriever = $uriRetriever;
$this->factory = $factory;
$this->schemaStorage = $schemaStorage;
}

/**
* @return UriRetriever $uriRetriever
* @return UriRetrieverInterface $uriRetriever
*/
public function getUriRetriever()
{
Expand All @@ -64,16 +72,28 @@ public function getUriRetriever()
public function getFactory()
{
if (!$this->factory) {
$this->factory = new Factory($this->getUriRetriever(), $this->checkMode);
$this->factory = new Factory($this->getSchemaStorage(), $this->getUriRetriever(), $this->checkMode);
}

return $this->factory;
}

/**
* @param UriRetriever $uriRetriever
* @return SchemaStorage
*/
public function getSchemaStorage()
{
if (is_null($this->schemaStorage)) {
$this->schemaStorage = new SchemaStorage($this->getUriRetriever());
}

return $this->schemaStorage;
}

/**
* @param UriRetrieverInterface $uriRetriever
*/
public function setUriRetriever(UriRetriever $uriRetriever)
public function setUriRetriever(UriRetrieverInterface $uriRetriever)
{
$this->uriRetriever = $uriRetriever;
}
Expand Down Expand Up @@ -211,7 +231,7 @@ protected function checkType($value, $schema = null, JsonPointer $path = null, $
protected function checkUndefined($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->getFactory()->createInstanceFor('undefined');
$validator->check($value, $schema, $path, $i);
$validator->check($value, $this->schemaStorage->resolveRefSchema($schema), $path, $i);

$this->addErrors($validator->getErrors());
}
Expand Down Expand Up @@ -280,20 +300,6 @@ protected function checkFormat($value, $schema = null, JsonPointer $path = null,
$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;
}

/**
* Get the type check based on the set check mode.
*
Expand Down
47 changes: 32 additions & 15 deletions src/JsonSchema/Constraints/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@
namespace JsonSchema\Constraints;

use JsonSchema\Exception\InvalidArgumentException;
use JsonSchema\SchemaStorage;
use JsonSchema\Uri\UriRetriever;
use JsonSchema\UriRetrieverInterface;

/**
* Factory for centralize constraint initialization.
*/
class Factory
{
/**
* @var SchemaStorage
*/
protected $schemaStorage;

/**
* @var UriRetriever $uriRetriever
*/
Expand Down Expand Up @@ -50,34 +57,39 @@ class Factory
);

/**
* @param UriRetriever $uriRetriever
* @param SchemaStorage $schemaStorage
* @param UriRetrieverInterface $uriRetriever
* @param int $checkMode
*/
public function __construct(UriRetriever $uriRetriever = null, $checkMode = Constraint::CHECK_MODE_NORMAL)
{
if (!$uriRetriever) {
$uriRetriever = new UriRetriever();
}

$this->uriRetriever = $uriRetriever;
public function __construct(
SchemaStorage $schemaStorage = null,
UriRetrieverInterface $uriRetriever = null,
$checkMode = Constraint::CHECK_MODE_NORMAL
) {
$this->uriRetriever = $uriRetriever ?: new UriRetriever;
$this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
$this->checkMode = $checkMode;
}

/**
* @return UriRetriever
* @return UriRetrieverInterface
*/
public function getUriRetriever()
{
return $this->uriRetriever;
}

public function getSchemaStorage()
{
return $this->schemaStorage;
}

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();
}
$this->typeCheck[$this->checkMode] = $this->checkMode === Constraint::CHECK_MODE_TYPE_CAST
? new TypeCheck\LooseTypeCheck
: new TypeCheck\StrictTypeCheck;
}

return $this->typeCheck[$this->checkMode];
Expand Down Expand Up @@ -112,7 +124,12 @@ public function setConstraintClass($name, $class)
public function createInstanceFor($constraintName)
{
if (array_key_exists($constraintName, $this->constraintMap)) {
return new $this->constraintMap[$constraintName]($this->checkMode, $this->uriRetriever, $this);
return new $this->constraintMap[$constraintName](
$this->checkMode,
$this->schemaStorage,
$this->uriRetriever,
$this
);
}
throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
}
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/ObjectConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public function validateElement($element, $matches, $objectDefinition = null, Js
public function validateDefinition($element, $objectDefinition = null, JsonPointer $path = null)
{
foreach ($objectDefinition as $i => $value) {
$property = $this->getProperty($element, $i, new UndefinedConstraint());
$property = $this->getProperty($element, $i, $this->getFactory()->createInstanceFor('undefined'));
$definition = $this->getProperty($objectDefinition, $i);
$this->checkUndefined($property, $definition, $path, $i);
}
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/TypeConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected function validateTypesArray($value, array $type, &$validTypesWording,
// with a new type constraint
if (is_object($tp)) {
if (!$isValid) {
$validator = new static($this->checkMode);
$validator = $this->getFactory()->createInstanceFor('type');
$subSchema = new \stdClass();
$subSchema->type = $tp;
$validator->check($value, $subSchema, $path, null);
Expand Down

0 comments on commit 1296583

Please sign in to comment.