Skip to content

Commit ef13b9b

Browse files
thewilkybarkidbighappyface
authored andcommitted
Cache the results of RefResolver::resolve() (#290)
* Cache the results of RefResolver::resolve() * Add test
1 parent 58b6e07 commit ef13b9b

File tree

2 files changed

+35
-22
lines changed

2 files changed

+35
-22
lines changed

src/JsonSchema/RefResolver.php

+12-22
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class RefResolver
3030
/** @var UriResolverInterface */
3131
private $uriResolver;
3232

33+
private $paths = array();
34+
3335
/**
3436
* @param UriRetrieverInterface $retriever
3537
* @param UriResolverInterface $uriResolver
@@ -48,26 +50,16 @@ public function __construct(UriRetrieverInterface $retriever, UriResolverInterfa
4850
* @return object
4951
*/
5052
public function resolve($sourceUri)
51-
{
52-
return $this->resolveCached($sourceUri, array());
53-
}
54-
55-
/**
56-
* @param string $sourceUri URI where this schema was located
57-
* @param array $paths
58-
* @return object
59-
*/
60-
private function resolveCached($sourceUri, array $paths)
6153
{
6254
$jsonPointer = new JsonPointer($sourceUri);
6355

6456
$fileName = $jsonPointer->getFilename();
65-
if (!array_key_exists($fileName, $paths)) {
57+
if (!array_key_exists($fileName, $this->paths)) {
6658
$schema = $this->uriRetriever->retrieve($jsonPointer->getFilename());
67-
$paths[$jsonPointer->getFilename()] = $schema;
68-
$this->resolveSchemas($schema, $jsonPointer->getFilename(), $paths);
59+
$this->paths[$jsonPointer->getFilename()] = $schema;
60+
$this->resolveSchemas($schema, $jsonPointer->getFilename());
6961
}
70-
$schema = $paths[$fileName];
62+
$schema = $this->paths[$fileName];
7163

7264
return $this->getRefSchema($jsonPointer, $schema);
7365
}
@@ -77,16 +69,15 @@ private function resolveCached($sourceUri, array $paths)
7769
*
7870
* @param object $unresolvedSchema
7971
* @param string $fileName
80-
* @param array $paths
8172
*/
82-
private function resolveSchemas($unresolvedSchema, $fileName, array $paths)
73+
private function resolveSchemas($unresolvedSchema, $fileName)
8374
{
8475
$objectIterator = new ObjectIterator($unresolvedSchema);
8576
foreach ($objectIterator as $toResolveSchema) {
8677
if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
8778
$jsonPointer = new JsonPointer($this->uriResolver->resolve($toResolveSchema->{'$ref'}, $fileName));
88-
$refSchema = $this->resolveCached((string) $jsonPointer, $paths);
89-
$this->unionSchemas($refSchema, $toResolveSchema, $fileName, $paths);
79+
$refSchema = $this->resolve((string) $jsonPointer);
80+
$this->unionSchemas($refSchema, $toResolveSchema, $fileName);
9081
}
9182
}
9283
}
@@ -120,14 +111,13 @@ private function getRefSchema(JsonPointer $jsonPointer, $refSchema)
120111
* @param object $refSchema
121112
* @param object $schema
122113
* @param string $fileName
123-
* @param array $paths
124114
*/
125-
private function unionSchemas($refSchema, $schema, $fileName, array $paths)
115+
private function unionSchemas($refSchema, $schema, $fileName)
126116
{
127117
if (property_exists($refSchema, '$ref')) {
128118
$jsonPointer = new JsonPointer($this->uriResolver->resolve($refSchema->{'$ref'}, $fileName));
129-
$newSchema = $this->resolveCached((string) $jsonPointer, $paths);
130-
$this->unionSchemas($newSchema, $refSchema, $fileName, $paths);
119+
$newSchema = $this->resolve((string) $jsonPointer);
120+
$this->unionSchemas($newSchema, $refSchema, $fileName);
131121
}
132122

133123
unset($schema->{'$ref'});

tests/RefResolverTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,29 @@ function testUnresolvableJsonPointExceptionShouldBeThrown()
112112
$refResolver->resolve('http://www.example.com/schema.json');
113113
}
114114

115+
public function testExternalReferencesLoadedOnlyOnce()
116+
{
117+
$mainSchema = $this->getMainSchema();
118+
$schema2 = $this->getSchema2();
119+
$schema3 = $this->getSchema3();
120+
121+
/** @var UriRetriever $uriRetriever */
122+
$uriRetriever = $this->prophesize('JsonSchema\UriRetrieverInterface');
123+
$uriRetriever->retrieve('http://www.example.com/schema.json')
124+
->willReturn($mainSchema)
125+
->shouldBeCalledTimes(1);
126+
$uriRetriever->retrieve('http://www.my-domain.com/schema2.json')
127+
->willReturn($schema2)
128+
->shouldBeCalledTimes(1);
129+
$uriRetriever->retrieve('http://www.my-domain.com/schema3.json')
130+
->willReturn($schema3)
131+
->shouldBeCalledTimes(1);
132+
133+
$refResolver = new RefResolver($uriRetriever->reveal(), new UriResolver());
134+
$refResolver->resolve('http://www.example.com/schema.json');
135+
$refResolver->resolve('http://www.example.com/schema.json');
136+
}
137+
115138
/**
116139
* @return object
117140
*/

0 commit comments

Comments
 (0)