Skip to content

New way of handling references #277

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 1 commit into from
Aug 15, 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
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
) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be kinda easier to move $schemaStorage to the end of the list? if we'd append it to the existing list, we wouldn't introduce a BC-Break at this point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 This seems like an unnecessary breaking change. However, if this is already a breaking change (and in this core functionality), it probably doesn't make sense to reorder arguments, if it makes sense. Unfortunately, I don't see a good reason to do it here? :)

Copy link
Author

@psafarov psafarov Aug 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steffkes @FlorianSW I think, you're right, it's better to be in the end

$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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've a getter method for $uriRetriever, wouldn't it make sense to have one for $schemStorage, too?


/**
* @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'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, however, is an unrelated change according to the discussion.

Copy link
Author

@psafarov psafarov Aug 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FlorianSW It's a necessary change, the factory passes existing schemaStorage to the new constaint

$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
Loading