Skip to content

Commit

Permalink
Merge pull request #167 from ergebnis/feature/sub-schema
Browse files Browse the repository at this point in the history
Enhancement: Require `JsonPointer` to allow resolving sub-schemas
  • Loading branch information
localheinz authored Dec 13, 2021
2 parents 1e85494 + 75e066b commit 5a08dbc
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 158 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ For a full diff see [`1.0.0...main`][1.0.0...main].
- Disallowed injection of `Validator` into `SchemaValidator` ([#158]), by [@localheinz]
- Removed `Schema` ([#161]), by [@localheinz]
- Composed `Error` into `Result` ([#166]), by [@localheinz]
- Required `JsonPointer` to allow specifying sub-schemas ([#166]), by [@localheinz]

## [`1.0.0`][1.0.0]

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use Ergebnis\Json\SchemaValidator;

$json = SchemaValidator\Json::fromFile('composer.json');
$schema = SchemaValidator\Json::fromString(file_get_contents('https://getcomposer.org/schema.json'));
$jsonPointer = SchemaValidator\JsonPointer::empty();

$schemaValidator = new SchemaValidator\SchemaValidator();

Expand Down
4 changes: 2 additions & 2 deletions infection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"logs": {
"text": ".build/infection/infection-log.txt"
},
"minCoveredMsi": 84,
"minMsi": 82,
"minCoveredMsi": 90,
"minMsi": 88,
"phpUnit": {
"configDir": "test\/Unit"
},
Expand Down
3 changes: 2 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
</MixedPropertyTypeCoercion>
</file>
<file src="src/SchemaValidator.php">
<MixedArgument occurrences="2">
<MixedArgument occurrences="3">
<code>$error['message']</code>
<code>$error['pointer']</code>
<code>$schemaDecoded</code>
</MixedArgument>
<MixedAssignment occurrences="2">
<code>$jsonDecoded</code>
Expand Down
27 changes: 27 additions & 0 deletions src/Exception/CanNotResolve.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json-schema-validator
*/

namespace Ergebnis\Json\SchemaValidator\Exception;

use Ergebnis\Json\SchemaValidator;

final class CanNotResolve extends \InvalidArgumentException
{
public static function jsonPointer(SchemaValidator\JsonPointer $jsonPointer): self
{
return new self(\sprintf(
'Can not resolve JSON pointer "%s".',
$jsonPointer->toString(),
));
}
}
27 changes: 27 additions & 0 deletions src/Exception/ResolvedToRootSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json-schema-validator
*/

namespace Ergebnis\Json\SchemaValidator\Exception;

use Ergebnis\Json\SchemaValidator;

final class ResolvedToRootSchema extends \RuntimeException
{
public static function jsonPointer(SchemaValidator\JsonPointer $jsonPointer): self
{
return new self(\sprintf(
'Resolved JSON pointer "%s" to root schema.',
$jsonPointer->toString(),
));
}
}
52 changes: 44 additions & 8 deletions src/SchemaValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,61 @@

namespace Ergebnis\Json\SchemaValidator;

use Ergebnis\Json\SchemaValidator\Exception\CanNotResolve;
use Ergebnis\Json\SchemaValidator\Exception\ResolvedToRootSchema;
use JsonSchema\Constraints;
use JsonSchema\Exception;
use JsonSchema\SchemaStorage;
use JsonSchema\Uri;
use JsonSchema\Validator;

final class SchemaValidator
{
/**
* @throws CanNotResolve
* @throws ResolvedToRootSchema
*/
public function validate(
Json $json,
Json $schema
Json $schema,
JsonPointer $jsonPointer
): Result {
$validator = new Validator();
$schemaDecoded = \json_decode(
$schema->toString(),
false,
);

$validator->reset();
$uriRetriever = new Uri\UriRetriever();

$jsonDecoded = \json_decode(
$json->toString(),
false,
if (!$jsonPointer->equals(JsonPointer::empty())) {
try {
$subSchemaDecoded = $uriRetriever->resolvePointer(
$schemaDecoded,
$jsonPointer->toString(),
);
} catch (Exception\ResourceNotFoundException $exception) {
throw CanNotResolve::jsonPointer($jsonPointer);
}

if ($schemaDecoded === $subSchemaDecoded) {
throw ResolvedToRootSchema::jsonPointer($jsonPointer);
}

$schemaDecoded = $subSchemaDecoded;
}

$schemaStorage = new SchemaStorage(
$uriRetriever,
new Uri\UriResolver(),
);

$schemaDecoded = \json_decode(
$schema->toString(),
$validator = new Validator(new Constraints\Factory(
$schemaStorage,
$uriRetriever,
));

$jsonDecoded = \json_decode(
$json->toString(),
false,
);

Expand Down
42 changes: 42 additions & 0 deletions test/Unit/Exception/CanNotResolveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json-schema-validator
*/

namespace Ergebnis\Json\SchemaValidator\Test\Unit\Exception;

use Ergebnis\Json\SchemaValidator\Exception;
use Ergebnis\Json\SchemaValidator\JsonPointer;
use PHPUnit\Framework;

/**
* @internal
*
* @covers \Ergebnis\Json\SchemaValidator\Exception\CanNotResolve
*
* @uses \Ergebnis\Json\SchemaValidator\JsonPointer
*/
final class CanNotResolveTest extends Framework\TestCase
{
public function testJsonPointerReturnsException(): void
{
$jsonPointer = JsonPointer::fromString('/foo/bar');

$exception = Exception\CanNotResolve::jsonPointer($jsonPointer);

$expected = \sprintf(
'Can not resolve JSON pointer "%s".',
$jsonPointer->toString(),
);

self::assertSame($expected, $exception->getMessage());
}
}
42 changes: 42 additions & 0 deletions test/Unit/Exception/ResolvedToRootSchemaTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2021 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json-schema-validator
*/

namespace Ergebnis\Json\SchemaValidator\Test\Unit\Exception;

use Ergebnis\Json\SchemaValidator\Exception;
use Ergebnis\Json\SchemaValidator\JsonPointer;
use PHPUnit\Framework;

/**
* @internal
*
* @covers \Ergebnis\Json\SchemaValidator\Exception\ResolvedToRootSchema
*
* @uses \Ergebnis\Json\SchemaValidator\JsonPointer
*/
final class ResolvedToRootSchemaTest extends Framework\TestCase
{
public function testJsonPointerReturnsException(): void
{
$jsonPointer = JsonPointer::fromString('/foo/bar');

$exception = Exception\ResolvedToRootSchema::jsonPointer($jsonPointer);

$expected = \sprintf(
'Resolved JSON pointer "%s" to root schema.',
$jsonPointer->toString(),
);

self::assertSame($expected, $exception->getMessage());
}
}
Loading

0 comments on commit 5a08dbc

Please sign in to comment.