Skip to content

Commit 6ef38b3

Browse files
committed
feat: more progress on draft-06 proof of concept
1 parent 90a858e commit 6ef38b3

11 files changed

+197
-95
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft06;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Constraints\Factory;
10+
use JsonSchema\Entity\ErrorBagProxy;
11+
use JsonSchema\Entity\JsonPointer;
12+
13+
class AdditionalPropertiesConstraint implements ConstraintInterface
14+
{
15+
use ErrorBagProxy;
16+
17+
public function __construct(?Factory $factory = null)
18+
{
19+
$this->initialiseErrorBag($factory ?: new Factory());
20+
}
21+
22+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
23+
{
24+
if (!property_exists($schema, 'additionalProperties')) {
25+
return;
26+
}
27+
28+
if ($schema->additionalProperties === true) {
29+
return;
30+
}
31+
32+
if (!is_object($value)) {
33+
return;
34+
}
35+
36+
$additionalProperties = array_diff_key(get_object_vars($value), (array) $schema->properties);
37+
// @todo additional properties should bechecked against the patternProperties
38+
if ($schema->additionalProperties === false && $additionalProperties !== []) {
39+
$this->addError(ConstraintError::ADDITIONAL_PROPERTIES(), $path, ['additionalProperties' => array_keys($additionalProperties)]);
40+
}
41+
}
42+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft06;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Constraints\Factory;
10+
use JsonSchema\Entity\ErrorBagProxy;
11+
use JsonSchema\Entity\JsonPointer;
12+
13+
class DependenciesConstraint implements ConstraintInterface
14+
{
15+
use ErrorBagProxy;
16+
17+
public function __construct(?Factory $factory = null)
18+
{
19+
$this->initialiseErrorBag($factory ?: new Factory());
20+
}
21+
22+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
23+
{
24+
if (!property_exists($schema, 'dependencies')) {
25+
return;
26+
}
27+
28+
if (!is_object($value)) {
29+
return;
30+
}
31+
32+
foreach ($schema->dependencies as $dependant => $dependencies) {
33+
foreach ($dependencies as $dependency) {
34+
if (property_exists($value, $dependant) && !property_exists($value, $dependency)) {
35+
$this->addError(ConstraintError::DEPENDENCIES(), $path, ['dependant' => $dependant, 'dependency' => $dependency]);
36+
}
37+
}
38+
}
39+
}
40+
}

src/JsonSchema/Constraints/Drafts/Draft06/Draft06Constraint.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,25 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
2020
// Required keyword
2121
$this->checkForKeyword('type', $value, $schema, $path, $i);
2222
// Not
23-
// Dependencies
23+
$this->checkForKeyword('dependencies', $value, $schema, $path, $i);
2424
// allof
2525
// anyof
2626
// oneof
2727

2828
// array
2929
// object
3030
// string
31-
$this->checkForKeyword('number', $value, $schema, $path, $i);
31+
$this->checkForKeyword('additionalProperties', $value, $schema, $path, $i);
3232
$this->checkForKeyword('uniqueItems', $value, $schema, $path, $i);
3333
$this->checkForKeyword('minItems', $value, $schema, $path, $i);
3434
$this->checkForKeyword('minProperties', $value, $schema, $path, $i);
35+
$this->checkForKeyword('maxProperties', $value, $schema, $path, $i);
3536
$this->checkForKeyword('minimum', $value, $schema, $path, $i);
3637
$this->checkForKeyword('minLength', $value, $schema, $path, $i);
3738
$this->checkForKeyword('exclusiveMinimum', $value, $schema, $path, $i);
3839
$this->checkForKeyword('maxItems', $value, $schema, $path, $i);
40+
$this->checkForKeyword('maxLength', $value, $schema, $path, $i);
41+
$this->checkForKeyword('exclusiveMaximum', $value, $schema, $path, $i);
3942
$this->checkForKeyword('enum', $value, $schema, $path, $i);
4043
$this->checkForKeyword('const', $value, $schema, $path, $i);
4144
}

src/JsonSchema/Constraints/Drafts/Draft06/NumberConstraint.php renamed to src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMaximumConstraint.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44

55
namespace JsonSchema\Constraints\Drafts\Draft06;
66

7+
use JsonSchema\ConstraintError;
78
use JsonSchema\Constraints\ConstraintInterface;
89
use JsonSchema\Constraints\Factory;
910
use JsonSchema\Entity\ErrorBagProxy;
1011
use JsonSchema\Entity\JsonPointer;
1112

