Skip to content

Commit 00bd7ae

Browse files
committed
cleanup
1 parent 05a0f45 commit 00bd7ae

17 files changed

+210
-34
lines changed

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
# yaoi schema
1+
# Swaggest JSON-schema implementation for PHP
22

3-
JSON-schema inspired PHP versatile structures.
3+
High definition PHP structures with JSON-schema based validation.
4+
5+
## Usage
6+
7+
### Validating JSON data against given schema
8+
9+
```php
410

511
```
6-
Schema:
7-
Ref
8-
Type
9-
Properties
10-
Items
11-
```
12+
13+
### Validated PHP classes
1214

1315
```php
1416
$schema = new Schema();

phpunit.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
bootstrap="vendor/autoload.php"
1313
>
1414
<testsuites>
15-
<testsuite name="Yaoi PHP Schema Test Suite">
15+
<testsuite name="Swaggest PHP Schema Test Suite">
1616
<directory>./tests/src/PHPUnit/</directory>
1717
</testsuite>
1818
</testsuites>

src/NameMirror.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Swaggest\JsonSchema;
4+
5+
class NameMirror
6+
{
7+
public function __get($name)
8+
{
9+
return $name;
10+
}
11+
12+
public function __set($name, $value)
13+
{
14+
throw new \Exception('Unexpected write to read-only structure');
15+
}
16+
}

src/Schema.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Schema extends MagicMap
2222
public $type;
2323

2424
// Object
25-
/** @var Properties */
25+
/** @var Properties|Schema[] */
2626
public $properties;
2727
/** @var Schema|bool */
2828
public $additionalProperties;
@@ -77,6 +77,10 @@ class Schema extends MagicMap
7777
public $minLength;
7878
/** @var int */
7979
public $maxLength;
80+
/** @var string */
81+
public $format;
82+
83+
const FORMAT_DATE_TIME = 'date-time'; // todo implement
8084

8185

8286
/** @var Schema[] */
@@ -88,6 +92,8 @@ class Schema extends MagicMap
8892
/** @var Schema[] */
8993
public $oneOf;
9094

95+
public $objectItemClass;
96+
9197
public function import($data)
9298
{
9399
return $this->process($data, true);
@@ -111,7 +117,7 @@ private function process($data, $import = true, $path = '#')
111117

112118
if ($this->type !== null) {
113119
if (!$this->type->isValid($data)) {
114-
$this->fail(new TypeException(ucfirst(implode(', ', $this->type->types) . ' required')), $path);
120+
$this->fail(new TypeException(ucfirst(implode(', ', $this->type->types) . ' expected, ' . json_encode($data) . ' received')), $path);
115121
}
116122
}
117123

@@ -244,7 +250,11 @@ private function process($data, $import = true, $path = '#')
244250
}
245251

246252
if ($import && !$result instanceof ObjectItem) {
247-
$result = new ObjectItem();
253+
if (null === $this->objectItemClass) {
254+
$result = new ObjectItem();
255+
} else {
256+
$result = new $this->objectItemClass;
257+
}
248258
}
249259

250260
if ($this->properties !== null) {
@@ -354,7 +364,9 @@ private function process($data, $import = true, $path = '#')
354364

355365
private function fail(InvalidValue $exception, $path)
356366
{
357-
$exception->addPath($path);
367+
if ($path !== '#') {
368+
$exception->addPath($path);
369+
}
358370
throw $exception;
359371
}
360372

@@ -379,6 +391,13 @@ public static function string()
379391
return $schema;
380392
}
381393

