@@ -125,25 +125,37 @@ public function resolve($uri, $baseUri = null)
125125 public static function combineRelativePathWithBasePath ($ relativePath , $ basePath )
126126 {
127127 $ relativePath = self ::normalizePath ($ relativePath );
128- if ($ relativePath == '' ) {
128+ if (! $ relativePath ) {
129129 return $ basePath ;
130130 }
131- if ($ relativePath [0 ] == '/ ' ) {
131+ if ($ relativePath [0 ] === '/ ' ) {
132132 return $ relativePath ;
133133 }
134-
135- $ basePathSegments = explode ('/ ' , $ basePath );
136-
137- preg_match ('|^/?(\.\./(?:\./)*)*| ' , $ relativePath , $ match );
138- $ numLevelUp = strlen ($ match [0 ]) /3 + 1 ;
139- if ($ numLevelUp >= count ($ basePathSegments )) {
134+ if (!$ basePath ) {
140135 throw new UriResolverException (sprintf ("Unable to resolve URI '%s' from base '%s' " , $ relativePath , $ basePath ));
141136 }
142137
143- $ basePathSegments = array_slice ($ basePathSegments , 0 , -$ numLevelUp );
144- $ path = preg_replace ('|^/?(\.\./(\./)*)*| ' , '' , $ relativePath );
138+ $ dirname = $ basePath [strlen ($ basePath ) - 1 ] === '/ ' ? $ basePath : dirname ($ basePath );
139+ $ combined = rtrim ($ dirname , '/ ' ) . '/ ' . ltrim ($ relativePath , '/ ' );
140+ $ combinedSegments = explode ('/ ' , $ combined );
141+ $ collapsedSegments = array ();
142+ while ($ combinedSegments ) {
143+ $ segment = array_shift ($ combinedSegments );
144+ if ($ segment === '.. ' ) {
145+ if (count ($ collapsedSegments ) <= 1 ) {
146+ // Do not remove the top level (domain)
147+ // This is not ideal - the domain should not be part of the path here. parse() and generate()
148+ // should handle the "domain" separately, like the schema.
149+ // Then the if-condition here would be `if (!$collapsedSegments) {`.
150+ throw new UriResolverException (sprintf ("Unable to resolve URI '%s' from base '%s' " , $ relativePath , $ basePath ));
151+ }
152+ array_pop ($ collapsedSegments );
153+ } else {
154+ $ collapsedSegments [] = $ segment ;
155+ }
156+ }
145157
146- return implode ('/ ' , $ basePathSegments ) . ' / ' . $ path ;
158+ return implode ('/ ' , $ collapsedSegments ) ;
147159 }
148160
149161 /**
0 commit comments