From c2e52936183e565f13359cdb66274ff8760b9b07 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Tue, 24 Mar 2015 23:46:45 +0000 Subject: [PATCH 01/37] First 2-series commit --- phpunit.xml | 7 + src/Docnet/HasLogger.php | 40 +++++ src/Docnet/JAPI/Config.php | 87 ----------- src/Docnet/JAPI/Interfaces/Logger.php | 35 ----- src/Docnet/JAPI/Interfaces/Router.php | 44 ------ src/Docnet/JAPI/Logger.php | 57 ------- src/Docnet/JAPI/Router.php | 217 -------------------------- src/Docnet/JAPI/SolidRouter.php | 0 tests/BaseTest.php | 123 --------------- tests/Controllers/Example.php | 6 + tests/Controllers/HeardYoLike.php | 6 + tests/Controllers/Three.php | 6 + tests/Controllers/World.php | 6 + tests/SolidRouterTest.php | 0 tests/bootstrap.php | 5 + tests/router.php | 97 ------------ 16 files changed, 76 insertions(+), 660 deletions(-) create mode 100644 phpunit.xml create mode 100644 src/Docnet/HasLogger.php delete mode 100644 src/Docnet/JAPI/Config.php delete mode 100644 src/Docnet/JAPI/Interfaces/Logger.php delete mode 100644 src/Docnet/JAPI/Interfaces/Router.php delete mode 100644 src/Docnet/JAPI/Logger.php delete mode 100644 src/Docnet/JAPI/Router.php create mode 100644 src/Docnet/JAPI/SolidRouter.php delete mode 100644 tests/BaseTest.php create mode 100644 tests/Controllers/Example.php create mode 100644 tests/Controllers/HeardYoLike.php create mode 100644 tests/Controllers/Three.php create mode 100644 tests/Controllers/World.php create mode 100644 tests/SolidRouterTest.php create mode 100644 tests/bootstrap.php delete mode 100644 tests/router.php diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..b356bf9 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests + + + \ No newline at end of file diff --git a/src/Docnet/HasLogger.php b/src/Docnet/HasLogger.php new file mode 100644 index 0000000..d54a798 --- /dev/null +++ b/src/Docnet/HasLogger.php @@ -0,0 +1,40 @@ +logger = $logger; + } + + /** + * Gets a logger. + * + * @return LoggerInterface + */ + protected function getLogger() + { + if(NULL === $this->logger) { + $this->logger = new NullLogger(); + } + return $this->logger; + } +} diff --git a/src/Docnet/JAPI/Config.php b/src/Docnet/JAPI/Config.php deleted file mode 100644 index 4beaf17..0000000 --- a/src/Docnet/JAPI/Config.php +++ /dev/null @@ -1,87 +0,0 @@ - - */ -class Config -{ - - /** - * Running configuration - * - * @var array - */ - private $arr_cfg = array(); - - /** - * Merge user supplied config array (if any) with our defaults - * - * @param array|null $arr_cfg - */ - public function __construct($arr_cfg = NULL) - { - $this->arr_cfg = array_merge(array( - 'live' => TRUE, - 'controller_namespace' => '\\', - 'dispatch_loops' => 1 - ), (array)$arr_cfg); - } - - /** - * Are we running in a live environment? - * - * @return bool - */ - public function isLive() - { - return ($this->arr_cfg['live'] === TRUE); - } - - /** - * Get a config parameter. - * - * Returns NULL when a parameter does not exist - * - * @param $str_key - * @return mixed - */ - public function get($str_key) - { - if (isset($this->arr_cfg[$str_key])) { - return $this->arr_cfg[$str_key]; - } - return NULL; - } - - /** - * Set a config parameter - * - * @param $str_key - * @param $mix_val - * @return \Docnet\JAPI\Config - * @fluent - */ - public function set($str_key, $mix_val) - { - $this->arr_cfg[$str_key] = $mix_val; - return $this; - } - -} \ No newline at end of file diff --git a/src/Docnet/JAPI/Interfaces/Logger.php b/src/Docnet/JAPI/Interfaces/Logger.php deleted file mode 100644 index 0e3e584..0000000 --- a/src/Docnet/JAPI/Interfaces/Logger.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -interface Logger -{ - - /** - * Log a message - * - * @param $int_level - * @param $str_message - */ - public function log($int_level, $str_message); - -} \ No newline at end of file diff --git a/src/Docnet/JAPI/Interfaces/Router.php b/src/Docnet/JAPI/Interfaces/Router.php deleted file mode 100644 index 93c490a..0000000 --- a/src/Docnet/JAPI/Interfaces/Router.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ -interface Router -{ - - /** - * Route the request. - * - * This means "turn the URL into a Controller (class) and Action (method) - * for execution. - * - * @throws Exceptions\Routing - */ - public function route($str_url = NULL); - - /** - * Dispatch the request - * - * @throws \Exception - */ - public function dispatch(); - -} \ No newline at end of file diff --git a/src/Docnet/JAPI/Logger.php b/src/Docnet/JAPI/Logger.php deleted file mode 100644 index 530aa6a..0000000 --- a/src/Docnet/JAPI/Logger.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ -class Logger implements Interfaces\Logger -{ - - /** - * Default PHP log levels as strings - * - * @var array - */ - protected $arr_levels = array( - LOG_EMERG => 'EMERG', - LOG_ALERT => 'ALERT', - LOG_CRIT => 'CRIT', - LOG_ERR => 'ERR', - LOG_WARNING => 'WARNING', - LOG_NOTICE => 'NOTICE', - LOG_INFO => 'INFO', - LOG_DEBUG => 'DEBUG' - ); - - /** - * Log a message - * - * @param $int_level - * @param $str_message - */ - public function log($int_level, $str_message) - { - if(!isset($this->arr_levels[$int_level])) { - $int_level = LOG_ERR; - } - syslog($int_level, $str_message); - error_log("[{$this->arr_levels[$int_level]}] {$str_message}"); - } - -} \ No newline at end of file diff --git a/src/Docnet/JAPI/Router.php b/src/Docnet/JAPI/Router.php deleted file mode 100644 index d78fe18..0000000 --- a/src/Docnet/JAPI/Router.php +++ /dev/null @@ -1,217 +0,0 @@ - - */ -class Router implements Interfaces\Router -{ - - /** - * URL to route - * - * @var string - */ - protected $str_url = ''; - - /** - * Output from parse_url() - * - * @var array|mixed - */ - protected $arr_url = array(); - - /** - * Number of dispatch loops - * - * @var int - */ - protected $int_dispatch_count = 0; - - /** - * Controller class as determined by parseController() - * - * @var string - */ - protected $str_controller = ''; - - /** - * Action method as determined by parseAction() - * - * @var string - */ - protected $str_action = ''; - - /** - * Static routes - * - * @var array - */ - private $arr_static_routes = array(); - - /** - * Route the request. - * - * This means "turn the URL into a Controller (class) and Action (method) - * for execution. - * - * Keep URL string and parse_url array response as member vars in case we - * want to evaluate later. - * - * @throws Exceptions\Routing - */ - public function route($str_url = NULL) - { - $this->str_url = (NULL === $str_url ? $_SERVER['REQUEST_URI'] : $str_url); - $this->arr_url = parse_url($this->str_url); - if (!$this->arr_url || !isset($this->arr_url['path'])) { - throw new Exceptions\Routing('URL parse error (parse_url): ' . $this->str_url); - } - if (!$this->static_route()) { - if (!(bool)preg_match("#/(?[\w\-]+)/(?[\w\-]+)#", $this->arr_url['path'], $arr_matches)) { - throw new Exceptions\Routing('URL parse error (preg_match): ' . $this->str_url); - } - $this->setup($arr_matches['controller'], $arr_matches['action']); - } - } - - /** - * Check for static routes, setup if needed - * - * @return bool - */ - protected function static_route() - { - if (isset($this->arr_static_routes[$this->arr_url['path']])) { - $this->setup( - $this->arr_static_routes[$this->arr_url['path']][0], - $this->arr_static_routes[$this->arr_url['path']][1], - FALSE - ); - return TRUE; - } - return FALSE; - } - - /** - * Add a single static route - * - * @param string $str_path - * @param string $str_controller - * @param string $str_action - * @return \Docnet\JAPI\Router - */ - public function addRoute($str_path, $str_controller, $str_action) - { - $this->arr_static_routes[$str_path] = array($str_controller, $str_action); - return $this; - } - - /** - * Set the static routes - * - * @param array $arr_routes - * @return \Docnet\JAPI\Router - */ - public function setRoutes(Array $arr_routes) - { - $this->arr_static_routes = $arr_routes; - return $this; - } - - /** - * Check & store controller and action from URL parts - * - * @param $str_controller - * @param $str_action - * @param $bol_parse - * @throws Exceptions\Routing - */ - protected function setup($str_controller, $str_action, $bol_parse = TRUE) - { - $this->str_controller = ($bol_parse ? $this->parseController($str_controller) : $str_controller); - $this->str_action = ($bol_parse ? $this->parseAction($str_action) : $str_action); - if (!method_exists($this->str_controller, $this->str_action)) { - throw new Exceptions\Routing("Could not find controller/action pair: {$this->str_controller}/{$this->str_action}"); - } - } - - /** - * Translate URL controller name into namespaced class - * - * @param $str_controller - * @return string - */ - protected function parseController($str_controller) - { - return JAPI::getConfig()->get('controller_namespace') . str_replace(" ", "", ucwords(str_replace("-", " ", strtolower($str_controller)))); - } - - /** - * Translate URL action name into method - * - * @param $str_action - * @return string - */ - protected function parseAction($str_action) - { - return lcfirst(str_replace(" ", "", ucwords(str_replace("-", " ", strtolower($str_action))))) . 'Action'; - } - - /** - * Dispatch the request - * - * @todo Verify dispatch loop count and re-dispatch - * - * @throws \Exception - */ - public function dispatch() - { - $this->int_dispatch_count++; - try { - /** @var \Docnet\JAPI\Controller $obj_controller */ - $obj_controller = new $this->str_controller(); - $obj_controller->preDispatch(); - call_user_func(array($obj_controller, $this->str_action)); - $obj_controller->postDispatch(); - $obj_controller->jsonResponse(); - } catch (\Exception $obj_ex) { - throw $obj_ex; - } - } - - /** - * Get the attempted routing (Controller & Action) - * - * Primarily here to support testing - * - * @return array - */ - public function getRouting() - { - return array($this->str_controller, $this->str_action); - } - -} diff --git a/src/Docnet/JAPI/SolidRouter.php b/src/Docnet/JAPI/SolidRouter.php new file mode 100644 index 0000000..e69de29 diff --git a/tests/BaseTest.php b/tests/BaseTest.php deleted file mode 100644 index bfebd49..0000000 --- a/tests/BaseTest.php +++ /dev/null @@ -1,123 +0,0 @@ - - * @abstract - */ -abstract class BaseTest -{ - private $flt_start = 0.0; - - private $int_passes = 0; - - private $int_failures = 0; - - public function __construct() - { - $this->flt_start = microtime(TRUE); - $this->say(""); - $this->say("-------------------------------------"); - $this->say("Starting at " . date('Y-m-d H:i:s')); - $this->say(""); - } - - public function run($str_test = NULL) - { - if (NULL === $str_test) { - $arr_tests = array(); - $obj_reflection = new ReflectionObject($this); - foreach ($obj_reflection->getMethods() as $obj_method) { - if (substr($obj_method->name, 0, 4) == 'test') { - $arr_tests[] = substr($obj_method->name, 4); - } - } - } else { - $arr_tests = array($str_test); - } - - foreach ($arr_tests as $str_test) { - $this->say(str_pad("- {$str_test}", 33, " "), FALSE); - try { - call_user_func(array($this, 'test' . $str_test)); - $this->pass(); - } catch (\InvalidArgumentException $obj_ex) { - $this->fail(); - $this->say(" " . $obj_ex->getMessage()); - } - } - } - - protected function pass() - { - $this->int_passes++; - $this->say('PASS'); - } - - protected function fail() - { - $this->int_failures++; - $this->say('FAIL'); - } - - private function say($str, $bol_eol = TRUE) - { - echo $str . ($bol_eol ? PHP_EOL : ''); - } - - public function __destruct() - { - $this->say(""); - $this->say("Passes : " . $this->int_passes); - $this->say("Failures : " . $this->int_failures); - $this->say(""); - $this->say("Time taken: " . round(microtime(TRUE) - $this->flt_start, 4) . "s"); - $this->say("Complete at " . date('Y-m-d H:i:s')); - $this->say("-------------------------------------"); - $this->say(""); - } - - /** - * Validate parameter is an array - * - * Optionally compare array contents - * - * @param $arr_test - * @param null $arr_compare - * @throws InvalidArgumentException - */ - protected function assertIsArray($arr_test, $arr_compare = NULL) - { - if(is_array($arr_test)) { - if(NULL !== $arr_compare) { - if(count($arr_test) !== count($arr_compare)) { - throw new InvalidArgumentException("Array counts do not match: [".count($arr_test)."] vs [".count($arr_compare)."]"); - } - foreach($arr_test as $mix_key => $mix_val) { - // $this->say("comparing ($mix_key) [{$arr_test[$mix_key]}] == [$arr_compare[$mix_key]]"); - if($arr_test[$mix_key] != $arr_compare[$mix_key]) { - throw new InvalidArgumentException("Array values do not match: [$arr_test[$mix_key]] vs [$arr_compare[$mix_key]]"); - } - } - } - } else { - throw new InvalidArgumentException("Input not an array"); - } - } -} \ No newline at end of file diff --git a/tests/Controllers/Example.php b/tests/Controllers/Example.php new file mode 100644 index 0000000..60f1c8b --- /dev/null +++ b/tests/Controllers/Example.php @@ -0,0 +1,6 @@ + - */ - -date_default_timezone_set("Europe/London"); -require('BaseTest.php'); -require('../src/Docnet/JAPI/Config.php'); -require('../src/Docnet/JAPI.php'); -require('../src/Docnet/JAPI/Exceptions/Routing.php'); -require('../src/Docnet/JAPI/Interfaces/Router.php'); -require('../src/Docnet/JAPI/Router.php'); - - -/** - * RouterTests - * - * @author Tom Walder - */ -class RouterTests extends BaseTest -{ - - public function testHelloWorld() - { - try { - $obj_router = new \Docnet\JAPI\Router(); - $obj_router->route('/hello/world'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('\Hello', 'worldAction')); - } - - public function testMultiPart() - { - try { - $obj_router = new \Docnet\JAPI\Router(); - $obj_router->route('/hello-world/long-name'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('\HelloWorld', 'longNameAction')); - } - - public function testCasing() - { - try { - $obj_router = new \Docnet\JAPI\Router(); - $obj_router->route('/heLLo-wORld/long-NaMe'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('\HelloWorld', 'longNameAction')); - } - - protected function testStaticRoute() - { - try { - $obj_router = new \Docnet\JAPI\Router(); - $obj_router->addRoute('/goodbye', 'Testing', 'StaticRoutes'); - $obj_router->route('/goodbye'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('Testing', 'StaticRoutes')); - } - - protected function testStaticRoutes() - { - try { - $obj_router = new \Docnet\JAPI\Router(); - $obj_router->addRoute('/goodbye', 'Testing', 'StaticRoutes'); - $obj_router->route('/goodbye'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('Testing', 'StaticRoutes')); - - try { - $obj_router->addRoute('/goodbye/cruel/world', 'TestingAgain', 'MoreStaticRoutes'); - $obj_router->route('/goodbye/cruel/world'); - } catch (\Exception $obj_ex) {} - $this->assertIsArray($obj_router->getRouting(), array('TestingAgain', 'MoreStaticRoutes')); - } - -} - -$obj_tests = new RouterTests(); -$obj_tests->run(); From f2ac5e6f2d54d8fb3206ca3a83906d71e8ff4f35 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Tue, 24 Mar 2015 23:58:05 +0000 Subject: [PATCH 02/37] First README updates for v2 --- README.md | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 740c189..7f272dc 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ # PHP JSON API Library # -Simple library for building HTTP JSON APIs in PHP. +Version 2 of our library for building HTTP JSON APIs in PHP. -Sure, I know, there are loads of MVC frameworks out there - and a few very popular ones - that can do this for -you and a lot more besides. +`php-japi` is designed to ONLY do HTTP JSON APIs, so it's small and fast. -BUT, `php-japi` is designed to ONLY do HTTP JSON APIs, so it's small and fast. +Some major changes in version 2 +- Adopt better code practices, allowing for Dependency Injection +- Adopt our new "Single Responsibility Controller" approach +- Decouple Router from JAPI container +- Use PSR logging +- Adopt PHP 5.4 minimum version As we expand our Service Orientated Architecture (SOA) at Docnet, we're using this more and more - so I hope it's useful to someone else ;) Intended to use HTTP status codes wherever possible for passing success/failure etc. back to the client. -Data/payload is your responsibility! - ## Hello, World! ## Let's assume we want our API to respond on the following URL: `api.example.com/hello/world` @@ -24,11 +26,11 @@ So, here's the JAPI controller we'll need: setResponse(array( + $this->setResponse([ 'message' =>'Hello, World!' - )); + ]); } } ``` @@ -41,7 +43,7 @@ See the examples folder for a working demo. Here's the require line for Composer users... -`"docnet/php-japi": "v1.1.1"` +`"docnet/php-japi": "v2.0.0"` ...or just download and use the src folder. @@ -57,9 +59,7 @@ then something like this is all the code you need ```php run(); +// @todo update for v2 ``` See the examples folder for a working demo (api.php). @@ -93,21 +93,14 @@ Add a single custom route ```php getRouter()->addRoute('/goodbye', 'Hello', 'worldAction'); -$api->run(); +// @todo update for v2 ``` Or set a load of them ```php getRouter()->setRoutes(array( - '/goodbye' => array('Hello', 'worldAction'), - '/testing' => array('SomeController', 'testAction'), -)); -$api->run(); +// @todo update for v2 ``` ### Custom Router ### @@ -120,9 +113,7 @@ There's a Router interface and you can follow and you can change the router thro ```php setRouter(new MyAwesomeRouter()); -$api->run(); +// @todo update for v2 ``` ## Coding Standards ## From 519b885845fabc24842fb36e3ec6a9d8f14593d5 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Tue, 24 Mar 2015 23:58:44 +0000 Subject: [PATCH 03/37] Version 2 commits --- LICENSE | 2 +- composer.json | 14 +- examples/Hello.php | 4 +- examples/api.php | 30 ++--- src/Docnet/HasLogger.php | 16 ++- src/Docnet/JAPI.php | 179 ++++++++----------------- src/Docnet/JAPI/Controller.php | 29 ++-- src/Docnet/JAPI/Exceptions/Auth.php | 2 +- src/Docnet/JAPI/Exceptions/Routing.php | 2 +- src/Docnet/JAPI/SolidRouter.php | 173 ++++++++++++++++++++++++ tests/Controllers/HeardYoLike.php | 4 +- tests/Controllers/Three.php | 4 +- tests/SolidRouterTest.php | 53 ++++++++ 13 files changed, 346 insertions(+), 166 deletions(-) diff --git a/LICENSE b/LICENSE index 264939f..948c7d1 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014 Docnet + Copyright 2015 Docnet Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/composer.json b/composer.json index ae55a35..2faf928 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,25 @@ { "name": "docnet/php-japi", "type": "library", - "description": "Simple framework for building HTTP JSON APIs in PHP", + "description": "Simple framework for building HTTP JSON APIs in PHP. 2.", + "authors": [ + { + "name": "Tom Walder", + "email": "tom@docnet.nu" + } + ], "keywords": ["docnet", "json", "http", "api"], "homepage": "https://github.com/DocnetUK/php-japi", "license": "Apache-2.0", "require": { - "php": ">=5.3.0" + "php": ">=5.4.0", + "psr/log": "~1.0" }, "autoload": { "classmap": [ "src/" - ] + ], + "psr-4": {"Docnet\\": "src/Docnet/"} }, "include-path": ["src/"] } \ No newline at end of file diff --git a/examples/Hello.php b/examples/Hello.php index 6e3aa75..ef9c4b5 100644 --- a/examples/Hello.php +++ b/examples/Hello.php @@ -1,6 +1,6 @@ setResponse(array( 'message' => 'Hello, World!' diff --git a/examples/api.php b/examples/api.php index cff75c3..48eff25 100644 --- a/examples/api.php +++ b/examples/api.php @@ -1,6 +1,6 @@ getRouter()->addRoute('/goodbye', 'Hello', 'worldAction'); -$api->run(); +// Demo +(new \Docnet\JAPI())->bootstrap(function(){ + + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/hello'); + + $str_controller = $obj_router->getController(); + return new $str_controller(); + +}); diff --git a/src/Docnet/HasLogger.php b/src/Docnet/HasLogger.php index d54a798..823fcb3 100644 --- a/src/Docnet/HasLogger.php +++ b/src/Docnet/HasLogger.php @@ -1,5 +1,19 @@ */ -class JAPI +class JAPI implements LoggerAwareInterface { - /** - * @var JAPI\Config - */ - private static $obj_config = NULL; - - /** - * @var JAPI\Router - */ - private static $obj_router = NULL; - - /** - * @var JAPI\Logger - */ - private $obj_logger = NULL; + use HasLogger; /** - * @var null|float + * Hook up the shutdown function so we always send nice JSON error responses */ - private static $flt_startup = NULL; - - /** - * When creating a new JAPI, hook up the shutdown function and set Config - * - * @param null|JAPI\Config $obj_config - */ - public function __construct($obj_config = NULL) + public function __construct() { - register_shutdown_function(array($this, 'timeToDie')); - if(NULL !== $obj_config) { - self::$obj_config = $obj_config; - } - self::$flt_startup = (isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE)); + register_shutdown_function([$this, 'timeToDie']); } /** - * Go, Johnny, Go! + * Optionally, encapsulate the bootstrap in a try/catch + * + * @param $fnc_strap */ - public function run() + public function bootstrap($fnc_strap) { try { - $obj_router = $this->getRouter(); - $obj_router->route(); - $obj_router->dispatch(); + if(!is_callable($fnc_strap)) { + throw new \Exception('Unable to bootstrap'); + } + $this->dispatch($fnc_strap()); } catch (RoutingException $obj_ex) { $this->jsonError($obj_ex, 404); } catch (AuthException $obj_ex) { $this->jsonError($obj_ex, 401); } catch (\Exception $obj_ex) { - $this->jsonError($obj_ex); + $this->jsonError($obj_ex, 500); } } /** - * Custom shutdown function + * Go, Johnny, Go! * - * @todo Consider checking if headers have already been sent + * @param Controller $obj_controller + */ + public function dispatch(Controller $obj_controller) + { + $obj_controller->preDispatch(); + $obj_controller->dispatch(); + $obj_controller->postDispatch(); + $this->sendResponse($obj_controller->getResponse()); + } + + /** + * Custom shutdown function */ public function timeToDie() { $arr_error = error_get_last(); - if ($arr_error && in_array($arr_error['type'], array(E_ERROR, E_USER_ERROR, E_COMPILE_ERROR))) { + if ($arr_error && in_array($arr_error['type'], [E_ERROR, E_USER_ERROR, E_COMPILE_ERROR])) { $this->jsonError($arr_error['message']); } } @@ -99,111 +91,52 @@ public function timeToDie() /** * Whatever went wrong, let 'em have it in JSON * - * One day... - * @see http://www.php.net/manual/en/function.http-response-code.php + * @todo Environment or LIVE check * * @param string|\Exception $mix_message * @param int $int_code */ protected function jsonError($mix_message = NULL, $int_code = 500) { + $int_code = (int)$int_code; switch ($int_code) { case 401: - header($_SERVER["SERVER_PROTOCOL"] . " 401 Unauthorized", TRUE, 401); - break; case 404: - header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found", TRUE, 404); - break; case 500: + http_response_code($int_code); + break; default: - header($_SERVER["SERVER_PROTOCOL"] . " 500 Internal Server Error", TRUE, 500); + http_response_code(500); } + $arr_response = [ + 'code' => $int_code, + 'msg' => 'Internal error' + ]; if ($mix_message instanceof \Exception) { - $str_log = get_class($mix_message) . ': ' . $mix_message->getMessage(); - $str_message = self::getConfig()->isLive() ? 'Exception' : $str_log; + $arr_response['msg'] = 'Exception'; + $str_log_message = get_class($mix_message) . ': ' . $mix_message->getMessage(); + if(TRUE) { // @todo Environment or LIVE check + $arr_response['detail'] = $str_log_message; + } } elseif (is_string($mix_message)) { - $str_log = $str_message = $mix_message; + $str_log_message = $mix_message; } else { - $str_log = $str_message = 'Unknown error'; + $str_log_message = ''; } - header('Content-type: application/json'); - echo json_encode(array( - 'response' => (int)$int_code, - 'msg' => $str_message - )); - $this->log(LOG_ERR, "[JAPI exiting with {$int_code}] " . $str_log); + $this->sendResponse($arr_response); + $this->getLogger()->error("[JAPI exiting with {$int_code}] " . $str_log_message); exit(); } /** - * Get the Router + * Output the response * - * @return JAPI\Router + * @param $response */ - public static function getRouter() + protected function sendResponse($response) { - if (NULL === self::$obj_router) { - self::$obj_router = new JAPI\Router(); - } - return self::$obj_router; - } - - /** - * Set a custom Router - * - * @param JAPI\Interfaces\Router $obj_router - */ - public function setRouter(JAPI\Interfaces\Router $obj_router) - { - self::$obj_router = $obj_router; - } - - /** - * Get the running config - * - * @return JAPI\Config|null - */ - public static function getConfig() - { - if(NULL === self::$obj_config) { - self::$obj_config = new JAPI\Config(); - } - return self::$obj_config; - } - - /** - * Get the execution time in seconds, rounded - * - * @param int $int_dp - * @return float - */ - public static function getDuration($int_dp = 4) - { - return round(microtime(TRUE) - self::$flt_startup, $int_dp); - } - - /** - * Log to the current Logger, create one if needed - * - * @param $int_level - * @param $str_message - */ - protected function log($int_level, $str_message) - { - if(NULL === $this->obj_logger) { - $this->obj_logger = new JAPI\Logger(); - } - $this->obj_logger->log($int_level, $str_message); - } - - /** - * Set a custom Logger - * - * @param JAPI\Interfaces\Logger $obj_logger - */ - public function setLogger(JAPI\Interfaces\Logger $obj_logger) - { - $this->obj_logger = $obj_logger; + header('Content-type: application/json'); + echo json_encode($response); } } \ No newline at end of file diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index 43a25c4..23eb523 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -1,6 +1,6 @@ = 50400 || function_exists('getallheaders')) { + if (function_exists('getallheaders')) { return getallheaders(); } $arr_headers = array(); @@ -154,25 +154,30 @@ protected function getPost($str_key, $str_default = NULL) } /** - * Issue the JSON response + * Set the response object * - * @todo How to deal with NULL? + * @param $obj_response */ - public function jsonResponse() + protected function setResponse($obj_response) { - header('Content-type: application/json'); - echo json_encode($this->obj_response); - //exit(); + $this->obj_response = $obj_response; } /** - * Set the response object + * Get the response data * - * @param $obj_response + * @return object|array */ - protected function setResponse($obj_response) + public function getResponse() { - $this->obj_response = $obj_response; + return $this->obj_response; } + /** + * Main dispatch method + * + * @return mixed + */ + abstract function dispatch(); + } \ No newline at end of file diff --git a/src/Docnet/JAPI/Exceptions/Auth.php b/src/Docnet/JAPI/Exceptions/Auth.php index 1264a66..ba1a750 100644 --- a/src/Docnet/JAPI/Exceptions/Auth.php +++ b/src/Docnet/JAPI/Exceptions/Auth.php @@ -1,6 +1,6 @@ str_controller_namespace = $str_controller_namespace; + } + + /** + * Route the request. + * + * This means "turn the URL into a Controller (class) for execution. + * + * Keep URL string and parse_url array response as member vars in case we + * want to evaluate later. + * + * @param string $str_url + * @throws Routing + */ + public function route($str_url = NULL) + { + $this->str_url = (NULL === $str_url ? $_SERVER['REQUEST_URI'] : $str_url); + $this->arr_url = parse_url($this->str_url); + if (!$this->arr_url || !isset($this->arr_url['path'])) { + throw new Routing('URL parse error (parse_url): ' . $this->str_url); + } + if (!$this->routeStatic()) { + if (!(bool)preg_match_all("#/(?[\w\-]+)#", $this->arr_url['path'], $arr_matches)) { + throw new Routing('URL parse error (preg_match): ' . $this->str_url); + } + $this->setup(implode("\t", $arr_matches['controller'])); + } + } + + /** + * Check for static routes, setup if needed + * + * @return bool + */ + protected function routeStatic() + { + if (isset($this->arr_static_routes[$this->arr_url['path']])) { + $this->setup($this->arr_static_routes[$this->arr_url['path']], NULL, FALSE); + return TRUE; + } + return FALSE; + } + + /** + * Check & store controller from URL parts + * + * @param $str_controller + * @param $bol_parse + * @throws Routing + */ + protected function setup($str_controller, $bol_parse = TRUE) + { + $this->str_controller = ($bol_parse ? $this->parseController($str_controller) : $str_controller); + if (!method_exists($this->str_controller, 'dispatch')) { + throw new Routing("Could not find controller: {$this->str_controller}"); + } + } + + /** + * Translate URL controller name into name-spaced class + * + * @param $str_controller + * @return string + */ + protected function parseController($str_controller) + { + return $this->str_controller_namespace . str_replace([" ", "\t"], ["", '\\'], ucwords(str_replace("-", " ", strtolower($str_controller)))); + } + + /** + * Get the routed controller + * + * @return string + */ + public function getController() + { + return $this->str_controller; + } + + /** + * Add a single static route + * + * @param string $str_path + * @param string $str_controller + * @return \Docnet\JAPI\Router + */ + public function addRoute($str_path, $str_controller) + { + $this->arr_static_routes[$str_path] = $str_controller; + return $this; + } + + /** + * Set the static routes + * + * @param array $arr_routes + * @return \Docnet\JAPI\Router + */ + public function setRoutes(Array $arr_routes) + { + $this->arr_static_routes = $arr_routes; + return $this; + } + +} \ No newline at end of file diff --git a/tests/Controllers/HeardYoLike.php b/tests/Controllers/HeardYoLike.php index 5542991..dd0f7e9 100644 --- a/tests/Controllers/HeardYoLike.php +++ b/tests/Controllers/HeardYoLike.php @@ -1,6 +1,6 @@ route('/example'); + $this->assertEquals($obj_router->getController(), '\Example'); + } + + public function testTwoWord() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/hello/world'); + $this->assertEquals($obj_router->getController(), '\Hello\World'); + } + + public function testThreeWord() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/one/two/three'); + $this->assertEquals($obj_router->getController(), '\One\Two\Three'); + } + + public function testCasing() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/hELLo/wORLd'); + $this->assertEquals($obj_router->getController(), '\Hello\World'); + } + + public function testHyphens() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/yo-dawg/heard-yo-like'); + $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); + } + + public function testHyphenCasing() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/YO-dAWg/hEArd-yo-liKE'); + $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); + } + +} From 0dc578ecca9dbb6b8e5446ba41f6af77b94f3e67 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 08:58:57 +0000 Subject: [PATCH 04/37] Update with composer include for 2-series code --- README.md | 4 ++-- composer.lock | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 composer.lock diff --git a/README.md b/README.md index 7f272dc..17b1df7 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,9 @@ See the examples folder for a working demo. ### Install with Composer ### -Here's the require line for Composer users... +Here's the require line for Composer users (during 2-series development)... -`"docnet/php-japi": "v2.0.0"` +`"docnet/php-japi": "2.0.*@dev"` ...or just download and use the src folder. diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..87d8a41 --- /dev/null +++ b/composer.lock @@ -0,0 +1,58 @@ +{ + "_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": "9bd92919d7a39e05a6bb1ca3b3a7b68c", + "packages": [ + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.3.0" + }, + "platform-dev": [] +} From dee7c171af3eddac6edd9629d1ee28b206705e4c Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 09:14:43 +0000 Subject: [PATCH 05/37] README updates --- README.md | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 17b1df7..7f6213c 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,41 @@ to someone else ;) Intended to use HTTP status codes wherever possible for passing success/failure etc. back to the client. +## Single Responsibility Controller ## + +We've adopted a new (for us) take on routing and controller complexity in 2.0. As such, where previously, you might have +had multiple actions (methods) on the same class like this: + +`BasketController::fetchDetailAction()` +`BasketController::addAction()` +`BasketController::removeAction()` +`BasketController::emptyAction()` + +Now this would be 4 name-spaced classes, like this + +`Basket\FetchDetailController` +`Basket\AddController` +`Basket\RemoveController` +`Basket\EmptyController` + +This allows for +- Greater code modularity +- Smaller classes +- Much easier Dependency Injection via `__construct()` + +You can still share common code via extension/composition - whatever takes your fancy! + ## Hello, World! ## Let's assume we want our API to respond on the following URL: `api.example.com/hello/world` -So, here's the JAPI controller we'll need: +So, here's a JAPI controller we'll need: ```php -setResponse([ 'message' =>'Hello, World!' @@ -58,8 +82,15 @@ Assuming: then something like this is all the code you need ```php -bootstrap(function(){ + + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route(); + + $str_controller = $obj_router->getController(); + return new $str_controller(); + +}); ``` See the examples folder for a working demo (api.php). From 06977baa9565be6d983f140d55221e0f16855824 Mon Sep 17 00:00:00 2001 From: Tom Walder Date: Wed, 25 Mar 2015 10:10:24 +0000 Subject: [PATCH 06/37] Routing detail --- README.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7f6213c..92c2555 100644 --- a/README.md +++ b/README.md @@ -21,17 +21,17 @@ Intended to use HTTP status codes wherever possible for passing success/failure We've adopted a new (for us) take on routing and controller complexity in 2.0. As such, where previously, you might have had multiple actions (methods) on the same class like this: -`BasketController::fetchDetailAction()` -`BasketController::addAction()` -`BasketController::removeAction()` -`BasketController::emptyAction()` +- `BasketController::fetchDetailAction()` +- `BasketController::addAction()` +- `BasketController::removeAction()` +- `BasketController::emptyAction()` Now this would be 4 name-spaced classes, like this -`Basket\FetchDetailController` -`Basket\AddController` -`Basket\RemoveController` -`Basket\EmptyController` +- `Basket\FetchDetailController` +- `Basket\AddController` +- `Basket\RemoveController` +- `Basket\EmptyController` This allows for - Greater code modularity @@ -40,6 +40,24 @@ This allows for You can still share common code via extension/composition - whatever takes your fancy! +### Routing ### + +The bundled router will accept any depth of controller namespace, like this + +- `/one` => `One` +- `/one/two` => `One\Two` +- `/one/two/three` => `One\Two\Three` + +When you construct the Router, you can give it a "root" namspace, like this: + +```php +$router = new \Docnet\JAPI\SolidRouter('\\Docnet\\App\\Controller\\'); +``` + +Which results in this routing: + +- `/one/two` => `\Docnet\App\Controller\One\Two` + ## Hello, World! ## Let's assume we want our API to respond on the following URL: `api.example.com/hello/world` From a3791021162623492e5b9d51562bee5c3d6bc279 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 10:12:31 +0000 Subject: [PATCH 07/37] Cleanup --- README.md | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 92c2555..80dcff2 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,10 @@ had multiple actions (methods) on the same class like this: Now this would be 4 name-spaced classes, like this -- `Basket\FetchDetailController` -- `Basket\AddController` -- `Basket\RemoveController` -- `Basket\EmptyController` +- `Basket\FetchDetail` +- `Basket\Add` +- `Basket\Remove` +- `Basket\Empty` This allows for - Greater code modularity @@ -113,26 +113,6 @@ then something like this is all the code you need See the examples folder for a working demo (api.php). -## Routing ## - -The standard routing is quite strict, and (at the time ot writing) expects a controller + action pair for all requests. - -e.g. `api.example.com/hello/world` - -URLs without a 2-part controller + action pair will result in a 404, such as - -- `api.example.com` -- `api.example.com/` -- `api.example.com/controller` - -We do conversion to `StudlyCaps` classes and `camelCase` methods, splitting on hyphens and suffix 'Action' for the -method. e.g. - -- `api.example.com/hello/world` becomes `Hello::worldAction()` -- `api.example.com/hello-world/long-name` becomes `HelloWorld::longNameAction()` - -I seem to recall this is similar to ZF1. - ### Static Routes ### If you have some static routes you want to set up, that's no problem - they also bypass the routing regex code From 1c8b8884437d1ea16ec8eab8b97fe08225452fe5 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 10:28:06 +0000 Subject: [PATCH 08/37] Basic set of Controller tests --- tests/ControllerTest.php | 54 +++++++++++++++++++++++++++++++++++ tests/Controllers/Example.php | 4 ++- tests/Controllers/World.php | 9 +++++- tests/SolidRouterTest.php | 8 +++--- 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 tests/ControllerTest.php diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php new file mode 100644 index 0000000..37533fb --- /dev/null +++ b/tests/ControllerTest.php @@ -0,0 +1,54 @@ +dispatch(); + $this->assertEquals($obj_controller->getResponse(), ['test' => TRUE]); + } + + public function testQuery() + { + $_GET['input1'] = 'value1'; + $obj_controller = new \Hello\World(); + $obj_controller->dispatch(); + $obj_response = $obj_controller->getResponse(); + $this->assertEquals($obj_response['input1'], 'value1'); + } + + public function testPost() + { + $_POST['input2'] = 'value2'; + $obj_controller = new \Hello\World(); + $obj_controller->dispatch(); + $obj_response = $obj_controller->getResponse(); + $this->assertEquals($obj_response['input2'], 'value2'); + } + + public function testParam() + { + $_GET['input3'] = 'value3'; + $_POST['input4'] = 'value4'; + $obj_controller = new \Hello\World(); + $obj_controller->dispatch(); + $obj_response = $obj_controller->getResponse(); + $this->assertEquals($obj_response['input3'], 'value3'); + $this->assertEquals($obj_response['input4'], 'value4'); + } + + public function testMixedParam() + { + $_GET['input4'] = 'value4-get'; + $_POST['input4'] = 'value4-post'; + $obj_controller = new \Hello\World(); + $obj_controller->dispatch(); + $obj_response = $obj_controller->getResponse(); + $this->assertEquals($obj_response['input4'], 'value4-get'); + } + +} diff --git a/tests/Controllers/Example.php b/tests/Controllers/Example.php index 60f1c8b..e3dd215 100644 --- a/tests/Controllers/Example.php +++ b/tests/Controllers/Example.php @@ -2,5 +2,7 @@ class Example extends \Docnet\JAPI\Controller { - public function dispatch(){} + public function dispatch(){ + $this->setResponse(['test' => TRUE]); + } } \ No newline at end of file diff --git a/tests/Controllers/World.php b/tests/Controllers/World.php index 5542991..6146eac 100644 --- a/tests/Controllers/World.php +++ b/tests/Controllers/World.php @@ -2,5 +2,12 @@ namespace Hello; class World extends \Docnet\JAPI\Controller { - public function dispatch(){} + public function dispatch(){ + $this->setResponse([ + 'input1' => $this->getQuery('input1'), + 'input2' => $this->getPost('input2'), + 'input3' => $this->getParam('input3'), + 'input4' => $this->getParam('input4') + ]); + } } \ No newline at end of file diff --git a/tests/SolidRouterTest.php b/tests/SolidRouterTest.php index 88fd38b..f162e8a 100644 --- a/tests/SolidRouterTest.php +++ b/tests/SolidRouterTest.php @@ -1,9 +1,9 @@ Date: Wed, 25 Mar 2015 10:35:55 +0000 Subject: [PATCH 09/37] First pass Travis CI config --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ce82687 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + +before_script: + - composer self-update + - composer install --prefer-source --dev \ No newline at end of file From 9585dbda934b4eff8d4d33386d89269ec5ca42b7 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 10:41:41 +0000 Subject: [PATCH 10/37] Add Travis build status --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 80dcff2..5c15f8d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build status][2.1 image]][2.1] + # PHP JSON API Library # Version 2 of our library for building HTTP JSON APIs in PHP. From 7f5e1c11b85a53a36b6850c5802122aecca62726 Mon Sep 17 00:00:00 2001 From: Tom Walder Date: Wed, 25 Mar 2015 10:46:32 +0000 Subject: [PATCH 11/37] Fix build image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c15f8d..eff3084 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build status][2.1 image]][2.1] +[![Build Status](https://api.travis-ci.org/DocnetUK/php-japi.svg?branch=2.0)](https://travis-ci.org/DocnetUK/php-japi) # PHP JSON API Library # From c76e0322bc62167f13ea5466fd5b79cd0a31d2b9 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 21:04:25 +0000 Subject: [PATCH 12/37] README fixes --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eff3084..1513f50 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ Version 2 of our library for building HTTP JSON APIs in PHP. -`php-japi` is designed to ONLY do HTTP JSON APIs, so it's small and fast. - Some major changes in version 2 - Adopt better code practices, allowing for Dependency Injection - Adopt our new "Single Responsibility Controller" approach @@ -93,13 +91,12 @@ Here's the require line for Composer users (during 2-series development)... ### Entry Point (index.php) ### -Assuming: +Assuming... - You've got Apache/whatever set up to route all requests to this file - An auto-loader is present (like the Composer example here) or you've included all files necessary -- Your controllers are not name spaced and you're happy with our default configuration -then something like this is all the code you need +...then something like this is all the code you need ```php (new \Docnet\JAPI())->bootstrap(function(){ From 704473545d2b6afebd7431fd49b0b732ffbbac33 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 21:04:36 +0000 Subject: [PATCH 13/37] Static route tests --- tests/SolidRouterTest.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/SolidRouterTest.php b/tests/SolidRouterTest.php index f162e8a..8c0940a 100644 --- a/tests/SolidRouterTest.php +++ b/tests/SolidRouterTest.php @@ -50,4 +50,25 @@ public function testHyphenCasing() $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); } + public function testOneStatic() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->addRoute('/testing-url', '\\Hello\\World'); + $obj_router->route('/testing-url'); + $this->assertEquals($obj_router->getController(), '\Hello\World'); + } + + public function testSetStatic() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->setRoutes([ + '/testing-url' => '\\Hello\\World', + '/test' => '\\YoDawg\\HeardYoLike' + ]); + $obj_router->route('/testing-url'); + $this->assertEquals($obj_router->getController(), '\Hello\World'); + $obj_router->route('/test'); + $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); + } + } From 83f54f305cacf3ea568176d98c8d3728ec24a8d6 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Wed, 25 Mar 2015 21:09:31 +0000 Subject: [PATCH 14/37] More tests --- tests/SolidRouterTest.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/SolidRouterTest.php b/tests/SolidRouterTest.php index 8c0940a..39babeb 100644 --- a/tests/SolidRouterTest.php +++ b/tests/SolidRouterTest.php @@ -8,6 +8,9 @@ class SolidRouterTest extends PHPUnit_Framework_TestCase { + /** + * Single word route test + */ public function testOneWord() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -15,6 +18,9 @@ public function testOneWord() $this->assertEquals($obj_router->getController(), '\Example'); } + /** + * Two word route test + */ public function testTwoWord() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -22,6 +28,9 @@ public function testTwoWord() $this->assertEquals($obj_router->getController(), '\Hello\World'); } + /** + * Three word route test + */ public function testThreeWord() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -29,6 +38,9 @@ public function testThreeWord() $this->assertEquals($obj_router->getController(), '\One\Two\Three'); } + /** + * Ensure casing does not affect routing + */ public function testCasing() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -36,6 +48,9 @@ public function testCasing() $this->assertEquals($obj_router->getController(), '\Hello\World'); } + /** + * Evaluate hyphens work as expected in routing + */ public function testHyphens() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -43,6 +58,9 @@ public function testHyphens() $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); } + /** + * Mixed casing and hyphen test + */ public function testHyphenCasing() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -50,6 +68,9 @@ public function testHyphenCasing() $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); } + /** + * Basic static route test + */ public function testOneStatic() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -58,6 +79,9 @@ public function testOneStatic() $this->assertEquals($obj_router->getController(), '\Hello\World'); } + /** + * Multiple static routes + */ public function testSetStatic() { $obj_router = new \Docnet\JAPI\SolidRouter(); @@ -71,4 +95,15 @@ public function testSetStatic() $this->assertEquals($obj_router->getController(), '\YoDawg\HeardYoLike'); } + /** + * Test for failed routing + * + * @expectedException \Docnet\JAPI\Exceptions\Routing + */ + public function testRoutingFailure() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('/missing-url'); + } + } From 07ac6d4c5e9004d055e47104036c730974d3c4b7 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 10:34:31 +0000 Subject: [PATCH 15/37] Allow custom HTTP response codes via Exceptions, filter with http_response_code() --- src/Docnet/JAPI.php | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Docnet/JAPI.php b/src/Docnet/JAPI.php index 119e3d7..878ba56 100644 --- a/src/Docnet/JAPI.php +++ b/src/Docnet/JAPI.php @@ -46,21 +46,27 @@ public function __construct() /** * Optionally, encapsulate the bootstrap in a try/catch * - * @param $fnc_strap + * @param $controller_source */ - public function bootstrap($fnc_strap) + public function bootstrap($controller_source) { try { - if(!is_callable($fnc_strap)) { + if (is_callable($controller_source)) { + $obj_controller = $controller_source(); + } else { + $obj_controller = $controller_source; + } + if($obj_controller instanceof Controller) { + $this->dispatch($obj_controller); + } else { throw new \Exception('Unable to bootstrap'); } - $this->dispatch($fnc_strap()); } catch (RoutingException $obj_ex) { $this->jsonError($obj_ex, 404); } catch (AuthException $obj_ex) { $this->jsonError($obj_ex, 401); } catch (\Exception $obj_ex) { - $this->jsonError($obj_ex, 500); + $this->jsonError($obj_ex, $obj_ex->getCode()); } } @@ -99,15 +105,7 @@ public function timeToDie() protected function jsonError($mix_message = NULL, $int_code = 500) { $int_code = (int)$int_code; - switch ($int_code) { - case 401: - case 404: - case 500: - http_response_code($int_code); - break; - default: - http_response_code(500); - } + http_response_code($int_code); $arr_response = [ 'code' => $int_code, 'msg' => 'Internal error' From 623df8967da282c494d312c6d90918914c43a94e Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 10:35:27 +0000 Subject: [PATCH 16/37] More tests --- tests/ControllerTest.php | 1 + tests/Controllers/Exceptional.php | 8 +++ tests/Controllers/Whoops.php | 8 +++ tests/JAPITest.php | 103 ++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 tests/Controllers/Exceptional.php create mode 100644 tests/Controllers/Whoops.php create mode 100644 tests/JAPITest.php diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index 37533fb..ffd82e5 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -1,6 +1,7 @@ getMockBuilder('\\Example')->getMock(); + $obj_controller->expects($this->once())->method('preDispatch'); + $obj_controller->expects($this->once())->method('dispatch'); + $obj_controller->expects($this->once())->method('postDispatch'); + + // Mock JAPI (just replace the sendResponse method to avoid output errors) + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); + + // Dispatch + $obj_japi->dispatch($obj_controller); + } + + /** + * Validate the bootstrap() cycle works on a supplied Controller + */ + public function testConcreteBootstrapCycle() + { + // Mocked controller & expectations + $obj_controller = $this->getMockBuilder('\\Example')->getMock(); + $obj_controller->expects($this->once())->method('preDispatch'); + $obj_controller->expects($this->once())->method('dispatch'); + $obj_controller->expects($this->once())->method('postDispatch'); + + // Mock JAPI (just replace the sendResponse method to avoid output errors) + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); + $obj_japi->expects($this->once())->method('sendResponse'); + + // Dispatch + $obj_japi->bootstrap($obj_controller); + } + + /** + * Test the bootstrap() methods correctly executes the supplied callback + * + * @todo Implement this test! + */ + public function testBootstrapCallback() + { + } + + /** + * Test Exceptions are correctly passed to jsonError from the bootstrap() method + */ + public function testBootstrapErrorCycle() + { + // Mock JAPI + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse', 'jsonError'])->getMock(); + $obj_japi->expects($this->never())->method('sendResponse'); + $obj_japi->expects($this->once())->method('jsonError')->with( + $this->equalTo(new Exception()), + $this->equalTo(0) + ); + + // Dispatch + $obj_japi->bootstrap(new Whoops()); + } + + /** + * Test custom Exception codes are correctly passed to jsonError from the bootstrap() method + */ + public function testBootstrapCustomErrorCycle() + { + // Mock JAPI + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse', 'jsonError'])->getMock(); + $obj_japi->expects($this->never())->method('sendResponse'); + $obj_japi->expects($this->once())->method('jsonError')->with( + $this->equalTo(new RuntimeException('Error Message', 400)), + $this->equalTo(400) + ); + + // Dispatch + $obj_japi->bootstrap(new Exceptional()); + } + + /** + * Validate the response data from the Controller is correctly passed to sendResponse() + */ + public function testSendResponse() + { + // Mock JAPI + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); + $obj_japi->expects($this->once())->method('sendResponse')->with($this->equalTo(['test' => TRUE])); + + // Dispatch + $obj_japi->bootstrap(new Example()); + } + +} From 74825d5d90dd62034c579edf4e9f076561a02bf0 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 10:59:14 +0000 Subject: [PATCH 17/37] Remove exit() call from jsonError --- src/Docnet/JAPI.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Docnet/JAPI.php b/src/Docnet/JAPI.php index 878ba56..a18d45f 100644 --- a/src/Docnet/JAPI.php +++ b/src/Docnet/JAPI.php @@ -123,7 +123,6 @@ protected function jsonError($mix_message = NULL, $int_code = 500) } $this->sendResponse($arr_response); $this->getLogger()->error("[JAPI exiting with {$int_code}] " . $str_log_message); - exit(); } /** From a635ec8cbe03165d47d312afb3b6f0971183c780 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 10:59:43 +0000 Subject: [PATCH 18/37] Add Logger test --- tests/JAPITest.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/JAPITest.php b/tests/JAPITest.php index ffd4630..1ca5e19 100644 --- a/tests/JAPITest.php +++ b/tests/JAPITest.php @@ -94,10 +94,31 @@ public function testSendResponse() { // Mock JAPI $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); - $obj_japi->expects($this->once())->method('sendResponse')->with($this->equalTo(['test' => TRUE])); + $obj_japi->expects($this->once())->method('sendResponse')->with( + $this->equalTo(['test' => TRUE]) + ); // Dispatch $obj_japi->bootstrap(new Example()); } + /** + * Do we correctly call the logger in jsonError scenarios? + */ + public function testLogger() + { + // Mock the logger + $obj_logger = $this->getMockBuilder('\\Psr\\Log\\NullLogger')->setMethods(['log'])->getMock(); + $obj_logger->expects($this->once())->method('log')->with( + $this->equalTo(\Psr\Log\LogLevel::ERROR) + ); + + // Mock JAPI + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); + $obj_japi->setLogger($obj_logger); + + // Dispatch + $obj_japi->bootstrap(new Exceptional()); + } + } From 72f0a9def3d84fea5572205fb823467f2d4d6bcd Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 13:32:35 +0000 Subject: [PATCH 19/37] Tidy up, standardise error handling --- src/Docnet/JAPI.php | 47 +++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/Docnet/JAPI.php b/src/Docnet/JAPI.php index a18d45f..bde01c7 100644 --- a/src/Docnet/JAPI.php +++ b/src/Docnet/JAPI.php @@ -51,15 +51,11 @@ public function __construct() public function bootstrap($controller_source) { try { - if (is_callable($controller_source)) { - $obj_controller = $controller_source(); - } else { - $obj_controller = $controller_source; - } + $obj_controller = is_callable($controller_source) ? $controller_source() : $controller_source; if($obj_controller instanceof Controller) { $this->dispatch($obj_controller); } else { - throw new \Exception('Unable to bootstrap'); + throw new \Exception('Unable to bootstrap', 500); } } catch (RoutingException $obj_ex) { $this->jsonError($obj_ex, 404); @@ -90,48 +86,41 @@ public function timeToDie() { $arr_error = error_get_last(); if ($arr_error && in_array($arr_error['type'], [E_ERROR, E_USER_ERROR, E_COMPILE_ERROR])) { - $this->jsonError($arr_error['message']); + $this->jsonError(new \ErrorException($arr_error['message'], 500, 0, $arr_error['file'], $arr_error['line']), 500); } } /** - * Whatever went wrong, let 'em have it in JSON + * Whatever went wrong, let 'em have it in JSON over HTTP * - * @todo Environment or LIVE check + * @todo Environment or LIVE check for extended error * - * @param string|\Exception $mix_message + * @param \Exception $obj_error * @param int $int_code */ - protected function jsonError($mix_message = NULL, $int_code = 500) + protected function jsonError(\Exception $obj_error, $int_code) { - $int_code = (int)$int_code; - http_response_code($int_code); $arr_response = [ 'code' => $int_code, - 'msg' => 'Internal error' + 'msg' => ($obj_error instanceof \ErrorException ? 'Internal Error' : 'Exception') ]; - if ($mix_message instanceof \Exception) { - $arr_response['msg'] = 'Exception'; - $str_log_message = get_class($mix_message) . ': ' . $mix_message->getMessage(); - if(TRUE) { // @todo Environment or LIVE check - $arr_response['detail'] = $str_log_message; - } - } elseif (is_string($mix_message)) { - $str_log_message = $mix_message; - } else { - $str_log_message = ''; + $str_log_message = get_class($obj_error) . ': ' . $obj_error->getMessage(); + if(TRUE) { // @todo Environment or LIVE check + $arr_response['detail'] = $str_log_message; } - $this->sendResponse($arr_response); - $this->getLogger()->error("[JAPI exiting with {$int_code}] " . $str_log_message); + $this->sendResponse($arr_response, $int_code); + $this->getLogger()->error("[JAPI] [{$int_code}] Error: {$str_log_message}"); } /** - * Output the response + * Output the response as JSON with HTTP headers * - * @param $response + * @param array|object $response + * @param int $http_code */ - protected function sendResponse($response) + protected function sendResponse($response, $http_code = 200) { + http_response_code($http_code); header('Content-type: application/json'); echo json_encode($response); } From 7638400c4dfa3ac43e8666782ad7e9daa67f6707 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 13:33:30 +0000 Subject: [PATCH 20/37] Improve tests --- tests/JAPITest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/JAPITest.php b/tests/JAPITest.php index 1ca5e19..bb2dcd2 100644 --- a/tests/JAPITest.php +++ b/tests/JAPITest.php @@ -95,7 +95,8 @@ public function testSendResponse() // Mock JAPI $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); $obj_japi->expects($this->once())->method('sendResponse')->with( - $this->equalTo(['test' => TRUE]) + $this->equalTo(['test' => TRUE]), + $this->equalTo(200) ); // Dispatch From 305ee2f97fb610a89565b6962dfcf55a293f8299 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 13:45:08 +0000 Subject: [PATCH 21/37] Update static routing --- README.md | 76 ++++++++++++++++++------------------------------------- 1 file changed, 24 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 1513f50..cbc750f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,9 @@ This allows for You can still share common code via extension/composition - whatever takes your fancy! -### Routing ### +JAPI will call the `dispatch()` method on your controller. + +### SOLID Routing ### The bundled router will accept any depth of controller namespace, like this @@ -48,7 +50,7 @@ The bundled router will accept any depth of controller namespace, like this - `/one/two` => `One\Two` - `/one/two/three` => `One\Two\Three` -When you construct the Router, you can give it a "root" namspace, like this: +When you construct the Router, you can give it a "root" namespace, like this: ```php $router = new \Docnet\JAPI\SolidRouter('\\Docnet\\App\\Controller\\'); @@ -58,30 +60,30 @@ Which results in this routing: - `/one/two` => `\Docnet\App\Controller\One\Two` -## Hello, World! ## +### Static Routes ### -Let's assume we want our API to respond on the following URL: `api.example.com/hello/world` +If you have some static routes you want to set up, that's no problem - they also bypass the routing regex code +and so make calls very slightly faster. -So, here's a JAPI controller we'll need: +Add a single custom route ```php -namespace Hello; -class World extends \Docnet\JAPI\Controller -{ - public function dispatch() // <-- method declared Abstract in the JAPI Controller - { - $this->setResponse([ - 'message' =>'Hello, World!' - ]); - } -} +$router = new \Docnet\JAPI\SolidRouter(); +$router->addRoute('/hello', '\\Some\\Controller'); ``` -See the examples folder for a working demo. +Or set a load of them -## Getting Started ## +```php +setRoutes([ + '/hello' => '\\Some\\Controller', + '/world' => '\\Other\\Controller' +]); +``` -### Install with Composer ### +## Installation ## Here's the require line for Composer users (during 2-series development)... @@ -89,14 +91,14 @@ Here's the require line for Composer users (during 2-series development)... ...or just download and use the src folder. -### Entry Point (index.php) ### +## Bootstrapping ## Assuming... - You've got Apache/whatever set up to route all requests to this file - An auto-loader is present (like the Composer example here) or you've included all files necessary -...then something like this is all the code you need +...then something like this is all the code you need in your `index.php` ```php (new \Docnet\JAPI())->bootstrap(function(){ @@ -112,38 +114,8 @@ Assuming... See the examples folder for a working demo (api.php). -### Static Routes ### - -If you have some static routes you want to set up, that's no problem - they also bypass the routing regex code -and so make calls very slightly faster. - -Add a single custom route - -```php - Date: Thu, 26 Mar 2015 13:58:34 +0000 Subject: [PATCH 22/37] Tidy up --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cbc750f..06465b2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Now this would be 4 name-spaced classes, like this This allows for - Greater code modularity - Smaller classes -- Much easier Dependency Injection via `__construct()` +- Much easier Dependency Injection via `__construct()` as each "action" is it's own class. You can still share common code via extension/composition - whatever takes your fancy! @@ -75,7 +75,6 @@ $router->addRoute('/hello', '\\Some\\Controller'); Or set a load of them ```php -setRoutes([ '/hello' => '\\Some\\Controller', @@ -116,6 +115,4 @@ See the examples folder for a working demo (api.php). ## Coding Standards ## -Desired adherence to [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). - -Uses [PSR-3](https://github.com/php-fig/log) logging \ No newline at end of file +Desired adherence to [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). Uses [PSR-3](https://github.com/php-fig/log) logging. \ No newline at end of file From 6a11b058972e92f80a74008fcbfb8cdee1c39371 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 14:22:24 +0000 Subject: [PATCH 23/37] Array syntax tweaks, comment update --- src/Docnet/JAPI/Controller.php | 6 +++--- src/Docnet/JAPI/SolidRouter.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index 23eb523..7cecb7e 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -30,7 +30,7 @@ abstract class Controller /** * Response data * - * @var null + * @var null|object|array */ protected $obj_response = NULL; @@ -80,7 +80,7 @@ protected function getHeaders() if (function_exists('getallheaders')) { return getallheaders(); } - $arr_headers = array(); + $arr_headers = []; foreach ($_SERVER as $str_key => $str_value) { if (strpos($str_key, 'HTTP_') === 0) { $arr_headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($str_key, 5)))))] = $str_value; @@ -178,6 +178,6 @@ public function getResponse() * * @return mixed */ - abstract function dispatch(); + abstract public function dispatch(); } \ No newline at end of file diff --git a/src/Docnet/JAPI/SolidRouter.php b/src/Docnet/JAPI/SolidRouter.php index a7755ac..c17d7bf 100644 --- a/src/Docnet/JAPI/SolidRouter.php +++ b/src/Docnet/JAPI/SolidRouter.php @@ -38,7 +38,7 @@ class SolidRouter * * @var array|mixed */ - protected $arr_url = array(); + protected $arr_url = []; /** * Controller class as determined by parseController() @@ -52,7 +52,7 @@ class SolidRouter * * @var array */ - private $arr_static_routes = array(); + private $arr_static_routes = []; /** * @var string From a86d918554fd89bb9c889e8f180b25f2eba0fb5b Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 14:26:31 +0000 Subject: [PATCH 24/37] Comment updates --- src/Docnet/JAPI/Controller.php | 18 +++++++++--------- src/Docnet/JAPI/Exceptions/Routing.php | 2 +- src/Docnet/JAPI/SolidRouter.php | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index 7cecb7e..7f67d6d 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -112,9 +112,9 @@ protected function getJson() /** * Get a request parameter. Check GET then POST data. * - * @param $str_key - * @param null $str_default - * @return null + * @param string $str_key + * @param mixed $str_default + * @return mixed */ protected function getParam($str_key, $str_default = NULL) { @@ -132,9 +132,9 @@ protected function getParam($str_key, $str_default = NULL) /** * Get a Query/GET input parameter * - * @param $str_key - * @param null $str_default - * @return null + * @param string $str_key + * @param mixed $str_default + * @return mixed */ protected function getQuery($str_key, $str_default = NULL) { @@ -144,9 +144,9 @@ protected function getQuery($str_key, $str_default = NULL) /** * Get a POST parameter * - * @param $str_key - * @param null $str_default - * @return null + * @param string $str_key + * @param mixed $str_default + * @return mixed */ protected function getPost($str_key, $str_default = NULL) { diff --git a/src/Docnet/JAPI/Exceptions/Routing.php b/src/Docnet/JAPI/Exceptions/Routing.php index a24d48c..59c7c6f 100644 --- a/src/Docnet/JAPI/Exceptions/Routing.php +++ b/src/Docnet/JAPI/Exceptions/Routing.php @@ -17,7 +17,7 @@ namespace Docnet\JAPI\Exceptions; /** - * Routing Exceptions + * Routing Exception * * @author Tom Walder */ diff --git a/src/Docnet/JAPI/SolidRouter.php b/src/Docnet/JAPI/SolidRouter.php index c17d7bf..24e9a48 100644 --- a/src/Docnet/JAPI/SolidRouter.php +++ b/src/Docnet/JAPI/SolidRouter.php @@ -150,7 +150,7 @@ public function getController() * * @param string $str_path * @param string $str_controller - * @return \Docnet\JAPI\Router + * @return \Docnet\JAPI\SolidRouter */ public function addRoute($str_path, $str_controller) { @@ -162,7 +162,7 @@ public function addRoute($str_path, $str_controller) * Set the static routes * * @param array $arr_routes - * @return \Docnet\JAPI\Router + * @return \Docnet\JAPI\SolidRouter */ public function setRoutes(Array $arr_routes) { From f90f5708ac8eaad9a61c10a8d12fabd2a30a4f09 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Thu, 26 Mar 2015 14:28:34 +0000 Subject: [PATCH 25/37] Whitespace --- src/Docnet/JAPI/Controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index 7f67d6d..ad41548 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -15,6 +15,7 @@ * limitations under the License. */ namespace Docnet\JAPI; + /** * Base Controller * From 6bccf618673ab16d03209c9091418d7cf9952aa4 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 12:35:34 +0100 Subject: [PATCH 26/37] Code coverage reports --- .travis.yml | 8 +++++++- README.md | 1 + phpunit.xml | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ce82687..f664bfe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,10 @@ php: before_script: - composer self-update - - composer install --prefer-source --dev \ No newline at end of file + - composer install --prefer-source --dev + +script: + - mkdir -p build/logs + +after_script: + - php vendor/bin/coveralls \ No newline at end of file diff --git a/README.md b/README.md index 06465b2..049302c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Build Status](https://api.travis-ci.org/DocnetUK/php-japi.svg?branch=2.0)](https://travis-ci.org/DocnetUK/php-japi) +[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg) # PHP JSON API Library # diff --git a/phpunit.xml b/phpunit.xml index b356bf9..a6d0c17 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -4,4 +4,7 @@ tests + + + \ No newline at end of file From 43ca146949835fcde34ac0350b9c81aa915de495 Mon Sep 17 00:00:00 2001 From: Tom Walder Date: Fri, 10 Apr 2015 12:39:46 +0100 Subject: [PATCH 27/37] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 049302c..12aa347 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://api.travis-ci.org/DocnetUK/php-japi.svg?branch=2.0)](https://travis-ci.org/DocnetUK/php-japi) -[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg) +[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg)] # PHP JSON API Library # @@ -116,4 +116,4 @@ See the examples folder for a working demo (api.php). ## Coding Standards ## -Desired adherence to [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). Uses [PSR-3](https://github.com/php-fig/log) logging. \ No newline at end of file +Desired adherence to [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). Uses [PSR-3](https://github.com/php-fig/log) logging. From ffde21f6324ce8c02c3406a2d64e81b416ea4fa2 Mon Sep 17 00:00:00 2001 From: Tom Walder Date: Fri, 10 Apr 2015 12:41:41 +0100 Subject: [PATCH 28/37] Fix coverage image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 12aa347..c149224 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://api.travis-ci.org/DocnetUK/php-japi.svg?branch=2.0)](https://travis-ci.org/DocnetUK/php-japi) -[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg)] +[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg)](https://coveralls.io/r/DocnetUK/php-japi) # PHP JSON API Library # From fd4e19edbc5c637f0f9267d7573a245385250155 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 12:49:29 +0100 Subject: [PATCH 29/37] Coverage graphic change, ignore build folder --- .gitignore | 2 + README.md | 2 +- composer.json | 4 + composer.lock | 1406 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 1409 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 9c2e50d..bbabfd6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ Thumbs.db # IDE # ####### .idea/ + +build/ \ No newline at end of file diff --git a/README.md b/README.md index c149224..c492dc2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://api.travis-ci.org/DocnetUK/php-japi.svg?branch=2.0)](https://travis-ci.org/DocnetUK/php-japi) -[![Coverage](https://img.shields.io/coveralls/DocnetUK/php-japi/2.0.svg)](https://coveralls.io/r/DocnetUK/php-japi) +[![Coverage Status](https://coveralls.io/repos/DocnetUK/php-japi/badge.svg?branch=2.0)](https://coveralls.io/r/DocnetUK/php-japi) # PHP JSON API Library # diff --git a/composer.json b/composer.json index 2faf928..31622bc 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,10 @@ "php": ">=5.4.0", "psr/log": "~1.0" }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "autoload": { "classmap": [ "src/" diff --git a/composer.lock b/composer.lock index 87d8a41..132ecb4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "9bd92919d7a39e05a6bb1ca3b3a7b68c", + "hash": "e5629c1113a4bccb101f6be8422b3dcc", "packages": [ { "name": "psr/log", @@ -45,14 +45,1412 @@ "time": "2012-12-21 11:40:51" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "2.0.*@ALPHA" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Instantiator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2014-10-13 12:58:55" + }, + { + "name": "guzzle/guzzle", + "version": "v3.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" + }, + "suggest": { + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.9-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-03-18 18:23:50" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", + "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-03-27 19:31:25" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.0.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "~1.0", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "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/", + "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": "2015-01-24 10:06:35" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "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": "2015-04-02 05:19:05" + }, + { + "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.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "eab81d02569310739373308137284e0158424330" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", + "reference": "eab81d02569310739373308137284e0158424330", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-04-08 04:46:07" + }, + { + "name": "phpunit/phpunit", + "version": "4.6.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "6c773fda0bdb5ea891d9e4430dcc26c990b9130b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6c773fda0bdb5ea891d9e4430dcc26c990b9130b", + "reference": "6c773fda0bdb5ea891d9e4430dcc26c990b9130b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "~1.3,>=1.3.1", + "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.6.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": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2015-04-07 09:16:49" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "~1.0,>=1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "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": "2015-04-02 05:36:41" + }, + { + "name": "satooshi/php-coveralls", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/satooshi/php-coveralls.git", + "reference": "2fbf803803d179ab1082807308a67bbd5a760c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/2fbf803803d179ab1082807308a67bbd5a760c70", + "reference": "2fbf803803d179ab1082807308a67bbd5a760c70", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-simplexml": "*", + "guzzle/guzzle": ">=2.7", + "php": ">=5.3", + "psr/log": "1.0.0", + "symfony/config": ">=2.0", + "symfony/console": ">=2.0", + "symfony/stopwatch": ">=2.2", + "symfony/yaml": ">=2.0" + }, + "require-dev": { + "apigen/apigen": "2.8.*@stable", + "pdepend/pdepend": "dev-master as 2.0.0", + "phpmd/phpmd": "dev-master", + "phpunit/php-invoker": ">=1.1.0,<1.2.0", + "phpunit/phpunit": "3.7.*@stable", + "sebastian/finder-facade": "dev-master", + "sebastian/phpcpd": "1.4.*@stable", + "squizlabs/php_codesniffer": "1.4.*@stable", + "theseer/fdomdocument": "dev-master" + }, + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" + }, + "bin": [ + "composer/bin/coveralls" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.7-dev" + } + }, + "autoload": { + "psr-0": { + "Satooshi\\Component": "src/", + "Satooshi\\Bundle": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kitamura Satoshi", + "email": "with.no.parachute@gmail.com", + "homepage": "https://www.facebook.com/satooshi.jp" + } + ], + "description": "PHP client library for Coveralls API", + "homepage": "https://github.com/satooshi/php-coveralls", + "keywords": [ + "ci", + "coverage", + "github", + "test" + ], + "time": "2014-11-11 15:35:34" + }, + { + "name": "sebastian/comparator", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-01-29 16:28:08" + }, + { + "name": "sebastian/diff", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-01-01 10:01:08" + }, + { + "name": "sebastian/exporter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "84839970d05254c73cde183a721c7af13aede943" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-01-27 07:23:06" + }, + { + "name": "sebastian/global-state", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2014-10-06 09:23:50" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "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": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-01-24 09:48:32" + }, + { + "name": "sebastian/version", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "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": "2015-02-24 06:35:25" + }, + { + "name": "symfony/config", + "version": "v2.6.6", + "target-dir": "Symfony/Component/Config", + "source": { + "type": "git", + "url": "https://github.com/symfony/Config.git", + "reference": "d91be01336605db8da21b79bc771e46a7276d1bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Config/zipball/d91be01336605db8da21b79bc771e46a7276d1bc", + "reference": "d91be01336605db8da21b79bc771e46a7276d1bc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/filesystem": "~2.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Config\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Config Component", + "homepage": "http://symfony.com", + "time": "2015-03-30 15:54:10" + }, + { + "name": "symfony/console", + "version": "v2.6.6", + "target-dir": "Symfony/Component/Console", + "source": { + "type": "git", + "url": "https://github.com/symfony/Console.git", + "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Console/zipball/5b91dc4ed5eb08553f57f6df04c4730a73992667", + "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.1" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Console\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Console Component", + "homepage": "http://symfony.com", + "time": "2015-03-30 15:54:10" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.6.6", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284", + "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/phpunit-bridge": "~2.7", + "symfony/stopwatch": "~2.3" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com", + "time": "2015-03-13 17:37:22" + }, + { + "name": "symfony/filesystem", + "version": "v2.6.6", + "target-dir": "Symfony/Component/Filesystem", + "source": { + "type": "git", + "url": "https://github.com/symfony/Filesystem.git", + "reference": "4983964b3693e4f13449cb3800c64a9112c301b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4983964b3693e4f13449cb3800c64a9112c301b4", + "reference": "4983964b3693e4f13449cb3800c64a9112c301b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "http://symfony.com", + "time": "2015-03-22 16:55:57" + }, + { + "name": "symfony/stopwatch", + "version": "v2.6.6", + "target-dir": "Symfony/Component/Stopwatch", + "source": { + "type": "git", + "url": "https://github.com/symfony/Stopwatch.git", + "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/5f196e84b5640424a166d2ce9cca161ce1e9d912", + "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Stopwatch\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "http://symfony.com", + "time": "2015-03-22 16:55:57" + }, + { + "name": "symfony/yaml", + "version": "v2.6.6", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "174f009ed36379a801109955fc5a71a49fe62dd4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/174f009ed36379a801109955fc5a71a49fe62dd4", + "reference": "174f009ed36379a801109955fc5a71a49fe62dd4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2015-03-30 15:54:10" + } + ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "satooshi/php-coveralls": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.3.0" + "php": ">=5.4.0" }, "platform-dev": [] } From c80a7b778adbea2d892e9eb160edf4b16dc771be Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 12:56:36 +0100 Subject: [PATCH 30/37] Add phpunit to Travis for coveralls --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f664bfe..1b2ea38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_script: script: - mkdir -p build/logs + - php vendor/bin/phpunit after_script: - php vendor/bin/coveralls \ No newline at end of file From df82937d754f457651152679147dfe427733b365 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 14:56:43 +0100 Subject: [PATCH 31/37] Added a "no logger" test --- tests/JAPITest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/JAPITest.php b/tests/JAPITest.php index bb2dcd2..3277fa8 100644 --- a/tests/JAPITest.php +++ b/tests/JAPITest.php @@ -122,4 +122,16 @@ public function testLogger() $obj_japi->bootstrap(new Exceptional()); } + /** + * Ensure we do not fall over when no logger has been supplied + */ + public function testNoLogger() + { + // Mock JAPI + $obj_japi = $this->getMockBuilder('\\Docnet\\JAPI')->setMethods(['sendResponse'])->getMock(); + + // Dispatch + $obj_japi->bootstrap(new Exceptional()); + } + } From 720d88d811e6e89ac6d9e60352fdb017da763512 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 15:05:07 +0100 Subject: [PATCH 32/37] Add more URL error tests --- tests/SolidRouterTest.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/SolidRouterTest.php b/tests/SolidRouterTest.php index 39babeb..26a1981 100644 --- a/tests/SolidRouterTest.php +++ b/tests/SolidRouterTest.php @@ -106,4 +106,26 @@ public function testRoutingFailure() $obj_router->route('/missing-url'); } + /** + * Test for failed URL parsing + * + * @expectedException \Docnet\JAPI\Exceptions\Routing + */ + public function testMalformedUrl() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('http://:80'); + } + + /** + * Test for failed URL regex match + * + * @expectedException \Docnet\JAPI\Exceptions\Routing + */ + public function testNonUrlString() + { + $obj_router = new \Docnet\JAPI\SolidRouter(); + $obj_router->route('-'); + } + } From 0e63291c48d70cb482b44733541ae399e14484cf Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 10 Apr 2015 15:10:24 +0100 Subject: [PATCH 33/37] Add basic headers test (CLI) --- tests/ControllerTest.php | 9 +++++++++ tests/Controllers/Headers.php | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/Controllers/Headers.php diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index ffd82e5..82442fd 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -1,6 +1,7 @@ assertEquals($obj_response['input4'], 'value4-get'); } + public function testCliHeaders() + { + $_SERVER['HTTP_SOME_HEADER'] = TRUE; + $obj_controller = new Headers(); + $obj_controller->dispatch(); + $this->assertEquals($obj_controller->getResponse(), ['Some-Header' => TRUE]); + } + } diff --git a/tests/Controllers/Headers.php b/tests/Controllers/Headers.php new file mode 100644 index 0000000..93b7991 --- /dev/null +++ b/tests/Controllers/Headers.php @@ -0,0 +1,8 @@ +setResponse($this->getHeaders()); + } +} \ No newline at end of file From 32ee70392c1bc8ec417c8100ed659a4a3bc7ca8d Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 3 Jul 2015 13:33:52 +0100 Subject: [PATCH 34/37] Ensure response codes are actual HTTP response codes --- src/Docnet/JAPI.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Docnet/JAPI.php b/src/Docnet/JAPI.php index bde01c7..bb40cc7 100644 --- a/src/Docnet/JAPI.php +++ b/src/Docnet/JAPI.php @@ -108,6 +108,9 @@ protected function jsonError(\Exception $obj_error, $int_code) if(TRUE) { // @todo Environment or LIVE check $arr_response['detail'] = $str_log_message; } + if($int_code < 400 || $int_code > 505) { + $int_code = 500; + } $this->sendResponse($arr_response, $int_code); $this->getLogger()->error("[JAPI] [{$int_code}] Error: {$str_log_message}"); } @@ -120,6 +123,7 @@ protected function jsonError(\Exception $obj_error, $int_code) */ protected function sendResponse($response, $http_code = 200) { + $http_code = min(max($http_code, 100), 505); http_response_code($http_code); header('Content-type: application/json'); echo json_encode($response); From deb0c5cfdd3b045ddaac0a0f7320325df7741561 Mon Sep 17 00:00:00 2001 From: twalder-docnet Date: Fri, 3 Jul 2015 14:57:50 +0100 Subject: [PATCH 35/37] Ensure fluent interface for route() method --- src/Docnet/JAPI/SolidRouter.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Docnet/JAPI/SolidRouter.php b/src/Docnet/JAPI/SolidRouter.php index 24e9a48..0be1b0b 100644 --- a/src/Docnet/JAPI/SolidRouter.php +++ b/src/Docnet/JAPI/SolidRouter.php @@ -79,6 +79,7 @@ public function __construct($str_controller_namespace = '\\') * * @param string $str_url * @throws Routing + * @return $this */ public function route($str_url = NULL) { @@ -93,6 +94,7 @@ public function route($str_url = NULL) } $this->setup(implode("\t", $arr_matches['controller'])); } + return $this; } /** From 34884987f061dd083f156e3bf5f2da6e5795fe81 Mon Sep 17 00:00:00 2001 From: Craig McMahon Date: Fri, 3 Jul 2015 20:56:33 +0100 Subject: [PATCH 36/37] Allow getParam to return parameters json_encoded into the request body. Fix to getParams where if get or post had a value that matched a non null default it would not get matched --- composer.lock | 280 +++++++++++++++---------------- src/Docnet/JAPI/Controller.php | 42 ++++- tests/ControllerTest.php | 12 ++ tests/Controllers/JsonParams.php | 21 +++ 4 files changed, 201 insertions(+), 154 deletions(-) create mode 100644 tests/Controllers/JsonParams.php diff --git a/composer.lock b/composer.lock index 132ecb4..b0520c1 100644 --- a/composer.lock +++ b/composer.lock @@ -1,7 +1,7 @@ { "_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", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "e5629c1113a4bccb101f6be8422b3dcc", @@ -48,16 +48,16 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { @@ -68,7 +68,7 @@ "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "2.0.*@ALPHA" + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -77,8 +77,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Instantiator\\": "src" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -98,7 +98,7 @@ "constructor", "instantiate" ], - "time": "2014-10-13 12:58:55" + "time": "2015-06-14 21:17:01" }, { "name": "guzzle/guzzle", @@ -246,16 +246,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.4.0", + "version": "v1.4.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5" + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", - "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", "shasum": "" }, "require": { @@ -302,20 +302,20 @@ "spy", "stub" ], - "time": "2015-03-27 19:31:25" + "time": "2015-04-27 22:15:08" }, { "name": "phpunit/php-code-coverage", - "version": "2.0.15", + "version": "2.1.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" + "reference": "07e27765596d72c378a6103e80da5d84e802f1e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", - "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/07e27765596d72c378a6103e80da5d84e802f1e4", + "reference": "07e27765596d72c378a6103e80da5d84e802f1e4", "shasum": "" }, "require": { @@ -338,7 +338,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -364,7 +364,7 @@ "testing", "xunit" ], - "time": "2015-01-24 10:06:35" + "time": "2015-06-30 06:52:35" }, { "name": "phpunit/php-file-iterator", @@ -415,16 +415,16 @@ }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -433,20 +433,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -455,20 +452,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "83fe1bdc5d47658b727595c14da140da92b3d66d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/83fe1bdc5d47658b727595c14da140da92b3d66d", + "reference": "83fe1bdc5d47658b727595c14da140da92b3d66d", "shasum": "" }, "require": { @@ -477,13 +474,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -499,20 +493,20 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-13 07:35:30" }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/7a9b0969488c3c54fd62b4d504b3ec758fd005d9", + "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9", "shasum": "" }, "require": { @@ -548,20 +542,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "time": "2015-06-19 03:43:16" }, { "name": "phpunit/phpunit", - "version": "4.6.2", + "version": "4.7.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "6c773fda0bdb5ea891d9e4430dcc26c990b9130b" + "reference": "0ebabb4cda7d066be8391dfdbaf57fe70ac9a99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6c773fda0bdb5ea891d9e4430dcc26c990b9130b", - "reference": "6c773fda0bdb5ea891d9e4430dcc26c990b9130b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0ebabb4cda7d066be8391dfdbaf57fe70ac9a99b", + "reference": "0ebabb4cda7d066be8391dfdbaf57fe70ac9a99b", "shasum": "" }, "require": { @@ -572,10 +566,10 @@ "ext-spl": "*", "php": ">=5.3.3", "phpspec/prophecy": "~1.3,>=1.3.1", - "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0", + "phpunit/php-timer": ">=1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", @@ -594,7 +588,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.6.x-dev" + "dev-master": "4.7.x-dev" } }, "autoload": { @@ -620,20 +614,20 @@ "testing", "xunit" ], - "time": "2015-04-07 09:16:49" + "time": "2015-06-30 06:53:57" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.1", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + "reference": "92408bb1968a81b3217a6fdf6c1a198da83caa35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/92408bb1968a81b3217a6fdf6c1a198da83caa35", + "reference": "92408bb1968a81b3217a6fdf6c1a198da83caa35", "shasum": "" }, "require": { @@ -675,7 +669,7 @@ "mock", "xunit" ], - "time": "2015-04-02 05:36:41" + "time": "2015-06-11 15:55:48" }, { "name": "satooshi/php-coveralls", @@ -1090,16 +1084,16 @@ }, { "name": "sebastian/version", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", @@ -1121,25 +1115,24 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" + "time": "2015-06-21 13:59:46" }, { "name": "symfony/config", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Config", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "d91be01336605db8da21b79bc771e46a7276d1bc" + "reference": "58ded81f1f582a87c528ef3dae9a859f78b5f374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/d91be01336605db8da21b79bc771e46a7276d1bc", - "reference": "d91be01336605db8da21b79bc771e46a7276d1bc", + "url": "https://api.github.com/repos/symfony/Config/zipball/58ded81f1f582a87c528ef3dae9a859f78b5f374", + "reference": "58ded81f1f582a87c528ef3dae9a859f78b5f374", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.9", "symfony/filesystem": "~2.3" }, "require-dev": { @@ -1148,11 +1141,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Config\\": "" } }, @@ -1161,36 +1154,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Config Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2015-06-11 14:06:56" }, { "name": "symfony/console", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Console", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667" + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/5b91dc4ed5eb08553f57f6df04c4730a73992667", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667", + "url": "https://api.github.com/repos/symfony/Console/zipball/564398bc1f33faf92fc2ec86859983d30eb81806", + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", @@ -1206,11 +1198,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" } }, @@ -1219,36 +1211,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2015-06-10 15:30:22" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.6", - "target-dir": "Symfony/Component/EventDispatcher", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284" + "reference": "be3c5ff8d503c46768aeb78ce6333051aa6f26d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/be3c5ff8d503c46768aeb78ce6333051aa6f26d9", + "reference": "be3c5ff8d503c46768aeb78ce6333051aa6f26d9", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", @@ -1265,11 +1256,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" } }, @@ -1278,36 +1269,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "homepage": "https://symfony.com", + "time": "2015-06-08 09:37:21" }, { "name": "symfony/filesystem", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Filesystem", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "4983964b3693e4f13449cb3800c64a9112c301b4" + "reference": "a0d43eb3e17d4f4c6990289805a488a0482a07f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4983964b3693e4f13449cb3800c64a9112c301b4", - "reference": "4983964b3693e4f13449cb3800c64a9112c301b4", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a0d43eb3e17d4f4c6990289805a488a0482a07f3", + "reference": "a0d43eb3e17d4f4c6990289805a488a0482a07f3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1315,11 +1305,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Filesystem\\": "" } }, @@ -1328,36 +1318,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Filesystem Component", - "homepage": "http://symfony.com", - "time": "2015-03-22 16:55:57" + "homepage": "https://symfony.com", + "time": "2015-06-08 09:37:21" }, { "name": "symfony/stopwatch", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Stopwatch", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912" + "reference": "c653f1985f6c2b7dbffd04d48b9c0a96aaef814b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/5f196e84b5640424a166d2ce9cca161ce1e9d912", - "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/c653f1985f6c2b7dbffd04d48b9c0a96aaef814b", + "reference": "c653f1985f6c2b7dbffd04d48b9c0a96aaef814b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1365,11 +1354,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Stopwatch\\": "" } }, @@ -1378,36 +1367,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Stopwatch Component", - "homepage": "http://symfony.com", - "time": "2015-03-22 16:55:57" + "homepage": "https://symfony.com", + "time": "2015-06-04 20:11:48" }, { "name": "symfony/yaml", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Yaml", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "174f009ed36379a801109955fc5a71a49fe62dd4" + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/174f009ed36379a801109955fc5a71a49fe62dd4", - "reference": "174f009ed36379a801109955fc5a71a49fe62dd4", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/9808e75c609a14f6db02f70fccf4ca4aab53c160", + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1415,11 +1403,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" } }, @@ -1428,18 +1416,18 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2015-06-10 15:30:22" } ], "aliases": [], diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index ad41548..5da40ef 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -33,7 +33,19 @@ abstract class Controller * * @var null|object|array */ - protected $obj_response = NULL; + protected $obj_response = null; + + /** + * Request body + * @var string + */ + protected $str_request_body = null; + + /** + * Request body decoded as json + * @var string + */ + protected $str_request_body_json = null; /** * Default, empty pre dispatch @@ -97,7 +109,11 @@ protected function getHeaders() */ protected function getBody() { - return file_get_contents('php://input'); + if ($this->str_request_body == null) { + // We store this as prior to php5.6 this can only be read once + $this->str_request_body = file_get_contents('php://input'); + } + return $this->str_request_body; } /** @@ -107,26 +123,36 @@ protected function getBody() */ protected function getJson() { - return json_decode($this->getBody()); + if ($this->str_request_body_json === null) { + $this->str_request_body_json = json_decode($this->str_request_body); + } + return $this->str_request_body_json; } /** - * Get a request parameter. Check GET then POST data. + * Get a request parameter. Check GET then POST data, then optionally any json body data. * * @param string $str_key * @param mixed $str_default + * @param bool $check_json_body * @return mixed */ - protected function getParam($str_key, $str_default = NULL) + protected function getParam($str_key, $str_default = null, $check_json_body = false) { - $str_query = $this->getQuery($str_key, $str_default); - if (NULL !== $str_query) { + $str_query = $this->getQuery($str_key); + if (null !== $str_query) { return $str_query; } - $str_post = $this->getPost($str_key, $str_default); + $str_post = $this->getPost($str_key); if (NULL !== $str_post) { return $str_post; } + // Optionally check Json in Body + if ($check_json_body && isset($this->getJson()->$str_key)) { + if (null !== $this->getJson()->$str_key) { + return $this->getJson()->$str_key; + } + } return $str_default; } diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index 82442fd..e833c2a 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -3,6 +3,7 @@ require_once('Controllers/Example.php'); require_once('Controllers/Headers.php'); require_once('Controllers/Exceptional.php'); +require_once('Controllers/JsonParams.php'); class ControllerTest extends PHPUnit_Framework_TestCase { @@ -61,4 +62,15 @@ public function testCliHeaders() $this->assertEquals($obj_controller->getResponse(), ['Some-Header' => TRUE]); } + public function testJsonBodyParam() + { + $str_json = '{"json_param": "param_found"}'; + $obj_controller = new \JsonParams(); + $obj_controller->setBody($str_json); + $obj_controller->dispatch(); + $obj_response = $obj_controller->getResponse(); + $this->assertEquals('param_found', $obj_response['json_param']); + $this->assertEquals('default_value', $obj_response['missing_param']); + } + } diff --git a/tests/Controllers/JsonParams.php b/tests/Controllers/JsonParams.php new file mode 100644 index 0000000..953b47c --- /dev/null +++ b/tests/Controllers/JsonParams.php @@ -0,0 +1,21 @@ +setResponse([ + 'json_param' => $this->getParam('json_param', 'default_value', true), + 'missing_param' => $this->getParam('missing_param', 'default_value', true) + ]); + } + + /** + * Helper function to set the body + * + * @param string $str_body + */ + public function setBody($str_body) { + $this->str_request_body = $str_body; + } +} \ No newline at end of file From 102de14585b3c081c89c5c6afc648d36622c23f8 Mon Sep 17 00:00:00 2001 From: Craig McMahon Date: Mon, 6 Jul 2015 08:41:14 +0100 Subject: [PATCH 37/37] Minor Fix to Controller Increase code coverage --- src/Docnet/JAPI/Controller.php | 4 ++-- tests/ControllerTest.php | 6 ++++++ tests/Controllers/ProtectedFunctions.php | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/Controllers/ProtectedFunctions.php diff --git a/src/Docnet/JAPI/Controller.php b/src/Docnet/JAPI/Controller.php index 5da40ef..8d38545 100644 --- a/src/Docnet/JAPI/Controller.php +++ b/src/Docnet/JAPI/Controller.php @@ -109,7 +109,7 @@ protected function getHeaders() */ protected function getBody() { - if ($this->str_request_body == null) { + if ($this->str_request_body === null) { // We store this as prior to php5.6 this can only be read once $this->str_request_body = file_get_contents('php://input'); } @@ -124,7 +124,7 @@ protected function getBody() protected function getJson() { if ($this->str_request_body_json === null) { - $this->str_request_body_json = json_decode($this->str_request_body); + $this->str_request_body_json = json_decode($this->getBody()); } return $this->str_request_body_json; } diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index e833c2a..2667094 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -4,6 +4,7 @@ require_once('Controllers/Headers.php'); require_once('Controllers/Exceptional.php'); require_once('Controllers/JsonParams.php'); +require_once('Controllers/ProtectedFunctions.php'); class ControllerTest extends PHPUnit_Framework_TestCase { @@ -73,4 +74,9 @@ public function testJsonBodyParam() $this->assertEquals('default_value', $obj_response['missing_param']); } + public function testIsPost() { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $obj_controller = new ProtectedFunctions(); + $this->assertTrue($obj_controller->getIsPost()); + } } diff --git a/tests/Controllers/ProtectedFunctions.php b/tests/Controllers/ProtectedFunctions.php new file mode 100644 index 0000000..44c7dcb --- /dev/null +++ b/tests/Controllers/ProtectedFunctions.php @@ -0,0 +1,14 @@ +setResponse(true); + } + + + public function getIsPost() { + return $this->isPost(); + } +} \ No newline at end of file