diff --git a/README.md b/README.md index 2e828d9..a44341f 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ $json = <<<'JSON' JSON; $builder = new RouteBuilder(); -$routes = $builder->buildRoutesFromJson($json); +$routes = $builder->buildRoutes($json); $router = new Router(); $router->addRoutes($routes); diff --git a/composer.json b/composer.json index fd426f1..c4f42ad 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,9 @@ "require": { "php": ">=5.3.0" }, + "require-dev": { + "phpunit/phpunit": "4.1.*" + }, "autoload": { "psr-0": { "pjdietz\\WellRESTed": "src/" }, "classmap": ["src/pjdietz/WellRESTed/Exceptions/HttpExceptions.php"] diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..8827332 --- /dev/null +++ b/composer.lock @@ -0,0 +1,714 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "ff7bc5c6c0cd51153b947901dc3d51af", + "packages": [], + "packages-dev": [ + { + "name": "phpunit/php-code-coverage", + "version": "2.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ed8ac99ce38c3fd134128c898f7ca74665abef7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ed8ac99ce38c3fd134128c898f7ca74665abef7f", + "reference": "ed8ac99ce38c3fd134128c898f7ca74665abef7f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3.1", + "phpunit/php-text-template": "~1.2.0", + "phpunit/php-token-stream": "~1.2.2", + "sebastian/environment": "~1.0.0", + "sebastian/version": "~1.0.3" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4.0.14" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2014-06-29 08:14:40" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2013-10-10 15:34:57" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2014-01-30 17:20:04" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-08-02 07:42:54" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2014-03-03 05:10:30" + }, + { + "name": "phpunit/phpunit", + "version": "4.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "939cb801b3b2aa253aedd0b279f40bb8f35cec91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/939cb801b3b2aa253aedd0b279f40bb8f35cec91", + "reference": "939cb801b3b2aa253aedd0b279f40bb8f35cec91", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": "~2.0", + "phpunit/php-file-iterator": "~1.3.1", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0.2", + "phpunit/phpunit-mock-objects": "~2.1", + "sebastian/comparator": "~1.0", + "sebastian/diff": "~1.1", + "sebastian/environment": "~1.0", + "sebastian/exporter": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2014-06-11 14:15:47" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "7878b9c41edb3afab92b85edf5f0981014a2713a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/7878b9c41edb3afab92b85edf5f0981014a2713a", + "reference": "7878b9c41edb3afab92b85edf5f0981014a2713a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.1" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2014-06-12 07:22:15" + }, + { + "name": "sebastian/comparator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2", + "reference": "f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.1", + "sebastian/exporter": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2014-05-02 07:05:58" + }, + { + "name": "sebastian/diff", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", + "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2013-08-03 16:46:33" + }, + { + "name": "sebastian/environment", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/79517609ec01139cd7e9fded0dd7ce08c952ef6a", + "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2014-02-18 16:17:19" + }, + { + "name": "sebastian/exporter", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", + "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net", + "role": "Lead" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2014-02-16 08:26:31" + }, + { + "name": "sebastian/version", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2014-03-07 15:35:33" + }, + { + "name": "symfony/yaml", + "version": "v2.5.1", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "1057e87364c0b38b50f5695fc9df9dd189036bec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/1057e87364c0b38b50f5695fc9df9dd189036bec", + "reference": "1057e87364c0b38b50f5695fc9df9dd189036bec", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2014-07-08 12:21:33" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "platform": { + "php": ">=5.3.0" + }, + "platform-dev": [] +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ca23fcd --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,8 @@ + + + + + ./test/ + + + diff --git a/src/pjdietz/WellRESTed/RouteBuilder.php b/src/pjdietz/WellRESTed/RouteBuilder.php index 3749711..78de6c1 100644 --- a/src/pjdietz/WellRESTed/RouteBuilder.php +++ b/src/pjdietz/WellRESTed/RouteBuilder.php @@ -15,26 +15,46 @@ use pjdietz\WellRESTed\Interfaces\HandlerInterface; use pjdietz\WellRESTed\Routes\RegexRoute; use pjdietz\WellRESTed\Routes\StaticRoute; use pjdietz\WellRESTed\Routes\TemplateRoute; -use stdClass; /** * Class for facilitating constructing Routers. */ class RouteBuilder { - private $handlerNamespace; - private $templateVariablePatterns; + /** @var string Regex pattern to use for URI template patters. */ private $defaultVariablePattern; + /** @var string Common prefix to affix to handler class names. */ + private $handlerNamespace; + /** @var array Associative array of variable names and regex patterns. */ + private $templateVariablePatterns; /** * Contruct and return an array of routes. * - * @param $data - * @return array + * If $data is a string, buildRoutes() will parse it as JSON with json_decode. + *

+ * If $data is an array, buildRoutes() assumes each item in the array is + * an object it can translate into a route. + *

+ * If $data is an object, buildRoutes() assumes it will have a "routes" + * property with an array value that is a collection of objects to + * translate into routes. Any other properties will be read with + * readConfiguration() + * + * @param string|array|object $data Description of routes to build. + * @return array List of routes to add to a router. * @throws Exceptions\ParseException */ public function buildRoutes($data) { + // If $data is a string, attempt to parse it as JSON. + if (is_string($data)) { + $data = json_decode($data); + if (is_null($data)) { + throw new ParseException("Unable to parse as JSON."); + } + } + // Locate the list of routes. This should be one of these: // - If $data is an object, $data->routes // - If $data is an array, $data @@ -55,12 +75,116 @@ class RouteBuilder return $routes; } - public function buildRoutesFromJson($json) { - return $this->buildRoutes(json_decode($json)); + /** + * Parse an object and update the instances with the new configuration. + * + * ->handlerNamespace is passed to setHandlerNamesapce() + *

+ * ->variablePattern is passed to setDefaultVariablePattern() + *

+ * ->vars is passed to setTemplateVars() + */ + public function readConfiguration($data) + { + if (isset($data->handlerNamespace)) { + $this->setHandlerNamespace($data->handlerNamespace); + } + if (isset($data->variablePattern)) { + $this->setDefaultVariablePattern($data->variablePattern); + } + if (isset($data->vars)) { + $this->setTemplateVars((array) $data->vars); + } } /** - * @param stdClass|array $item + * Return the string to prepend to handler class names. + * + * @return string + */ + public function getHandlerNamespace() + { + return $this->handlerNamespace; + } + + /** + * Set the prefix to prepend to handler class names. + * + * @param mixed $handlerNamespace + */ + public function setHandlerNamespace($handlerNamespace = "") + { + $this->handlerNamespace = $handlerNamespace; + } + + /** + * Return an associative array of variable names and regex patterns. + * + * @return mixed + */ + public function getTemplateVars() + { + return $this->templateVariablePatterns; + } + + /** + * Set the array of template variable patterns. + * + * Keys are names of variables for use in URI template (do not include {}). + * Values are regex patterns or any of the following special names: SLUG, + * ALPHA, ALPHANUM, DIGIT, NUM. + *

+ * If you wish to use additional named patterns, subclass RouteBuilder and + * override getTemplateVariablePattern. + * + * @param array $vars Associative array of variable name => pattern + */ + public function setTemplateVars(array $vars) + { + foreach ($vars as $name => $var) { + $vars[$name] = $this->getTemplateVariablePattern($var); + } + $this->templateVariablePatterns = $vars; + } + + /** + * Return the default regex pattern to use for URI template variables. + * + * @return string + */ + public function getDefaultVariablePattern() + { + return $this->defaultVariablePattern; + } + + /** + * Set the default regex pattern to use for URI template variables. + * + * $defaultVariablePattern may be a regex pattern or one of the following: + * SLUG, ALPHA, ALPHANUM, DIGIT, NUM. + *

+ * If you wish to use additional named patterns, subclass RouteBuilder and + * override getTemplateVariablePattern. + * + * @param mixed $defaultVariablePattern + */ + public function setDefaultVariablePattern($defaultVariablePattern) + { + $this->defaultVariablePattern = $this->getTemplateVariablePattern($defaultVariablePattern); + } + + /** + * Create and return an approrate route given an object describing a route. + * + * $item must contain a "handler" property providing the classname for the + * HandlerInterface to call getResponse() on if the route matches. "handler" + * may be fully qualified and begin with "\". If it does not begin with "\", + * the instance's $handlerNamespace is affixed to the begining. + *

+ * $item must also contain a "path", "template", or "pattern" property to + * indicate how to create the StaticRoute, TemplateRoute, or RegexRoute. + * + * @param object|array $item * @return HandlerInterface * @throws Exceptions\ParseException */ @@ -93,7 +217,7 @@ class RouteBuilder return new TemplateRoute($item->template, $handler, $this->getDefaultVariablePattern(), $vars); } - // Regex Rout + // Regex Route if (isset($item->pattern)) { return new RegexRoute($item->pattern, $handler); } @@ -101,20 +225,20 @@ class RouteBuilder return null; } - protected function readConfiguration($data) + /** + * Provide a regular expression pattern given a name. + * + * The names SLUG, ALPHA, ALPHANUM, DIGIT, NUM convert to regex patterns. + * Anything else passes through as is. + *

+ * If you wish to use additional named patterns, subclass RouteBuilder and + * override getTemplateVariablePattern. + * + * @param string $variable Regex pattern or name (SLUG, ALPHA, ALPHANUM, DIGIT, NUM + * @return string + */ + protected function getTemplateVariablePattern($variable) { - if (isset($data->handlerNamespace)) { - $this->setHandlerNamespace($data->handlerNamespace); - } - if (isset($data->variablePattern)) { - $this->setDefaultVariablePattern($data->variablePattern); - } - if (isset($data->vars)) { - $this->setTemplateVars((array) $data->vars); - } - } - - protected function getTemplateVariablePattern($variable) { switch ($variable) { case "SLUG": return TemplateRoute::RE_SLUG; @@ -130,56 +254,4 @@ class RouteBuilder } } - /** - * @param mixed $handlerNamespace - */ - public function setHandlerNamespace($handlerNamespace) - { - $this->handlerNamespace = $handlerNamespace; - } - - /** - * @return mixed - */ - public function getHandlerNamespace() - { - return $this->handlerNamespace; - } - - /** - * @param array $vars - * @internal param mixed $templateVars - */ - public function setTemplateVars(array $vars) - { - foreach ($vars as $name => $var) { - $vars[$name] = $this->getTemplateVariablePattern($var); - } - $this->templateVariablePatterns = $vars; - } - - /** - * @return mixed - */ - public function getTemplateVars() - { - return $this->templateVariablePatterns; - } - - /** - * @param mixed $defaultVariablePattern - */ - public function setDefaultVariablePattern($defaultVariablePattern) - { - $this->defaultVariablePattern = $this->getTemplateVariablePattern($defaultVariablePattern); - } - - /** - * @return mixed - */ - public function getDefaultVariablePattern() - { - return $this->defaultVariablePattern; - } - } diff --git a/src/pjdietz/WellRESTed/Routes/BaseRoute.php b/src/pjdietz/WellRESTed/Routes/BaseRoute.php index 017014c..00967bf 100644 --- a/src/pjdietz/WellRESTed/Routes/BaseRoute.php +++ b/src/pjdietz/WellRESTed/Routes/BaseRoute.php @@ -10,7 +10,7 @@ use pjdietz\WellRESTed\Interfaces\HandlerInterface; abstract class BaseRoute implements HandlerInterface { /** @var string Fully qualified name for the interface for handlers */ - const DISPATCHER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface'; + const HANDLER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface'; /** @var string */ private $targetClassName; @@ -29,7 +29,7 @@ abstract class BaseRoute implements HandlerInterface */ protected function getTarget() { - if (is_subclass_of($this->targetClassName, self::DISPATCHER_INTERFACE)) { + if (is_subclass_of($this->targetClassName, self::HANDLER_INTERFACE)) { /** @var HandlerInterface $target */ $target = new $this->targetClassName(); return $target; diff --git a/test/RouteBuilderTest.php b/test/RouteBuilderTest.php new file mode 100644 index 0000000..be78c27 --- /dev/null +++ b/test/RouteBuilderTest.php @@ -0,0 +1,168 @@ +buildRoutes($json); + $this->assertEquals(3, count($routes)); + } + + /** + * Fail properly on malformed JSON + * + * @expectedException \pjdietz\WellRESTed\Exceptions\ParseException + * @expectedExceptionMessage Unable to parse as JSON. + */ + public function testBuildInvalidJson() + { + $json = "jadhjaksd"; + $builder = new RouteBuilder(); + $routes = $builder->buildRoutes($json); + } + + public function testNamesapce() + { + $namespace = "\\test\\Namespace"; + $builder = new RouteBuilder(); + $builder->setHandlerNamespace($namespace); + $this->assertEquals($namespace, $builder->getHandlerNamespace()); + } + + /** + * @dataProvider varProvider + */ + public function testDefaultVariablePattern($name, $pattern, $expected) + { + $builder = new RouteBuilder(); + $builder->setDefaultVariablePattern($pattern); + $this->assertEquals($builder->getDefaultVariablePattern(), $expected); + } + + /** + * @dataProvider varProvider + */ + public function testConfigurationDefaultVariablePattern($name, $pattern, $expected) + { + $builder = new RouteBuilder(); + $conf = new stdClass(); + $conf->variablePattern = $pattern; + $builder->readConfiguration($conf); + $this->assertEquals($builder->getDefaultVariablePattern(), $expected); + } + + /** + * @dataProvider varProvider + */ + public function testTemplateVariables($name, $pattern, $expected) + { + $builder = new RouteBuilder(); + $builder->setTemplateVars(array($name => $pattern)); + $vars = $builder->getTemplateVars(); + $this->assertEquals($vars[$name], $expected); + } + + /** + * @dataProvider varProvider + */ + public function testConfigurationTemplateVariables($name, $pattern, $expected) + { + $builder = new RouteBuilder(); + $conf = new stdClass(); + $conf->vars = array($name => $pattern); + $builder->readConfiguration($conf); + $vars = $builder->getTemplateVars(); + $this->assertEquals($vars[$name], $expected); + } + + public function varProvider() + { + return array( + array("slug", "SLUG", TemplateRoute::RE_SLUG), + array("name", "ALPHA", TemplateRoute::RE_ALPHA), + array("name", "ALPHANUM", TemplateRoute::RE_ALPHANUM), + array("id", "DIGIT", TemplateRoute::RE_NUM), + array("id", "NUM", TemplateRoute::RE_NUM), + array("custom", ".*", ".*") + ); + } + + /** + * @dataProvider routeDescriptionProvider + */ + public function testRoutes($key, $value, $expectedClass) + { + $mock = $this->getMock('\pjdietz\WellRESTed\Interfaces\HandlerInterface'); + $routes = array( + (object) array( + $key => $value, + "handler" => get_class($mock) + ) + ); + $builder = new RouteBuilder(); + $routes = $builder->buildRoutes($routes); + $route = $routes[0]; + $this->assertInstanceOf($expectedClass, $route); + } + + /** + * @dataProvider routeDescriptionProvider + */ + public function testRoutesObject($key, $value, $expectedClass) + { + $mock = $this->getMock('\pjdietz\WellRESTed\Interfaces\HandlerInterface'); + $conf = (object) array( + "routes" => array( + (object) array( + $key => $value, + "handler" => get_class($mock) + ) + ) + ); + $builder = new RouteBuilder(); + $routes = $builder->buildRoutes($conf); + $route = $routes[0]; + $this->assertInstanceOf($expectedClass, $route); + } + + public function routeDescriptionProvider() + { + return array( + array("path", "/", '\pjdietz\WellRESTed\Routes\StaticRoute'), + array("pattern", "/cat/[0-9]+", '\pjdietz\WellRESTed\Routes\RegexRoute'), + array("template", "/cat/{id}", '\pjdietz\WellRESTed\Routes\TemplateRoute'), + ); + } + +}