diff --git a/src/Transformer.php b/src/Transformer.php index f6dde8e..0a89042 100644 --- a/src/Transformer.php +++ b/src/Transformer.php @@ -111,15 +111,13 @@ private function resolveReference($ref, $context, $root, bool &$found = null) { $context = $root; } - if (!is_array($context)) { - $found = false; - return null; - } - $parts = self::explodeRef($ref); $result = $context; foreach ($parts as $key) { - if (array_key_exists($key, $result)) { + if (!is_array($result)) { + $found = false; + return null; + } elseif (array_key_exists($key, $result)) { $result = $result[$key]; } else { $found = false; @@ -146,7 +144,7 @@ private static function escapeRef(string $field): string { * @param string $str The segment to unescapeRef. * @return string Returns the unescaped string. */ - public static function unescapeRef(string $str): string { + private static function unescapeRef(string $str): string { return str_replace(['~2', '~1', '~0'], ['$', '/', '~'], $str); } diff --git a/tests/BasicTransformsTest.php b/tests/BasicTransformsTest.php index 24beae4..7789f1b 100644 --- a/tests/BasicTransformsTest.php +++ b/tests/BasicTransformsTest.php @@ -30,8 +30,9 @@ public function testTransform(array $spec, array $expected) { 'bar' => 'foo', ], 'a~b' => 'c', - 'a/b' => 'c', - 'a$b' => 'c', + 'a/b' => 'd', + 'a$b' => 'e', + '~/$' => 'f' ]; $t = new Transformer($spec); @@ -51,12 +52,14 @@ public function provideTransformTests(): array { 'basic ref' => [['foo' => 'nested/bar'], ['foo' => 'foo']], 'basic nested' => [['nested' => ['foo' => '/foo']], ['nested' => ['foo' => 'baz']]], 'escape ~' => [['a' => 'a~0b'], ['a' => 'c']], - 'escape /' => [['a' => 'a~1b'], ['a' => 'c']], - 'escape $' => [['a' => 'a~2b'], ['a' => 'c']], + 'escape /' => [['a' => 'a~1b'], ['a' => 'd']], + 'escape $' => [['a' => 'a~2b'], ['a' => 'e']], + 'escape all' => [['a' => '~0~1~2'], ['a' => 'f']], 'not found' => [['a' => 'xdsd'], []], 'not found default' => [['a' => ['$ref' => 'xdsd', '$default' => 'b']], ['a' => 'b']], 'literal' => [['a' => ['$literal' => 'abc']], ['a' => 'abc']], - + 'escaped dest' => [['a/b' => 'foo'], ['a/b' => 'baz']], + 'ref to non-array' => [['a' => 'bar/baz'], []], ]; return $r; @@ -67,6 +70,7 @@ public function provideTransformTests(): array { * * @expectedException \Garden\JSON\InvalidSpecException * @expectedExceptionMessageRegExp `^Invalid spec value` + * @expectedExceptionCode 500 */ public function testInvalidSpec() { $t = new Transformer(['foo' => true]); @@ -79,6 +83,7 @@ public function testInvalidSpec() { * * @expectedException \Garden\JSON\InvalidSpecException * @expectedExceptionMessageRegExp `^Invalid control expression` + * @expectedExceptionCode 500 */ public function testInvalidControlExpression() { $t = new Transformer(['$foo' => 'bar']); @@ -112,9 +117,23 @@ public function testNumericRelativeArray() { $this->assertSame(['b', 'a'], $actual); } + /** + * Transformer should be callable on a non-array. + */ public function testNonArrayContext() { $t = new Transformer('/foo'); $actual = $t('baz'); $this->assertSame(null, $actual); } + + /** + * Paths should be escaped in error messages. + * + * @expectedException \Garden\JSON\InvalidSpecException + * @expectedExceptionMessage Invalid spec value at /~0~1~2. + */ + public function testEscapePath() { + $t = new Transformer(['~/$' => true]); + $t(['~/$' => 'a']); + } }