From 0d89091ad5731b1d3f98f96f06441f49b0eeb508 Mon Sep 17 00:00:00 2001 From: ignace namagana butera Date: Thu, 30 Jan 2020 08:47:47 +0100 Subject: [PATCH] Improve filter variables --- src/UriTemplate.php | 81 ++++++++++++++++++++++----------------- tests/UriTemplateTest.php | 7 +++- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/UriTemplate.php b/src/UriTemplate.php index 8b858963..a4dbfdb6 100644 --- a/src/UriTemplate.php +++ b/src/UriTemplate.php @@ -251,7 +251,9 @@ private function parseVariableSpecification(array $expression, array $foundVaria } /** - * Filter out the value whose key is not a valid variable name for the given template. + * Filters out variables for the given template. + * + * @return array> */ private function filterVariables(array $variables): array { @@ -259,7 +261,47 @@ private function filterVariables(array $variables): array return in_array($key, $this->variableNames, true); }; - return array_filter($variables, $filter, ARRAY_FILTER_USE_KEY); + $result = array_filter($variables, $filter, ARRAY_FILTER_USE_KEY); + foreach ($result as $name => &$value) { + $value = $this->normalizeValue($name, $value, true); + } + unset($value); + + return $result; + } + + /** + * @param mixed $value the value to be expanded + * + * @throws \TypeError if the type is not supported + * @throws TemplateCanNotBeExpanded if the value contains nested list + * + * @return string|array + */ + private function normalizeValue(string $name, $value, bool $isNestedListAllowed) + { + if (is_array($value)) { + if (!$isNestedListAllowed) { + throw TemplateCanNotBeExpanded::dueToNestedListOfValue($name); + } + + foreach ($value as &$var) { + $var = $this->normalizeValue($name, $var, false); + } + unset($var); + + return $value; + } + + if (is_bool($value)) { + return true === $value ? '1' : '0'; + } + + if (null === $value || is_scalar($value) || method_exists($value, '__toString')) { + return (string) $value; + } + + throw new \TypeError(sprintf('The variable '.$name.' must be NULL, a scalar or a stringable object `%s` given', gettype($value))); } /** @@ -385,12 +427,7 @@ private function expandExpression(array $foundExpression): string */ private function expandVariable(array $variable, string $operator, string $joiner, bool $useQuery): string { - $expanded = ''; - if (!isset($this->variables[$variable['name']])) { - return $expanded; - } - - $value = $this->normalizeValue($this->variables[$variable['name']]); + $value = $this->variables[$variable['name']] ?? ''; $arguments = [$value, $variable, $operator]; $method = 'expandString'; $actualQuery = $useQuery; @@ -416,30 +453,6 @@ private function expandVariable(array $variable, string $operator, string $joine return $variable['name'].'='.$expanded; } - /** - * @param mixed $value the value to be expanded - * - * @throws \TypeError if the type is not supported - * - * @return string|array - */ - private function normalizeValue($value) - { - if (is_array($value)) { - return $value; - } - - if (is_bool($value)) { - return true === $value ? '1' : '0'; - } - - if (is_scalar($value) || method_exists($value, '__toString')) { - return (string) $value; - } - - throw new \TypeError(sprintf('The variables must be a scalar or a stringable object `%s` given', gettype($value))); - } - /** * Expands an expression using a string value. */ @@ -480,10 +493,6 @@ private function expandList(array $value, array $variable, string $operator, str /** @var string $key */ foreach ($value as $key => $var) { if ($isAssoc) { - if (is_array($var)) { - throw TemplateCanNotBeExpanded::dueToNestedListOfValue($key); - } - $key = rawurlencode((string) $key); } diff --git a/tests/UriTemplateTest.php b/tests/UriTemplateTest.php index 8ee91bbe..7b9c3607 100644 --- a/tests/UriTemplateTest.php +++ b/tests/UriTemplateTest.php @@ -47,6 +47,7 @@ public function testGetTemplate(): void /** * @covers ::__construct * @covers ::filterVariables + * @covers ::normalizeValue * @covers ::getDefaultVariables */ public function testGetDefaultVariables(): void @@ -54,7 +55,7 @@ public function testGetDefaultVariables(): void $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}'; $variables = [ 'path' => '/foo/bar', - 'segments' => ['one', 'two'], + 'segments' => ['one', 'two', 3, true, 'false', false, null], 'query' => 'test', 'more' => ['fun', 'ice cream'], 'foo[]' => ['fizz', 'buzz'], @@ -63,7 +64,7 @@ public function testGetDefaultVariables(): void $expectedVariables = [ 'path' => '/foo/bar', - 'segments' => ['one', 'two'], + 'segments' => ['one', 'two', '3', '1', 'false', '0', ''], 'query' => 'test', 'more' => ['fun', 'ice cream'], 'foo[]' => ['fizz', 'buzz'], @@ -78,6 +79,7 @@ public function testGetDefaultVariables(): void /** * @covers ::filterVariables + * @covers ::normalizeValue * @covers ::withDefaultVariables */ public function testWithDefaultVariables(): void @@ -163,6 +165,7 @@ public function testExpandAcceptsOnlyStringAndStringableObject(): void * @covers ::expandList * @covers ::isAssoc * @covers ::decodeReserved + * @covers ::normalizeValue * * @dataProvider templateExpansionProvider */