Skip to content

Commit bbd19bb

Browse files
authored
Merge pull request #17 from swaggest/ajv-further
better ajv tests compliance
2 parents 2589ae7 + ab6dbb4 commit bbd19bb

File tree

13 files changed

+209
-88
lines changed

13 files changed

+209
-88
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
vendor
22
.idea
33
composer.lock
4-
cover.xml
5-
build
4+
composer.phar
5+
clover.xml
6+
build

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ cache:
2121
before_script:
2222
- composer install --dev --no-interaction --prefer-dist
2323
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then test -f $HOME/.composer/cache/phpstan.phar || wget https://github.com/phpstan/phpstan/releases/download/0.9.1/phpstan.phar -O $HOME/.composer/cache/phpstan.phar; fi
24-
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then test -f $HOME/.composer/cache/ocular.phar || wget https://scrutinizer-ci.com/ocular.phar -O ocular.phar; fi
24+
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then test -f $HOME/.composer/cache/ocular.phar || wget https://scrutinizer-ci.com/ocular.phar -O $HOME/.composer/cache/ocular.phar; fi
2525
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then test -f $HOME/.composer/cache/cctr || wget https://codeclimate.com/downloads/test-reporter/test-reporter-0.1.4-linux-amd64 -O $HOME/.composer/cache/cctr && chmod +x $HOME/.composer/cache/cctr; fi
2626
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then $HOME/.composer/cache/cctr before-build; fi
2727

@@ -32,10 +32,9 @@ matrix:
3232
fast_finish: true
3333

3434
script:
35-
- mkdir -p build/logs
36-
- ./vendor/bin/phpunit -v --configuration phpunit.xml --coverage-clover build/logs/clover.xml
35+
- ./vendor/bin/phpunit -v --configuration phpunit.xml --coverage-text --coverage-clover clover.xml
3736
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then php $HOME/.composer/cache/phpstan.phar analyze -l 7 -c phpstan.neon ./src; fi
3837

3938
after_script:
40-
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then php $HOME/.composer/cache/ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.clover; fi
39+
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then php $HOME/.composer/cache/ocular.phar code-coverage:upload --format=php-clover clover.xml; fi
4140
- if [[ $(phpenv version-name) =~ 7.2 ]] ; then $HOME/.composer/cache/cctr after-build --exit-code $TRAVIS_TEST_RESULT; fi

spec/ajv

Submodule ajv updated from ef40fbb to 2726d29

src/Constraint/Ref.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ public function setData($data)
5656

5757
/**
5858
* @return mixed
59-
* @throws \Exception
6059
*/
6160
public function getData()
6261
{

src/Context.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class Context extends MagicMap
3333
/** @var bool do not tolerate special symbols even if base64_decode accepts string */
3434
public $strictBase64Validation = false;
3535

36+
/** @var bool pack/unpack application/json in string content */
3637
public $unpackContentMediaType = true;
3738

3839
/** @var string property mapping set name */

src/RefResolver.php

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

33
namespace Swaggest\JsonSchema;
44

5+
use PhpLang\ScopeExit;
56
use Swaggest\JsonSchema\Constraint\Ref;
67
use Swaggest\JsonSchema\RemoteRef\BasicFetcher;
78

@@ -100,6 +101,12 @@ public function __construct($rootData = null)
100101
$this->rootData = $rootData;
101102
}
102103

104+
public function setRootData($rootData)
105+
{
106+
$this->rootData = $rootData;
107+
return $this;
108+
}
109+
103110

104111
public function setRemoteRefProvider(RemoteRefProvider $provider)
105112
{
@@ -115,16 +122,10 @@ private function getRefProvider()
115122
return $this->refProvider;
116123
}
117124

