diff --git a/src/Parser.php b/src/Parser.php index fbb322a..d36471f 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -71,7 +71,17 @@ class Parser implements \IteratorAggregate, PositionAware } $intersectingJsonPointers = array_filter($jsonPointers, static function($el) use ($jsonPointerEl) { - return $jsonPointerEl !== $el && strpos($jsonPointerEl, $el) === 0; + if ($jsonPointerEl === $el) { + return false; + } + + if (strpos($jsonPointerEl, $el) === 0) { + return true; + } + + $elWildcard = preg_replace('~/\d+(/|$)~', '/-$1', $el); + + return strpos($jsonPointerEl, $elWildcard) === 0; }); if (!empty($intersectingJsonPointers)) { @@ -93,18 +103,24 @@ class Parser implements \IteratorAggregate, PositionAware */ private function getMatchingJsonPointerPath($currentPath) { + $matchingPointer = key($this->jsonPointerPaths); + if (count($this->jsonPointerPaths) === 1) { + $this->currentJsonPointer = $matchingPointer; return current($this->jsonPointerPaths); } - $matchingPointer = key($this->jsonPointerPaths); + $currentPathLength = count($currentPath); $matchLength = -1; foreach ($this->jsonPointerPaths as $jsonPointer => $jsonPointerPath) { $matchingParts = []; foreach ($jsonPointerPath as $i => $jsonPointerPathEl) { - if (!isset($currentPath[$i]) || $currentPath[$i] !== $jsonPointerPathEl) { + if ( + !isset($currentPath[$i]) + || preg_replace('~/\d+(/|$)~', '/-$1', $currentPath[$i]) !== preg_replace('~/\d+(/|$)~', '/-$1', $jsonPointerPathEl) + ) { continue; } @@ -121,6 +137,10 @@ class Parser implements \IteratorAggregate, PositionAware $matchingPointer = $jsonPointer; $matchLength = $currentMatchLength; } + + if ($matchLength === $currentPathLength) { + break; + } } $this->currentJsonPointer = $matchingPointer; diff --git a/test/JsonMachineTest/ParserTest.php b/test/JsonMachineTest/ParserTest.php index 1728cc6..4e68350 100644 --- a/test/JsonMachineTest/ParserTest.php +++ b/test/JsonMachineTest/ParserTest.php @@ -294,6 +294,12 @@ class ParserTest extends \PHPUnit_Framework_TestCase } } + public function testIntersectingPaths() + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("JSON Pointers must not intersect: '/companies/-/id' is within '/companies/0/id'"); + $this->createParser(new \ArrayObject(), ['/companies/-/id', '/companies/0/id']); + } private function createParser($json, $jsonPointer = '') {