394+
public static function boolean()
395+
{
396+
$schema = new Schema();
397+
$schema->type = new Type(Type::BOOLEAN);
398+
return $schema;
399+
}
400+
382401
public static function object()
383402
{
384403
$schema = new Schema();

src/Structure/ClassStructure.php

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

33
namespace Swaggest\JsonSchema\Structure;
44

5-
use Swaggest\JsonSchema\Base;
65
use Swaggest\JsonSchema\Constraint\Properties;
76
use Swaggest\JsonSchema\Constraint\Type;
7+
use Swaggest\JsonSchema\NameMirror;
88
use Swaggest\JsonSchema\Schema;
9-
use Swaggest\JsonSchema\OldSchema;
109

11-
abstract class ClassStructure implements ClassStructureContract
10+
abstract class ClassStructure extends ObjectItem implements ClassStructureContract
1211
{
1312
/**
1413
* @return Schema
1514
*/
16-
public static function makeSchema()
15+
public static function schema()
1716
{
1817
$schema = new Schema();
1918
$schema->type = new Type(Type::OBJECT);
2019
$properties = new Properties();
2120
$schema->properties = $properties;
21+
$schema->objectItemClass = get_called_class();
2222
static::setUpProperties($properties, $schema);
2323
return $schema;
2424
}
@@ -31,7 +31,7 @@ public static function makeSchema()
3131
public static function import($data)
3232
{
3333
//static $schemas = array();
34-
return static::makeSchema()->import($data);
34+
return static::schema()->import($data);
3535
}
3636

3737
/**
@@ -41,7 +41,7 @@ public static function import($data)
4141
*/
4242
public static function export($data)
4343
{
44-
return static::makeSchema()->export($data);
44+
return static::schema()->export($data);
4545
}
4646

4747
/**
@@ -51,4 +51,49 @@ static function create()
5151
{
5252
return new static;
5353
}
54+
55+
protected $__hasNativeProperties = true;
56+
protected $__validateOnSet = true;
57+
58+
public function jsonSerialize()
59+
{
60+
if ($this->__hasNativeProperties) {
61+
$result = new \stdClass();
62+
foreach (static::schema()->properties->toArray() as $name => $schema) {
63+
$value = $this->$name;
64+
if (null !== $value || array_key_exists($name, $this->_arrayOfData)) {
65+
$result->$name = $value;
66+
}
67+
}
68+
} else {
69+
$result = parent::jsonSerialize();
70+
}
71+
72+
return $result;
73+
}
74+
75+
/**
76+
* @return static
77+
*/
78+
public static function names()
79+
{
80+
static $nameflector = null;
81+
if (null === $nameflector) {
82+
$nameflector = new NameMirror();
83+
}
84+
return $nameflector;
85+
}
86+
87+
public function __set($name, $column)
88+
{
89+
if ($this->__validateOnSet) {
90+
if ($property = static::schema()->properties[$name]) {
91+
$property->export($column);
92+
}
93+
}
94+
$this->_arrayOfData[$name] = $column;
95+
return $this;
96+
}
97+
98+
5499
}

src/TODO.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
* implement go-unnamed-style structures
22
* separate `additionalProperties` to an unnamed structure
33
* avoid `(array)` cast in `SchemaLoader`, getaway from `const` fields?
4+
* process string formats
5+
* test against optional json-schema cases
6+
* all-errors at once mode (apart of throw Exception)

tests/src/Helper/Example.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Swaggest\JsonSchema\Tests\Helper;
4+
5+
use Swaggest\JsonSchema\Constraint\Properties;
6+
use Swaggest\JsonSchema\Schema;
7+
use Swaggest\JsonSchema\Structure\ClassStructure;
8+
9+
/**
10+
* @property int $quantity PHPDoc defined dynamic properties will be validated on every set
11+
*/
12+
class Example extends ClassStructure
13+
{
14+
/* Native (public) properties will be validated only on import and export of structure data */
15+
16+
/** @var int */
17+
public $id;
18+
public $name;
19+
/** @var Order[] */
20+
public $orders;
21+
22+
/**
23+
* @param Properties|static $properties
24+
* @param Schema $ownerSchema
25+
*/
26+
public static function setUpProperties($properties, Schema $ownerSchema)
27+
{
28+
$properties->id = Schema::integer();
29+
$properties->name = Schema::string();
30+
31+
$properties->quantity = Schema::integer();
32+
$properties->quantity->minimum = 0;
33+
34+
$properties->orders = Schema::create();
35+
$properties->orders->items = Order::schema();
36+
37+
$ownerSchema->required = array(self::names()->id);
38+
}
39+
}
40+
41+
42+
class Order extends ClassStructure
43+
{
44+
public $id;
45+
public $dateTime;
46+
public $price;
47+
48+
/**
49+
* @param Properties|static $properties
50+
* @param Schema $ownerSchema
51+
*/
52+
public static function setUpProperties($properties, Schema $ownerSchema)
53+
{
54+
$properties->id = Schema::integer();
55+
$properties->dateTime = Schema::string();
56+
$properties->dateTime->format = Schema::FORMAT_DATE_TIME;
57+
$properties->price = Schema::number();
58+
59+
$ownerSchema->required[] = self::names()->id;
60+
}
61+
}

tests/src/Helper/LevelOneClass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class LevelOneClass extends ClassStructure
1919
*/
2020
public static function setUpProperties($properties, Schema $ownerSchema)
2121
{
22-
$properties->level1 = LevelTwoClass::makeSchema();
22+
$properties->level1 = LevelTwoClass::schema();
2323
}
2424

2525

tests/src/Helper/LevelTwoClass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class LevelTwoClass extends ClassStructure
2020
*/
2121
public static function setUpProperties($properties, Schema $ownerSchema)
2222
{
23-
$properties->level2 = LevelThreeClass::makeSchema();
23+
$properties->level2 = LevelThreeClass::schema();
2424
}
2525

2626

tests/src/Helper/SampleStructure.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
*/
1313
class SampleStructure extends ClassStructure
1414
{
15+
public $native;
16+
1517
/**
1618
* @param \Swaggest\JsonSchema\Constraint\Properties|static $properties
1719
* @param Schema $schema
1820
*/
1921
public static function setUpProperties($properties, Schema $schema)
2022
{
23+
$properties->native = Schema::boolean();
2124
$properties->propOne = Schema::string();
2225
$properties->propTwo = Schema::integer();
2326
$properties->recursion = $schema;

0 commit comments

Comments
 (0)