118-
private function registerIdData($id, $data)
119-
{
120-
121-
}
122-
123-
124125
/**
125126
* @param string $referencePath
126127
* @return Ref
127-
* @throws \Exception
128+
* @throws InvalidValue
128129
*/
129130
public function resolveReference($referencePath)
130131
{
@@ -185,6 +186,7 @@ public function resolveReference($referencePath)
185186
$rootResolver = $this->rootResolver ? $this->rootResolver : $this;
186187
/** @var null|RefResolver $refResolver */
187188
$refResolver = &$rootResolver->remoteRefResolvers[$url];
189+
$this->setResolutionScope($url);
188190
if (null === $refResolver) {
189191
$rootData = $rootResolver->getRefProvider()->getSchemaData($url);
190192
$refResolver = new RefResolver($rootData);
@@ -203,4 +205,52 @@ public function resolveReference($referencePath)
203205
}
204206

205207

208+
/**
209+
* @param mixed $data
210+
* @param Context $options
211+
* @param int $nestingLevel
212+
* @throws Exception
213+
*/
214+
public function preProcessReferences($data, Context $options, $nestingLevel = 0)
215+
{
216+
if ($nestingLevel > 200) {
217+
throw new Exception('Too deep nesting level', Exception::DEEP_NESTING);
218+
}
219+
if (is_array($data)) {
220+
foreach ($data as $key => $item) {
221+
$this->preProcessReferences($item, $options, $nestingLevel + 1);
222+
}
223+
} elseif ($data instanceof \stdClass) {
224+
/** @var JsonSchema $data */
225+
if (
226+
isset($data->{Schema::ID_D4})
227+
&& is_string($data->{Schema::ID_D4})
228+
&& (($options->version === Schema::VERSION_AUTO) || $options->version === Schema::VERSION_DRAFT_04)
229+
) {
230+
$prev = $this->setupResolutionScope($data->{Schema::ID_D4}, $data);
231+
/** @noinspection PhpUnusedLocalVariableInspection */
232+
$_ = new ScopeExit(function () use ($prev) {
233+
$this->setResolutionScope($prev);
234+
});
235+
}
236+
237+
if (isset($data->{Schema::ID})
238+
&& is_string($data->{Schema::ID})
239+
&& (($options->version === Schema::VERSION_AUTO) || $options->version >= Schema::VERSION_DRAFT_06)
240+
) {
241+
$prev = $this->setupResolutionScope($data->{Schema::ID}, $data);
242+
/** @noinspection PhpUnusedLocalVariableInspection */
243+
$_ = new ScopeExit(function () use ($prev) {
244+
$this->setResolutionScope($prev);
245+
});
246+
}
247+
248+
249+
foreach ((array)$data as $key => $value) {
250+
$this->preProcessReferences($value, $options, $nestingLevel + 1);
251+
}
252+
}
253+
}
254+
255+
206256
}

src/RemoteRef/Preloaded.php

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,70 @@
22

33
namespace Swaggest\JsonSchema\RemoteRef;
44

5+
use Swaggest\JsonSchema\Context;
6+
use Swaggest\JsonSchema\RefResolver;
57
use Swaggest\JsonSchema\RemoteRefProvider;
8+
use Swaggest\JsonSchema\Schema;
69

710
class Preloaded implements RemoteRefProvider
811
{
912
private $storage;
1013

14+
private $schemaFiles;
15+
1116
public function __construct()
1217
{
13-
$this->setSchemaData('http://json-schema.org/draft-04/schema',
14-
json_decode(file_get_contents(__DIR__ . '/../../spec/json-schema.json')));
15-
$this->setSchemaData('http://json-schema.org/draft-06/schema',
16-
json_decode(file_get_contents(__DIR__ . '/../../spec/json-schema-draft6.json')));
17-
$this->setSchemaData('http://json-schema.org/draft-07/schema',
18-
json_decode(file_get_contents(__DIR__ . '/../../spec/json-schema-draft7.json')));
18+
$this->schemaFiles = array(
19+
'http://json-schema.org/draft-04/schema' => __DIR__ . '/../../spec/json-schema.json',
20+
'http://json-schema.org/draft-06/schema' => __DIR__ . '/../../spec/json-schema-draft6.json',
21+
'http://json-schema.org/draft-07/schema' => __DIR__ . '/../../spec/json-schema-draft7.json',
22+
);
1923
}
2024

2125
public function getSchemaData($url)
2226
{
2327
if (isset($this->storage[$url])) {
2428
return $this->storage[$url];
29+
} elseif (isset($this->schemaFiles[$url])) {
30+
$this->storage[$url] = json_decode(file_get_contents($this->schemaFiles[$url]));
31+
return $this->storage[$url];
2532
}
2633
return false;
2734
}
2835

36+
/**
37+
* @param RefResolver $refResolver
38+
* @param Context|null $options
39+
* @throws \Swaggest\JsonSchema\Exception
40+
*/
41+
public function populateSchemas(RefResolver $refResolver, Context $options = null)
42+
{
43+
if ($options === null) {
44+
$options = new Context();
45+
$options->refResolver = $refResolver;
46+
$options->version = Schema::VERSION_AUTO;
47+
}
48+
49+
$prev = $refResolver->getResolutionScope();
50+
foreach ($this->storage as $url => $schemaData) {
51+
$refResolver->setupResolutionScope($url, $schemaData);
52+
$refResolver->setResolutionScope($url);
53+
$refResolver->preProcessReferences($schemaData, $options);
54+
}
55+
$refResolver->setResolutionScope($prev);
56+
}
57+
2958
public function setSchemaData($url, $schemaData)
3059
{
3160
$this->storage[$url] = $schemaData;
3261
return $this;
3362
}
3463

64+
public function setSchemaFile($url, $path)
65+
{
66+
$this->schemaFiles[$url] = $path;
67+
return $this;
68+
}
69+
3570

3671
}

src/Schema.php

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ class Schema extends JsonSchema implements MetaHolder
4040
const VERSION_DRAFT_06 = 6;
4141
const VERSION_DRAFT_07 = 7;
4242

43-
const SCHEMA_DRAFT_04_URL = 'http://json-schema.org/draft-04/schema';
44-
4543
const REF = '$ref';
4644
const ID = '$id';
4745
const ID_D4 = 'id';
@@ -108,47 +106,6 @@ public function addPropertyMapping($dataName, $propertyName, $mapping = self::DE
108106
return $this;
109107
}
110108

