Skip to content

Commit 304f3e7

Browse files
committed
improve fragment resolving for extend
1 parent a189cd0 commit 304f3e7

2 files changed

Lines changed: 105 additions & 11 deletions

File tree

src/JsonSchema/Uri/UriResolver.php

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@ public function parse($uri)
5454
*/
5555
public function generate(array $components)
5656
{
57-
$uri = $components['scheme'] . '://'
58-
. $components['authority']
57+
$uri = '';
58+
if(!empty($components['scheme'])) $uri = $components['scheme'] . '://';
59+
60+
$uri .= $components['authority']
5961
. $components['path'];
60-
61-
if (array_key_exists('query', $components)) {
62-
$uri .= $components['query'];
62+
63+
if (array_key_exists('query', $components) && !empty($components['query'])) {
64+
$uri .= '?'.$components['query'];
6365
}
64-
if (array_key_exists('fragment', $components)) {
65-
$uri .= $components['fragment'];
66+
if (array_key_exists('fragment', $components) && !empty($components['fragment'])) {
67+
$uri .= '#'.$components['fragment'];
6668
}
6769

6870
return $uri;
@@ -87,10 +89,28 @@ public function resolve($uri, $baseUri = null)
8789
$basePath = $baseComponents['path'];
8890

8991
$baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
90-
92+
if(!empty($components['fragment'])) $baseComponents['fragment'] = $components['fragment'];
93+
94+
return $this->generate($baseComponents);
95+
}
96+
97+
public function resolveWithoutFragment($uri, $baseUri = null)
98+
{
99+
$components = $this->parse($uri);
100+
$path = $components['path'];
101+
102+
if (! empty($components['scheme'])) {
103+
return $uri;
104+
}
105+
$baseComponents = $this->parse($baseUri);
106+
$basePath = $baseComponents['path'];
107+
108+
$baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
109+
110+
unset($baseComponents['fragment']);
111+
91112
return $this->generate($baseComponents);
92113
}
93-
94114
/**
95115
* Tries to glue a relative path onto an absolute one
96116
*
@@ -99,11 +119,12 @@ public function resolve($uri, $baseUri = null)
99119
* @return string Merged path
100120
* @throws UriResolverException
101121
*/
102-
private static function combineRelativePathWithBasePath($relativePath, $basePath)
122+
static function combineRelativePathWithBasePath($relativePath, $basePath)
103123
{
104124
$relativePath = self::normalizePath($relativePath);
105125
$basePathSegments = self::getPathSegments($basePath);
106-
126+
127+
if($relativePath == '') return $basePath;
107128
preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
108129
$numLevelUp = strlen($match[0]) /3 + 1;
109130
if ($numLevelUp >= count($basePathSegments)) {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace JsonSchema\Tests\Uri;
4+
5+
use JsonSchema\Uri\UriResolver;
6+
7+
class UriResolverTest extends \PHPUnit_Framework_TestCase {
8+
9+
function testParseWithFragment() {
10+
$resolver = new UriResolver();
11+
$this->assertEquals(
12+
array('scheme' => 'file', 'authority' => '', 'path' => '/the/directory', 'query'=>'', 'fragment' => '/the/fragment')
13+
,$resolver->parse('file:///the/directory#/the/fragment')
14+
);
15+
}
16+
17+
function testParseWithQuery() {
18+
$resolver = new UriResolver();
19+
$this->assertEquals(
20+
array('scheme' => 'file', 'authority' => '', 'path' => '/the/directory', 'query'=>'the=query&key=val')
21+
,$resolver->parse('file:///the/directory?the=query&key=val')
22+
);
23+
}
24+
25+
function testParseWithHttp() {
26+
$resolver = new UriResolver();
27+
$this->assertEquals(
28+
array('scheme' => 'http', 'authority' => 'localhost:1234', 'path' => '/the/directory')
29+
,$resolver->parse('http://localhost:1234/the/directory')
30+
);
31+
}
32+
33+
function testParseFragmentOnly() {
34+
$resolver = new UriResolver();
35+
$this->assertEquals(
36+
array('scheme' => '', 'authority' => '', 'path' => '', 'query'=>'', 'fragment' => '/theFragment')
37+
,$resolver->parse('#/theFragment')
38+
);
39+
}
40+
41+
function testResolveWithBothHttp() {
42+
$resolver = new UriResolver();
43+
$this->setExpectedException('JsonSchema\Exception\UriResolverException', "Unable to resolve URI '/the/path' from base ''");
44+
$this->assertEquals('http://localhost:1234/the/path', $resolver->resolve('/the/path', 'http://localhost:1234'));
45+
}
46+
47+
function testResolveWithValidHttpBaseUri() {
48+
$resolver = new UriResolver();
49+
50+
$this->assertEquals('http://localhost:1234/the/other/schema.json' , $resolver->resolve('/the/other/schema.json' , 'http://localhost:1234/'));
51+
$this->assertEquals('http://localhost:1234/other/foo.json' , $resolver->resolve('/other/foo.json' , 'http://localhost:1234/schema.json'));
52+
$this->assertEquals('http://localhost:1234/foo.json#/fragment' , $resolver->resolve('/foo.json#/fragment' , 'http://localhost:1234/schma.json'));
53+
$this->assertEquals('http://localhost:1234/three/dirs/bar.json' , $resolver->resolve('bar.json' , 'http://localhost:1234/three/dirs/schema.json'));
54+
$this->assertEquals('http://localhost:1234/sourceSchema.json#/localTarget' , $resolver->resolve('#/localTarget' , 'http://localhost:1234/sourceSchema.json#/sourceNode'));
55+
}
56+
57+
function testResolveWithValidFileBaseUri() {
58+
$resolver = new UriResolver();
59+
$this->assertEquals('file:///base/uri/foo.json', $resolver->resolve('foo.json', 'file:///base/uri/dir.json'));
60+
$this->assertEquals('file:///other-dir/foo.json', $resolver->resolve('file:///other-dir/foo.json', 'file:///base/uri/dir.json'));
61+
62+
}
63+
64+
function testCombineRelativePathWithBasePath() {
65+
$this->assertEquals('/foo/bar/boo', UriResolver::combineRelativePathWithBasePath('boo', '/foo/bar/'));
66+
$this->assertEquals('/foo/bar/' , UriResolver::combineRelativePathWithBasePath('', '/foo/bar/'));
67+
$this->assertEquals('/foo/bar' , UriResolver::combineRelativePathWithBasePath('', '/foo/bar'));
68+
// ??? imho /boo
69+
$this->assertEquals('/foo/bar/boo' , UriResolver::combineRelativePathWithBasePath('/boo', '/foo/bar/'));
70+
$this->assertEquals('/foo.json' , UriResolver::combineRelativePathWithBasePath('', '/foo.json'));
71+
72+
}
73+
}

0 commit comments

Comments
 (0)