Skip to content

Commit e428b84

Browse files
committed
performance improvements
1 parent 2128f9d commit e428b84

File tree

7 files changed

+67
-74
lines changed

7 files changed

+67
-74
lines changed

src/JsonSchema/Constraints/Constraint.php

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,48 +22,31 @@
2222
*/
2323
abstract class Constraint implements ConstraintInterface
2424
{
25-
protected $schemaStorage;
26-
protected $checkMode = self::CHECK_MODE_NORMAL;
27-
protected $uriRetriever;
2825
protected $errors = array();
2926
protected $inlineSchemaProperty = '$schema';
3027

3128
const CHECK_MODE_NORMAL = 1;
3229
const CHECK_MODE_TYPE_CAST = 2;
3330

3431
/**
35-
* @var null|Factory
32+
* @var Factory
3633
*/
3734
private $factory;
3835

3936
/**
40-
* @param int $checkMode
41-
* @param SchemaStorage $schemaStorage
42-
* @param UriRetrieverInterface $uriRetriever
4337
* @param Factory $factory
4438
*/
45-
public function __construct(
46-
$checkMode = self::CHECK_MODE_NORMAL,
47-
SchemaStorage $schemaStorage = null,
48-
UriRetrieverInterface $uriRetriever = null,
49-
Factory $factory = null
50-
) {
51-
$this->checkMode = $checkMode;
52-
$this->uriRetriever = $uriRetriever;
53-
$this->factory = $factory;
54-
$this->schemaStorage = $schemaStorage;
39+
public function __construct(Factory $factory = null)
40+
{
41+
$this->factory = $factory ? : $this->getFactory();
5542
}
5643

5744
/**
5845
* @return UriRetrieverInterface $uriRetriever
5946
*/
6047
public function getUriRetriever()
6148
{
62-
if (is_null($this->uriRetriever)) {
63-
$this->setUriRetriever(new UriRetriever);
64-
}
65-
66-
return $this->uriRetriever;
49+
return $this->factory->getUriRetriever();
6750
}
6851

6952
/**
@@ -72,7 +55,7 @@ public function getUriRetriever()
7255
public function getFactory()
7356
{
7457
if (!$this->factory) {
75-
$this->factory = new Factory($this->getSchemaStorage(), $this->getUriRetriever(), $this->checkMode);
58+
$this->factory = new Factory();
7659
}
7760

7861
return $this->factory;
@@ -83,19 +66,12 @@ public function getFactory()
8366
*/
8467
public function getSchemaStorage()
8568
{
86-
if (is_null($this->schemaStorage)) {
87-
$this->schemaStorage = new SchemaStorage($this->getUriRetriever());
88-
}
89-
90-
return $this->schemaStorage;
69+
return $this->getFactory()->getSchemaStorage();
9170
}
9271

93-
/**
94-
* @param UriRetrieverInterface $uriRetriever
95-
*/
96-
public function setUriRetriever(UriRetrieverInterface $uriRetriever)
72+
public function getCheckMode()
9773
{
98-
$this->uriRetriever = $uriRetriever;
74+
return $this->factory->getCheckMode();
9975
}
10076

10177
/**
@@ -123,7 +99,9 @@ public function addError(JsonPointer $path = null, $message, $constraint='', arr
12399
*/
124100
public function addErrors(array $errors)
125101
{
126-
$this->errors = array_merge($this->errors, $errors);
102+
if ($errors) {
103+
$this->errors = array_merge($this->errors, $errors);
104+
}
127105
}
128106

129107
/**
@@ -181,7 +159,7 @@ protected function incrementPath(JsonPointer $path = null, $i)
181159
*/
182160
protected function checkArray($value, $schema = null, JsonPointer $path = null, $i = null)
183161
{
184-
$validator = $this->getFactory()->createInstanceFor('collection');
162+
$validator = $this->factory->createInstanceFor('collection');
185163
$validator->check($value, $schema, $path, $i);
186164

187165
$this->addErrors($validator->getErrors());
@@ -198,7 +176,7 @@ protected function checkArray($value, $schema = null, JsonPointer $path = null,
198176
*/
199177
protected function checkObject($value, $schema = null, JsonPointer $path = null, $i = null, $patternProperties = null)
200178
{
201-
$validator = $this->getFactory()->createInstanceFor('object');
179+
$validator = $this->factory->createInstanceFor('object');
202180
$validator->check($value, $schema, $path, $i, $patternProperties);
203181

204182
$this->addErrors($validator->getErrors());
@@ -214,7 +192,7 @@ protected function checkObject($value, $schema = null, JsonPointer $path = null,
214192
*/
215193
protected function checkType($value, $schema = null, JsonPointer $path = null, $i = null)
216194
{
217-
$validator = $this->getFactory()->createInstanceFor('type');
195+
$validator = $this->factory->createInstanceFor('type');
218196
$validator->check($value, $schema, $path, $i);
219197

220198
$this->addErrors($validator->getErrors());
@@ -230,8 +208,8 @@ protected function checkType($value, $schema = null, JsonPointer $path = null, $
230208
*/
231209
protected function checkUndefined($value, $schema = null, JsonPointer $path = null, $i = null)
232210
{
233-
$validator = $this->getFactory()->createInstanceFor('undefined');
234-
$validator->check($value, $this->schemaStorage->resolveRefSchema($schema), $path, $i);
211+
$validator = $this->factory->createInstanceFor('undefined');
212+
$validator->check($value, $this->getSchemaStorage()->resolveRefSchema($schema), $path, $i);
235213

236214
$this->addErrors($validator->getErrors());
237215
}
@@ -246,7 +224,7 @@ protected function checkUndefined($value, $schema = null, JsonPointer $path = nu
246224
*/
247225
protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
248226
{
249-
$validator = $this->getFactory()->createInstanceFor('string');
227+
$validator = $this->factory->createInstanceFor('string');
250228
$validator->check($value, $schema, $path, $i);
251229

252230
$this->addErrors($validator->getErrors());
@@ -262,7 +240,7 @@ protected function checkString($value, $schema = null, JsonPointer $path = null,
262240
*/
263241
protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
264242
{
265-
$validator = $this->getFactory()->createInstanceFor('number');
243+
$validator = $this->factory->createInstanceFor('number');
266244
$validator->check($value, $schema, $path, $i);
267245

268246
$this->addErrors($validator->getErrors());
@@ -278,7 +256,7 @@ protected function checkNumber($value, $schema = null, JsonPointer $path = null,
278256
*/
279257
protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
280258
{
281-
$validator = $this->getFactory()->createInstanceFor('enum');
259+
$validator = $this->factory->createInstanceFor('enum');
282260
$validator->check($value, $schema, $path, $i);
283261

284262
$this->addErrors($validator->getErrors());
@@ -294,7 +272,7 @@ protected function checkEnum($value, $schema = null, JsonPointer $path = null, $
294272
*/
295273
protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
296274
{
297-
$validator = $this->getFactory()->createInstanceFor('format');
275+
$validator = $this->factory->createInstanceFor('format');
298276
$validator->check($value, $schema, $path, $i);
299277

300278
$this->addErrors($validator->getErrors());
@@ -307,7 +285,7 @@ protected function checkFormat($value, $schema = null, JsonPointer $path = null,
307285
*/
308286
protected function getTypeCheck()
309287
{
310-
return $this->getFactory()->getTypeCheck();
288+
return $this->factory->getTypeCheck();
311289
}
312290

313291
/**

src/JsonSchema/Constraints/EnumConstraint.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function check($element, $schema = null, JsonPointer $path = null, $i = n
3232

3333
foreach ($schema->enum as $enum) {
3434
$enumType = gettype($enum);
35-
if ($this->checkMode === self::CHECK_MODE_TYPE_CAST && $type == "array" && $enumType == "object") {
35+
if ($this->getCheckMode() === self::CHECK_MODE_TYPE_CAST && $type == "array" && $enumType == "object") {
3636
if ((object)$element == $enum) {
3737
return;
3838
}

src/JsonSchema/Constraints/Factory.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,22 @@ public function setConstraintClass($name, $class)
128128
*/
129129
public function createInstanceFor($constraintName)
130130
{
131-
if (array_key_exists($constraintName, $this->constraintMap)) {
132-
if (!isset($this->instanceCache[$constraintName])) {
133-
$this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName](
134-
$this->checkMode,
135-
$this->schemaStorage,
136-
$this->uriRetriever,
137-
$this
138-
);
139-
}
140-
return clone $this->instanceCache[$constraintName];
131+
if (!isset($this->constraintMap[$constraintName])) {
132+
throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
141133
}
142-
throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
134+
135+
if (!isset($this->instanceCache[$constraintName])) {
136+
$this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
137+
}
138+
139+
return clone $this->instanceCache[$constraintName];
140+
}
141+
142+
/**
143+
* @return int
144+
*/
145+
public function getCheckMode()
146+
{
147+
return $this->checkMode;
143148
}
144149
}

src/JsonSchema/Constraints/ObjectConstraint.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@ public function validateDefinition($element, $objectDefinition = null, JsonPoint
143143
*/
144144
protected function getProperty($element, $property, $fallback = null)
145145
{
146-
if (is_array($element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) {
147-
return array_key_exists($property, $element) ? $element[$property] : $fallback;
148-
} elseif (is_object($element)) {
149-
return property_exists($element, $property) ? $element->$property : $fallback;
146+
if (is_array($element) && array_key_exists($property, $element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) {
147+
return $element[$property];
148+
} elseif (is_object($element) && property_exists($element, $property)) {
149+
return $element->$property;
150150
}
151151

152152
return $fallback;

src/JsonSchema/Validator.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace JsonSchema;
1111

12-
use JsonSchema\Constraints\SchemaConstraint;
1312
use JsonSchema\Constraints\Constraint;
1413
use JsonSchema\Entity\JsonPointer;
1514

tests/Constraints/BaseTestCase.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace JsonSchema\Tests\Constraints;
1111

1212
use JsonSchema\Constraints\Constraint;
13+
use JsonSchema\Constraints\Factory;
1314
use JsonSchema\SchemaStorage;
1415
use JsonSchema\Uri\UriResolver;
1516
use JsonSchema\Validator;
@@ -36,7 +37,7 @@ public function testInvalidCases($input, $schema, $checkMode = Constraint::CHECK
3637
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
3738
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');
3839

39-
$validator = new Validator($checkMode, $schemaStorage);
40+
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
4041
$validator->check(json_decode($input), $schema);
4142

4243
if (array() !== $errors) {
@@ -58,7 +59,7 @@ public function testInvalidCasesUsingAssoc($input, $schema, $checkMode = Constra
5859
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
5960
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');
6061

61-
$validator = new Validator($checkMode, $schemaStorage);
62+
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
6263
$validator->check(json_decode($input, true), $schema);
6364

6465
if (array() !== $errors) {
@@ -75,7 +76,7 @@ public function testValidCases($input, $schema, $checkMode = Constraint::CHECK_M
7576
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
7677
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');
7778

78-
$validator = new Validator($checkMode, $schemaStorage);
79+
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
7980
$validator->check(json_decode($input), $schema);
8081

8182
$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
@@ -95,7 +96,7 @@ public function testValidCasesUsingAssoc($input, $schema, $checkMode = Constrain
9596
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');
9697

9798
$value = json_decode($input, true);
98-
$validator = new Validator($checkMode, $schemaStorage);
99+
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
99100

100101
$validator->check($value, $schema);
101102
$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
@@ -142,6 +143,7 @@ private function getUriRetrieverMock($schema)
142143
$uriRetriever->retrieve('http://www.my-domain.com/schema.json')
143144
->willReturn($schema)
144145
->shouldBeCalled();
146+
145147
$uriRetriever->retrieve(Argument::any())
146148
->will(function ($args) use ($jsonSchemaDraft03, $jsonSchemaDraft04, $relativeTestsRoot) {
147149
if ('http://json-schema.org/draft-03/schema' === $args[0]) {

tests/Uri/UriRetrieverTest.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ protected function setUp()
2626

2727
private function getRetrieverMock($returnSchema, $returnMediaType = Validator::SCHEMA_MEDIA_TYPE)
2828
{
29-
3029
$jsonSchema = json_decode($returnSchema);
3130

3231
if (JSON_ERROR_NONE < $error = json_last_error()) {
@@ -48,13 +47,12 @@ private function getRetrieverMock($returnSchema, $returnMediaType = Validator::S
4847
*/
4948
public function testChildExtendsParentValidTest($childSchema, $parentSchema)
5049
{
51-
$retrieverMock = $this->getRetrieverMock($parentSchema);
50+
$this->mockRetriever($parentSchema);
5251

5352
$json = '{"childProp":"infant", "parentProp":false}';
5453
$decodedJson = json_decode($json);
5554
$decodedJsonSchema = json_decode($childSchema);
5655

57-
$this->validator->setUriRetriever($retrieverMock);
5856
$this->validator->check($decodedJson, $decodedJsonSchema);
5957
$this->assertTrue($this->validator->isValid());
6058
}
@@ -64,13 +62,12 @@ public function testChildExtendsParentValidTest($childSchema, $parentSchema)
6462
*/
6563
public function testChildExtendsParentInvalidChildTest($childSchema, $parentSchema)
6664
{
67-
$retrieverMock = $this->getRetrieverMock($parentSchema);
65+
$this->mockRetriever($parentSchema);
6866

6967
$json = '{"childProp":1, "parentProp":false}';
7068
$decodedJson = json_decode($json);
7169
$decodedJsonSchema = json_decode($childSchema);
7270

73-
$this->validator->setUriRetriever($retrieverMock);
7471
$this->validator->check($decodedJson, $decodedJsonSchema);
7572
$this->assertFalse($this->validator->isValid());
7673
}
@@ -80,13 +77,12 @@ public function testChildExtendsParentInvalidChildTest($childSchema, $parentSche
8077
*/
8178
public function testChildExtendsParentInvalidParentTest($childSchema, $parentSchema)
8279
{
83-
$retrieverMock = $this->getRetrieverMock($parentSchema);
80+
$this->mockRetriever($parentSchema);
8481

8582
$json = '{"childProp":"infant", "parentProp":1}';
8683
$decodedJson = json_decode($json);
8784
$decodedJsonSchema = json_decode($childSchema);
8885

89-
$this->validator->setUriRetriever($retrieverMock);
9086
$this->validator->check($decodedJson, $decodedJsonSchema);
9187
$this->assertFalse($this->validator->isValid());
9288
}
@@ -97,12 +93,12 @@ public function testChildExtendsParentInvalidParentTest($childSchema, $parentSch
9793
public function testResolveRelativeUri($childSchema, $parentSchema)
9894
{
9995
self::setParentSchemaExtendsValue($parentSchema, 'grandparent');
100-
$retrieverMock = $this->getRetrieverMock($parentSchema);
96+
$this->mockRetriever($parentSchema);
97+
10198
$json = '{"childProp":"infant", "parentProp":false}';
10299
$decodedJson = json_decode($json);
103100
$decodedJsonSchema = json_decode($childSchema);
104101

105-
$this->validator->setUriRetriever($retrieverMock);
106102
$this->validator->check($decodedJson, $decodedJsonSchema);
107103
$this->assertTrue($this->validator->isValid());
108104
}
@@ -269,4 +265,17 @@ public function testConfirmMediaTypeThrowsExceptionForUnsupportedTypes()
269265

270266
$this->assertEquals(null, $retriever->confirmMediaType($retriever, null));
271267
}
268+
269+
private function mockRetriever($schema)
270+
{
271+
$retrieverMock = $this->getRetrieverMock($schema);
272+
273+
$factory = new \ReflectionProperty('JsonSchema\Constraints\Constraint', 'factory');
274+
$factory->setAccessible(true);
275+
$factory = $factory->getValue($this->validator);
276+
277+
$retriever = new \ReflectionProperty('JsonSchema\Constraints\Factory', 'uriRetriever');
278+
$retriever->setAccessible(true);
279+
$retriever->setValue($factory, $retrieverMock);
280+
}
272281
}

0 commit comments

Comments
 (0)