From e597926634ec0e927ee80e9e51498ecb9347971d Mon Sep 17 00:00:00 2001 From: PJ Dietz Date: Sun, 13 Jul 2014 17:08:15 -0400 Subject: [PATCH] Fix documentation and add tests for TemplateRoute --- .../WellRESTed/Routes/TemplateRoute.php | 61 +++++++------ test/Routes/RegexRouteTest.php | 2 + test/Routes/StaticRouteTest.php | 2 + test/Routes/TemplateRouteTest.php | 85 +++++++++++++++++++ 4 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 test/Routes/TemplateRouteTest.php diff --git a/src/pjdietz/WellRESTed/Routes/TemplateRoute.php b/src/pjdietz/WellRESTed/Routes/TemplateRoute.php index 4176318..5023bb1 100644 --- a/src/pjdietz/WellRESTed/Routes/TemplateRoute.php +++ b/src/pjdietz/WellRESTed/Routes/TemplateRoute.php @@ -1,9 +1,18 @@ + * @copyright Copyright 2014 by PJ Dietz + * @license MIT + */ + namespace pjdietz\WellRESTed\Routes; -use InvalidArgumentException; - +/** + * Maps a URI template to a Handler + */ class TemplateRoute extends RegexRoute { /** @@ -21,6 +30,10 @@ class TemplateRoute extends RegexRoute const URI_TEMPLATE_EXPRESSION_RE = '/{([a-zA-Z]+)}/'; /** + * Create a new route that matches a URI template to a Handler. + * + * Optionally provide patterns for the variables in the template. + * * @param string $template URI template the path must match * @param string $targetClassName Fully qualified name to an autoloadable handler class * @param string $defaultPattern Regular expression for variables @@ -36,6 +49,14 @@ class TemplateRoute extends RegexRoute parent::__construct($pattern, $targetClassName); } + /** + * Translate the URI template into a regular expression. + * + * @param string $template URI template the path must match + * @param string $defaultPattern Regular expression for variables + * @param array $variablePatterns Map of variable names and regular expression + * @return string + */ private function buildPattern($template, $defaultPattern, $variablePatterns) { if (is_null($variablePatterns)) { @@ -64,32 +85,24 @@ class TemplateRoute extends RegexRoute // Is this part an expression or a literal? if (preg_match(self::URI_TEMPLATE_EXPRESSION_RE, $part, $matches)) { - // This part of the path is an expresion. - - if (count($matches) === 2) { - - // Locate the name for the variable from the template. - $variableName = $matches[1]; - - // If the caller passed an array with this variable name - // as a key, use its value for the pattern here. - // Otherwise, use the class's current default. - if (isset($variablePatterns[$variableName])) { - $variablePattern = $variablePatterns[$variableName]; - } else { - $variablePattern = $defaultPattern; - } - - $pattern .= sprintf( - '(?<%s>%s)', - $variableName, - $variablePattern - ); + // Locate the name for the variable from the template. + $variableName = $matches[1]; + // If the caller passed an array with this variable name + // as a key, use its value for the pattern here. + // Otherwise, use the class's current default. + if (isset($variablePatterns[$variableName])) { + $variablePattern = $variablePatterns[$variableName]; } else { - throw new InvalidArgumentException('Invalid URI Template.'); + $variablePattern = $defaultPattern; } + $pattern .= sprintf( + '(?<%s>%s)', + $variableName, + $variablePattern + ); + } else { // This part is a literal. $pattern .= $part; diff --git a/test/Routes/RegexRouteTest.php b/test/Routes/RegexRouteTest.php index 448401a..28aaab0 100644 --- a/test/Routes/RegexRouteTest.php +++ b/test/Routes/RegexRouteTest.php @@ -1,5 +1,7 @@ getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface'); + $mockRequest->expects($this->any()) + ->method('getPath') + ->will($this->returnValue($path)); + + $route = new TemplateRoute($template, __NAMESPACE__ . '\TemplateRouteTestMockHandler', $default, $vars); + $resp = $route->getResponse($mockRequest); + $args = json_decode($resp->getBody(), true); + $this->assertEquals($expected, $args[$testName]); + } + + public function matchingTemplateProvider() + { + return array( + array("/cat/{id}", TemplateRoute::RE_NUM, null, "/cat/12", "id", "12"), + array("/cat/{catId}/{dogId}", TemplateRoute::RE_SLUG, null, "/cat/molly/bear", "dogId", "bear"), + array("/cat/{catId}/{dogId}", TemplateRoute::RE_NUM, array( + "catId" => TemplateRoute::RE_SLUG, + "dogId" => TemplateRoute::RE_SLUG), + "/cat/molly/bear", "dogId", "bear"), + array("cat/{catId}/{dogId}", TemplateRoute::RE_NUM, (object) array( + "catId" => TemplateRoute::RE_SLUG, + "dogId" => TemplateRoute::RE_SLUG), + "/cat/molly/bear", "dogId", "bear") + ); + } + + /** + * @dataProvider nonmatchingTemplateProvider + */ + public function testNonmatchingTemplate($template, $default, $vars, $path) + { + $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface'); + $mockRequest->expects($this->any()) + ->method('getPath') + ->will($this->returnValue($path)); + + $route = new TemplateRoute($template, __NAMESPACE__ . '\TemplateRouteTestMockHandler', $default, $vars); + $resp = $route->getResponse($mockRequest); + $this->assertNull($resp); + } + + public function nonmatchingTemplateProvider() + { + return array( + array("/cat/{id}", TemplateRoute::RE_NUM, null, "/cat/molly"), + array("/cat/{catId}/{dogId}", TemplateRoute::RE_ALPHA, null, "/cat/12/13"), + array("/cat/{catId}/{dogId}", TemplateRoute::RE_NUM, array( + "catId" => TemplateRoute::RE_ALPHA, + "dogId" => TemplateRoute::RE_ALPHA), + "/cat/12/13") + ); + } + +} + +/** + * Mini Handler class that allways returns a 200 status code Response. + */ +class TemplateRouteTestMockHandler implements HandlerInterface +{ + public function getResponse(RequestInterface $request, array $args = null) + { + $resp = new Response(); + $resp->setStatusCode(200); + $resp->setBody(json_encode($args)); + return $resp; + } +}