12-
class NumberConstraint implements ConstraintInterface
13+
class ExclusiveMaximumConstraint implements ConstraintInterface
1314
{
1415
use ErrorBagProxy;
1516

@@ -20,10 +21,14 @@ public function __construct(?Factory $factory = null)
2021

2122
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
2223
{
23-
if (!property_exists($schema, 'type')) {
24+
if (!property_exists($schema, 'exclusiveMaximum')) {
2425
return;
2526
}
2627

27-
throw new \Exception('Implement check method');
28+
if ($value < $schema->exclusiveMaximum) {
29+
return;
30+
}
31+
32+
$this->addError(ConstraintError::EXCLUSIVE_MAXIMUM(), $path, ['exclusiveMaximum' => $schema->exclusiveMaximum, 'found' => $value]);
2833
}
2934
}

src/JsonSchema/Constraints/Drafts/Draft06/Factory.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@ class Factory extends \JsonSchema\Constraints\Factory
1010
* @var array<string, class-string>
1111
*/
1212
protected $constraintMap = [
13+
'additionalProperties' => AdditionalPropertiesConstraint::class,
14+
'dependencies' => DependenciesConstraint::class,
1315
'type' => TypeConstraint::class,
1416
'const' => ConstConstraint::class,
1517
'enum' => EnumConstraint::class,
16-
'number' => NumberConstraint::class,
1718
'uniqueItems' => UniqueItemsConstraint::class,
1819
'minItems' => MinItemsConstraint::class,
1920
'minProperties' => MinPropertiesConstraint::class,
21+
'maxProperties' => MaxPropertiesConstraint::class,
2022
'minimum' => MinimumConstraint::class,
2123
'exclusiveMinimum' => ExclusiveMinimumConstraint::class,
2224
'minLength' => MinLengthConstraint::class,
25+
'maxLength' => MaxLengthConstraint::class,
2326
'maxItems' => MaxItemsConstraint::class,
27+
'exclusiveMaximum' => ExclusiveMaximumConstraint::class,
2428
];
2529
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft06;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Constraints\Factory;
10+
use JsonSchema\Entity\ErrorBagProxy;
11+
use JsonSchema\Entity\JsonPointer;
12+
13+
class MaxLengthConstraint implements ConstraintInterface
14+
{
15+
use ErrorBagProxy;
16+
17+
public function __construct(?Factory $factory = null)
18+
{
19+
$this->initialiseErrorBag($factory ?: new Factory());
20+
}
21+
22+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
23+
{
24+
if (!property_exists($schema, 'maxLength')) {
25+
return;
26+
}
27+
28+
if (!is_string($value)) {
29+
return;
30+
}
31+
32+
$length = mb_strlen($value);
33+
if ($length <= $schema->maxLength) {
34+
return;
35+
}
36+
37+
$this->addError(ConstraintError::LENGTH_MAX(), $path, ['maxLength' => $schema->maxLength, 'found' => $length]);
38+
}
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft06;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Constraints\Factory;
10+
use JsonSchema\Entity\ErrorBagProxy;
11+
use JsonSchema\Entity\JsonPointer;
12+
13+
class MaxPropertiesConstraint implements ConstraintInterface
14+
{
15+
use ErrorBagProxy;
16+
17+
public function __construct(?Factory $factory = null)
18+
{
19+
$this->initialiseErrorBag($factory ?: new Factory());
20+
}
21+
22+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
23+
{
24+
if (!property_exists($schema, 'maxProperties')) {
25+
return;
26+
}
27+
28+
if (!is_object($value)) {
29+
return;
30+
}
31+
32+
$count = count(get_object_vars($value));
33+
if ($count <= $schema->maxProperties) {
34+
return;
35+
}
36+
37+
$this->addError(ConstraintError::PROPERTIES_MAX(), $path, ['maxProperties' => $schema->maxProperties, 'found' => $count]);
38+
}
39+
}

src/JsonSchema/Constraints/Drafts/Draft06/TypeConstraint.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace JsonSchema\Constraints\Drafts\Draft06;
66

7+
use JsonSchema\ConstraintError;
78
use JsonSchema\Constraints\ConstraintInterface;
89
use JsonSchema\Constraints\Factory;
910
use JsonSchema\Entity\ErrorBagProxy;
@@ -24,6 +25,15 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
2425
return;
2526
}
2627

27-
throw new \Exception('Implement check method');
28+
$schemaTypes = (array) $schema->type;
29+
$valueType = gettype($value);
30+
31+
foreach ($schemaTypes as $type) {
32+
if ($valueType === $type) {
33+
return;
34+
}
35+
}
36+
37+
$this->addError(ConstraintError::TYPE(), $path, ['found' => $valueType, 'expected' => implode(', ', $schemaTypes)]);
2838
}
2939
}

src/JsonSchema/Constraints/NumberConstraint.php

Lines changed: 0 additions & 84 deletions
This file was deleted.

tests/Constraints/BaseTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public function getInvalidForAssocTests(): Generator
152152
yield from $this->getInvalidTests();
153153
}
154154

155-
private function validatorErrorsToString(Validator $validator): string
155+
protected function validatorErrorsToString(Validator $validator): string
156156
{
157157
return implode(
158158
', ',

0 commit comments

Comments
 (0)