Skip to content

Commit 0600dcf

Browse files
committed
spec compliance
Tests: 275, Assertions: 259, Errors: 16, Failures: 55.
1 parent 5b65e12 commit 0600dcf

File tree

7 files changed

+108
-27
lines changed

7 files changed

+108
-27
lines changed
File renamed without changes.
File renamed without changes.

src/Constraint/InvalidValue.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Yaoi\Schema\Constraint;
4+
5+
6+
use Yaoi\Schema\Exception;
7+
8+
class InvalidValue extends Exception
9+
{
10+
}

src/Schema.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Yaoi\Schema;
44

55

6+
use Yaoi\Schema\Constraint\InvalidValue;
67
use Yaoi\Schema\Constraint\Properties;
78
use Yaoi\Schema\Constraint\Ref;
89
use Yaoi\Schema\Constraint\Type;
@@ -34,6 +35,12 @@ class Schema extends MagicMap
3435
public $ref;
3536

3637

38+
public $maximum;
39+
public $exclusiveMaximum;
40+
public $minimum;
41+
public $exclusiveMinimum;
42+
43+
3744
public function import($data)
3845
{
3946
$result = $data;
@@ -47,6 +54,34 @@ public function import($data)
4754
}
4855
}
4956

57+
if (is_int($data) || is_float($data)) {
58+
if ($this->maximum !== null) {
59+
if ($this->exclusiveMaximum === true) {
60+
if ($data >= $this->maximum) {
61+
$this->fail('Maximum value exceeded');
62+
}
63+
} else {
64+
if ($data > $this->maximum) {
65+
$this->fail('Maximum value exceeded');
66+
}
67+
}
68+
}
69+
70+
if ($this->minimum !== null) {
71+
if ($this->exclusiveMinimum === true) {
72+
if ($data <= $this->minimum) {
73+
$this->fail('Minimum value exceeded');
74+
}
75+
} else {
76+
if ($data < $this->minimum) {
77+
$this->fail('Minimum value exceeded');
78+
}
79+
}
80+
}
81+
82+
83+
}
84+
5085
if ($data instanceof \stdClass) {
5186
if ($this->properties !== null) {
5287
if (!$result instanceof ObjectItem) {
@@ -130,7 +165,6 @@ private function fail($message)
130165
}
131166
}
132167

133-
134168
public function export($data)
135169
{
136170
$result = $data;

src/SchemaLoader.php

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Yaoi\Schema;
44

5-
65
use Yaoi\Schema\Base;
76
use Yaoi\Schema\Constraint\Properties;
87
use Yaoi\Schema\Constraint\Ref;
@@ -21,6 +20,11 @@ class SchemaLoader extends Base
2120
const ADDITIONAL_ITEMS = 'additionalItems';
2221
const UNIQUE_ITEMS = 'uniqueItems';
2322

23+
const MINIMUM = 'minimum';
24+
const EXCLUSIVE_MINIMUM = 'exclusiveMinimum';
25+
const MAXIMUM = 'maximum';
26+
const EXCLUSIVE_MAXIMUM = 'exclusiveMaximum';
27+
2428
/** @var Schema */
2529
private $rootSchema;
2630

@@ -36,32 +40,32 @@ public function readSchema($schemaData)
3640
}
3741

3842

39-
protected function readSchemaDeeper($schemaData, Schema $parentSchema = null)
43+
protected function readSchemaDeeper($schemaArray, Schema $parentSchema = null)
4044
{
4145
$schema = new Schema();
4246
if (null === $this->rootSchema) {
4347
$this->rootSchema = $schema;
44-
$this->rootData = $schemaData;
48+
$this->rootData = $schemaArray;
4549
}
4650

47-
if ($schemaData instanceof \stdClass) {
48-
$schemaData = (array)$schemaData;
51+
if ($schemaArray instanceof \stdClass) {
52+
$schemaArray = (array)$schemaArray;
4953
}
5054

51-
if (isset($schemaData[self::TYPE])) {
52-
$schema->type = new Type($schemaData[self::TYPE]);
55+
if (isset($schemaArray[self::TYPE])) {
56+
$schema->type = new Type($schemaArray[self::TYPE]);
5357
}
5458

55-
if (isset($schemaData[self::PROPERTIES])) {
59+
if (isset($schemaArray[self::PROPERTIES])) {
5660
$properties = new Properties();
5761
$schema->properties = $properties;
58-
foreach ($schemaData[self::PROPERTIES] as $name => $data) {
62+
foreach ($schemaArray[self::PROPERTIES] as $name => $data) {
5963
$properties->__set($name, $this->readSchemaDeeper($data, $schema));
6064
}
6165
}
6266

63-
if (isset($schemaData[self::ADDITIONAL_PROPERTIES])) {
64-
$additionalProperties = $schemaData[self::ADDITIONAL_PROPERTIES];
67+
if (isset($schemaArray[self::ADDITIONAL_PROPERTIES])) {
68+
$additionalProperties = $schemaArray[self::ADDITIONAL_PROPERTIES];
6569
if ($additionalProperties instanceof \stdClass) {
6670
$schema->additionalProperties = $this->readSchemaDeeper($additionalProperties, $schema);
6771
} else {
@@ -70,8 +74,8 @@ protected function readSchemaDeeper($schemaData, Schema $parentSchema = null)
7074
}
7175

7276

73-
if (isset($schemaData[self::ITEMS])) {
74-
$items = $schemaData[self::ITEMS];
77+
if (isset($schemaArray[self::ITEMS])) {
78+
$items = $schemaArray[self::ITEMS];
7579
if (is_array($items)) {
7680
$schema->items = array();
7781
foreach ($items as $item) {
@@ -83,22 +87,37 @@ protected function readSchemaDeeper($schemaData, Schema $parentSchema = null)
8387
}
8488

8589

86-
if (isset($schemaData[self::ADDITIONAL_ITEMS])) {
87-
$additionalItems = $schemaData[self::ADDITIONAL_ITEMS];
90+
if (isset($schemaArray[self::ADDITIONAL_ITEMS])) {
91+
$additionalItems = $schemaArray[self::ADDITIONAL_ITEMS];
8892
if ($additionalItems instanceof \stdClass) {
8993
$schema->additionalItems = $this->readSchemaDeeper($additionalItems, $schema);
9094
} else {
9195
$schema->additionalItems = $additionalItems;
9296
}
9397
}
9498

95-
if (isset($schemaData[self::UNIQUE_ITEMS]) && $schemaData[self::UNIQUE_ITEMS] === true) {
99+
if (isset($schemaArray[self::UNIQUE_ITEMS]) && $schemaArray[self::UNIQUE_ITEMS] === true) {
96100
$schema->uniqueItems = true;
97101
}
98102

103+
104+
if (isset($schemaArray[self::MINIMUM])) {
105+
$schema->minimum = $schemaArray[self::MINIMUM];
106+
}
107+
if (isset($schemaArray[self::EXCLUSIVE_MINIMUM])) {
108+
$schema->exclusiveMinimum = $schemaArray[self::EXCLUSIVE_MINIMUM];
109+
}
110+
if (isset($schemaArray[self::MAXIMUM])) {
111+
$schema->maximum = $schemaArray[self::MAXIMUM];
112+
}
113+
if (isset($schemaArray[self::EXCLUSIVE_MAXIMUM])) {
114+
$schema->exclusiveMaximum = $schemaArray[self::EXCLUSIVE_MAXIMUM];
115+
}
116+
117+
99118
// should resolve references on load
100-
if (isset($schemaData[self::REF])) {
101-
$schema->ref = $this->resolveReference($schemaData[self::REF]);
119+
if (isset($schemaArray[self::REF])) {
120+
$schema->ref = $this->resolveReference($schemaArray[self::REF]);
102121
}
103122

104123
return $schema;
@@ -114,7 +133,14 @@ private function resolveReference($referencePath)
114133
{
115134
$ref = &$this->refs[$referencePath];
116135
if (null === $ref) {
117-
if ($referencePath === '#') {
136+
if ($referencePath === 'http://json-schema.org/draft-04/schema#') {
137+
$ref = new Ref(
138+
$referencePath,
139+
SchemaLoader::create()->readSchema(json_decode(file_get_contents(__DIR__ . '/../spec/json-schema.json')))
140+
);
141+
}
142+
143+
elseif ($referencePath === '#') {
118144
$ref = new Ref($referencePath, $this->rootSchema);
119145
}
120146

@@ -123,8 +149,8 @@ private function resolveReference($referencePath)
123149
$branch = &$this->rootData;
124150
while ($path) {
125151
$folder = array_shift($path);
126-
if (isset($branch[$folder])) {
127-
$branch = &$branch[$folder];
152+
if (isset($branch->$folder)) {
153+
$branch = &$branch->$folder;
128154
} else {
129155
throw new \Exception('Could not resolve ' . $referencePath . ', ' . $folder);
130156
}
@@ -144,4 +170,9 @@ public function writeSchema()
144170

145171
}
146172

147-
}
173+
}
174+
175+
/**
176+
* @property $minimum
177+
*/
178+
class __stubJsonSchema {}

src/TODO.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
* separate `additionalProperties` to an unnamed structure
33
* check export
44
* add constraint to stack-trace during import
5-
* check against spec test cases
5+
* check against spec test cases
6+
* avoid `(array)` cast in `SchemaLoader`, getaway from `const` fields?
7+
* different exceptions

tests/src/PHPUnit/Spec/SpecTest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function provider()
5757
foreach ($tests as $test) {
5858
//$schema = SchemaLoader::create()->readSchema($test->schema);
5959
foreach ($test->tests as $case) {
60-
$testCases[$test->description . ': ' . $case->description] = array(
60+
$testCases[$entry . ' ' . $test->description . ': ' . $case->description] = array(
6161
'schema' => $test->schema,
6262
'data' => $case->data,
6363
'isValid' => $case->valid,
@@ -82,11 +82,15 @@ public function provider()
8282
* @property $schema
8383
* @property _SpecTestCase[] $tests
8484
*/
85-
class _SpecTest{}
85+
class _SpecTest
86+
{
87+
}
8688

8789
/**
8890
* @property $description
8991
* @property $data
9092
* @property bool $valid
9193
*/
92-
class _SpecTestCase{}
94+
class _SpecTestCase
95+
{
96+
}

0 commit comments

Comments
 (0)