111-
private function preProcessReferences($data, Context $options, $nestingLevel = 0)
112-
{
113-
if ($nestingLevel > 200) {
114-
throw new Exception('Too deep nesting level', Exception::DEEP_NESTING);
115-
}
116-
if (is_array($data)) {
117-
foreach ($data as $key => $item) {
118-
$this->preProcessReferences($item, $options, $nestingLevel + 1);
119-
}
120-
} elseif ($data instanceof \stdClass) {
121-
/** @var JsonSchema $data */
122-
if (
123-
isset($data->{Schema::ID_D4})
124-
&& is_string($data->{Schema::ID_D4})
125-
&& (($options->version === self::VERSION_AUTO) || $options->version === self::VERSION_DRAFT_04)
126-
) {
127-
$prev = $options->refResolver->setupResolutionScope($data->{Schema::ID_D4}, $data);
128-
/** @noinspection PhpUnusedLocalVariableInspection */
129-
$_ = new ScopeExit(function () use ($prev, $options) {
130-
$options->refResolver->setResolutionScope($prev);
131-
});
132-
}
133-
134-
if (isset($data->{self::ID})
135-
&& is_string($data->{self::ID})
136-
&& (($options->version === self::VERSION_AUTO) || $options->version >= self::VERSION_DRAFT_06)
137-
) {
138-
$prev = $options->refResolver->setupResolutionScope($data->{self::ID}, $data);
139-
/** @noinspection PhpUnusedLocalVariableInspection */
140-
$_ = new ScopeExit(function () use ($prev, $options) {
141-
$options->refResolver->setResolutionScope($prev);
142-
});
143-
}
144-
145-
146-
foreach ((array)$data as $key => $value) {
147-
$this->preProcessReferences($value, $options, $nestingLevel + 1);
148-
}
149-
}
150-
}
151-
152109
public static function import($data, Context $options = null)
153110
{
154111
// string $data is expected to be $ref uri
@@ -160,6 +117,14 @@ public static function import($data, Context $options = null)
160117
return parent::import($data, $options);
161118
}
162119

120+
/**
121+
* @param mixed $data
122+
* @param Context|null $options
123+
* @return array|mixed|null|object|\stdClass
124+
* @throws Exception
125+
* @throws InvalidValue
126+
* @throws \Exception
127+
*/
163128
public function in($data, Context $options = null)
164129
{
165130
if ($options === null) {
@@ -168,13 +133,18 @@ public function in($data, Context $options = null)
168133

169134
$options->import = true;
170135

171-
$options->refResolver = new RefResolver($data);
136+
if ($options->refResolver === null) {
137+
$options->refResolver = new RefResolver($data);
138+
} else {
139+
$options->refResolver->setRootData($data);
140+
}
141+
172142
if ($options->remoteRefProvider) {
173143
$options->refResolver->setRemoteRefProvider($options->remoteRefProvider);
174144
}
175145

176146
if ($options->import) {
177-
$this->preProcessReferences($data, $options);
147+
$options->refResolver->preProcessReferences($data, $options);
178148
}
179149

180150
return $this->process($data, $options, '#');
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Swaggest\JsonSchema\Tests\PHPUnit\Ref;
4+
5+
6+
use Swaggest\JsonSchema\Exception;
7+
use Swaggest\JsonSchema\RefResolver;
8+
use Swaggest\JsonSchema\RemoteRef\Preloaded;
9+
10+
class InnerScopeTest extends \PHPUnit_Framework_TestCase
11+
{
12+
public function testInnerDef()
13+
{
14+
$p = new Preloaded();
15+
$p->setSchemaData('http://localhost:1234/scope_change.json',
16+
json_decode(file_get_contents(__DIR__ . '/../../../../spec/ajv/spec/remotes/scope_change.json')));
17+
$r = new RefResolver();
18+
$r->setRemoteRefProvider($p);
19+
try {
20+
$p->populateSchemas($r);
21+
$ref = $r->resolveReference('http://localhost:1234/scope_foo.json#/definitions/bar');
22+
$this->assertEquals((object)array('type' => 'string'), $ref->getData());
23+
} catch (Exception $e) {
24+
$this->fail($e->getMessage());
25+
}
26+
}
27+
28+
}

tests/src/PHPUnit/RefTest.php renamed to tests/src/PHPUnit/Ref/RefTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<?php
22

3-
namespace Swaggest\JsonSchema\Tests\PHPUnit;
4-
3+
namespace Swaggest\JsonSchema\Tests\PHPUnit\Ref;
54

65
use Swaggest\JsonSchema\Context;
76
use Swaggest\JsonSchema\Exception\LogicException;
@@ -135,7 +134,7 @@ public function testRemoteRef()
135134
$refProvider->setSchemaData(
136135
'http://localhost:1234/subSchemas.json',
137136
json_decode(file_get_contents(
138-
__DIR__ . '/../../../spec/JSON-Schema-Test-Suite/remotes/subSchemas.json'
137+
__DIR__ . '/../../../../spec/JSON-Schema-Test-Suite/remotes/subSchemas.json'
139138
))
140139
);
141140

0 commit comments

Comments
 (0)