From 3e53ec152654d3cb1c4d5873ffff045be39fca49 Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Tue, 30 Jun 2015 13:03:20 -0400 Subject: [PATCH] More dependency injection, and code coverage --- app/base/BaseApiModel.php | 4 +- app/base/BaseController.php | 23 +++- app/base/BaseDBModel.php | 4 +- app/base/BaseModel.php | 3 +- app/base/Router.php | 142 ++++++++++++++------ app/bootstrap.php | 2 - app/config/config.php | 5 +- app/controllers/AnimeController.php | 4 +- app/controllers/MangaController.php | 2 +- app/models/AnimeCollectionModel.php | 6 +- app/models/AnimeModel.php | 4 +- app/models/MangaModel.php | 7 + app/views/header.php | 10 +- app/views/login.php | 4 +- phpunit.xml | 3 + tests/base/BaseApiModelTest.php | 6 +- tests/base/BaseControllerTest.php | 31 +++++ tests/base/BaseDBModelTest.php | 2 +- tests/base/BaseModelTest.php | 2 +- tests/base/RouterTest.php | 192 ++++++++++++++++++++++++++++ tests/bootstrap.php | 15 ++- 21 files changed, 402 insertions(+), 69 deletions(-) create mode 100644 tests/base/BaseControllerTest.php create mode 100644 tests/base/RouterTest.php diff --git a/app/base/BaseApiModel.php b/app/base/BaseApiModel.php index 1c6679ad..bc1edc87 100644 --- a/app/base/BaseApiModel.php +++ b/app/base/BaseApiModel.php @@ -33,9 +33,9 @@ class BaseApiModel extends BaseModel { /** * Constructor */ - public function __construct() + public function __construct(Config $config) { - parent::__construct(); + parent::__construct($config); $this->cookieJar = new CookieJar(); $this->client = new Client([ diff --git a/app/base/BaseController.php b/app/base/BaseController.php index 01c1e489..28adef0b 100644 --- a/app/base/BaseController.php +++ b/app/base/BaseController.php @@ -39,12 +39,19 @@ class BaseController { * Common data to be sent to views * @var array */ - protected $base_data = []; + protected $base_data = [ + 'url_type' => 'anime', + 'other_type' => 'manga', + 'nav_routes' => [] + ]; /** * Constructor + * + * @param \AnimeClient\Client $config + * @param array $web */ - public function __construct(Config $config, Array $web) + public function __construct(Config &$config, Array $web) { $this->config = $config; @@ -53,6 +60,11 @@ class BaseController { $this->response = $response; } + /** + * Destructor + * + * @codeCoverageIgnore + */ public function __destruct() { $this->output(); @@ -61,6 +73,7 @@ class BaseController { /** * Get the string output of a partial template * + * @codeCoverageIgnore * @param string $template * @param array|object $data * @return string @@ -99,6 +112,7 @@ class BaseController { /** * Output a template to HTML, using the provided data * + * @codeCoverageIgnore * @param string $template * @param array|object $data * @return void @@ -131,6 +145,7 @@ class BaseController { /** * Redirect to the selected page * + * @codeCoverageIgnore * @param string $url * @param int $code * @return void @@ -152,6 +167,7 @@ class BaseController { /** * Add a message box to the page * + * @codeCoverageIgnore * @param string $type * @param string $message * @return string @@ -167,6 +183,7 @@ class BaseController { /** * Clear the api session * + * @codeCoverageIgnore * @return void */ public function logout() @@ -178,6 +195,7 @@ class BaseController { /** * Show the login form * + * @codeCoverageIgnore * @param string $status * @return void */ @@ -220,6 +238,7 @@ class BaseController { /** * Send the appropriate response * + * @codeCoverageIgnore * @return void */ private function output() diff --git a/app/base/BaseDBModel.php b/app/base/BaseDBModel.php index d2a7e52f..ae273509 100644 --- a/app/base/BaseDBModel.php +++ b/app/base/BaseDBModel.php @@ -23,9 +23,9 @@ class BaseDBModel extends BaseModel { /** * Constructor */ - public function __construct() + public function __construct(Config $config) { - parent::__construct(); + parent::__construct($config); $this->db_config = $this->config->database; } } diff --git a/app/base/BaseModel.php b/app/base/BaseModel.php index e3710e28..a28e9c3c 100644 --- a/app/base/BaseModel.php +++ b/app/base/BaseModel.php @@ -20,9 +20,8 @@ class BaseModel { /** * Constructor */ - public function __construct() + public function __construct(Config &$config) { - global $config; $this->config = $config; } diff --git a/app/base/Router.php b/app/base/Router.php index 93243ba4..829b2c5d 100644 --- a/app/base/Router.php +++ b/app/base/Router.php @@ -22,12 +22,24 @@ class Router { */ protected $config; + /** + * Class wrapper for input superglobals + * @var object + */ + protected $request; + /** * Array containing request and response objects * @var array $web */ protected $web; + /** + * Routes added to router + * @var array $output_routes + */ + protected $output_routes; + /** * Constructor * @@ -37,9 +49,10 @@ class Router { { $this->config = $config; $this->router = $router; + $this->request = $request; $this->web = [$request, $response]; - $this->_setup_routes(); + $this->output_routes = $this->_setup_routes(); } /** @@ -51,7 +64,7 @@ class Router { { global $defaultHandler; - $raw_route = $_SERVER['REQUEST_URI']; + $raw_route = $this->request->server->get('REQUEST_URI'); $route_path = str_replace([$this->config->anime_path, $this->config->manga_path], '', $raw_route); $route_path = "/" . trim($route_path, '/'); @@ -64,9 +77,20 @@ class Router { return $route; } + /** + * Get list of routes applied + * + * @return array + */ + public function get_output_routes() + { + return $this->output_routes; + } + /** * Handle the current route * + * @codeCoverageIgnore * @param [object] $route * @return void */ @@ -84,7 +108,7 @@ class Router { $failure = $this->router->getFailedRoute(); $defaultHandler->addDataTable('failed_route', (array)$failure); - $controller_name = 'BaseController'; + $controller_name = '\\AnimeClient\\BaseController'; $action_method = 'outputHTML'; $params = [ 'template' => '404', @@ -117,59 +141,101 @@ class Router { call_user_func_array([$controller, $action_method], $params); } + /** + * Get the type of route, to select the current controller + * + * @return string + */ + public function get_route_type() + { + $route_type = ""; + + $host = $this->request->server->get("HTTP_HOST"); + $request_uri = $this->request->server->get('REQUEST_URI'); + + // Host-based controller selection + if ($this->config->route_by === "host") + { + if (strtolower($host) === strtolower($this->config->anime_host)) + { + $route_type = "anime"; + } + + if (strtolower($host) === strtolower($this->config->manga_host)) + { + $route_type = "manga"; + } + } + + // Path-based controller selection + if ($this->config->route_by === "path") + { + $path = trim($request_uri, '/'); + + if (stripos($path, trim($this->config->anime_path, '/')) === 0) + { + $route_type = "anime"; + } + + if (stripos($path, trim($this->config->manga_path, '/')) === 0) + { + $route_type = "manga"; + } + } + + return $route_type; + } + /** * Select controller based on the current url, and apply its relevent routes * - * @return void + * @return array */ - private function _setup_routes() + public function _setup_routes() { $route_map = [ 'anime' => '\\AnimeClient\\AnimeController', 'manga' => '\\AnimeClient\\MangaController', ]; - $route_type = "anime"; - if ($this->config->manga_host !== "" && strpos($_SERVER['HTTP_HOST'], $this->config->manga_host) !== FALSE) - { - $route_type = "manga"; - } - else if ($this->config->manga_path !== "" && strpos($_SERVER['REQUEST_URI'], $this->config->manga_path) !== FALSE) - { - $route_type = "manga"; - } + $output_routes = []; - $routes = $this->config->routes; + $route_type = $this->get_route_type(); + + // Return early if invalid route array + if ( ! array_key_exists($route_type, $this->config->routes)) return []; + + $applied_routes = array_merge($this->config->routes['common'], $this->config->routes[$route_type]); // Add routes - foreach(['common', $route_type] as $key) + foreach($applied_routes as $name => &$route) { - foreach($routes[$key] as $name => &$route) + $path = $route['path']; + unset($route['path']); + + // Prepend the controller to the route parameters + array_unshift($route['action'], $route_map[$route_type]); + + // Select the appropriate router method based on the http verb + $add = (array_key_exists('verb', $route)) ? "add" . ucfirst(strtolower($route['verb'])) : "addGet"; + + // Add the route to the router object + if ( ! array_key_exists('tokens', $route)) { - $path = $route['path']; - unset($route['path']); + $output_routes[] = $this->router->$add($name, $path)->addValues($route); + } + else + { + $tokens = $route['tokens']; + unset($route['tokens']); - // Prepend the controller to the route parameters - array_unshift($route['action'], $route_map[$route_type]); - - // Select the appropriate router method based on the http verb - $add = (array_key_exists('verb', $route)) ? "add" . ucfirst(strtolower($route['verb'])) : "addGet"; - - if ( ! array_key_exists('tokens', $route)) - { - $this->router->$add($name, $path)->addValues($route); - } - else - { - $tokens = $route['tokens']; - unset($route['tokens']); - - $this->router->$add($name, $path) - ->addValues($route) - ->addTokens($tokens); - } + $output_routes[] = $this->router->$add($name, $path) + ->addValues($route) + ->addTokens($tokens); } } + + return $output_routes; } } // End of Router.php \ No newline at end of file diff --git a/app/bootstrap.php b/app/bootstrap.php index 49ae0fe3..06f2ebcd 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -6,8 +6,6 @@ use \Whoops\Handler\PrettyPageHandler; use \Whoops\Handler\JsonResponseHandler; use \Aura\Web\WebFactory; use \Aura\Router\RouterFactory; -use \GuzzleHttp\Client; -use \GuzzleHttp\Cookie\CookieJar; // ----------------------------------------------------------------------------- // Setup error handling diff --git a/app/config/config.php b/app/config/config.php index e2e62f2f..dd505833 100644 --- a/app/config/config.php +++ b/app/config/config.php @@ -22,10 +22,11 @@ $config = [ // Routing // // Route by path, or route by domain. To route by path, set the _host suffixed - // options to an empty string. To route by host, set the _path suffixed options - // to an empty string + // options to an empty string, and set 'route_by' to 'path'. To route by host, set + // the _path suffixed options to an empty string, and set 'route_by' to 'host'. // ---------------------------------------------------------------------------- + 'route_by' => 'host', // host or path 'anime_host' => 'anime.timshomepage.net', 'manga_host' => 'manga.timshomepage.net', 'anime_path' => '', diff --git a/app/controllers/AnimeController.php b/app/controllers/AnimeController.php index 6c40cc7c..81d24fee 100644 --- a/app/controllers/AnimeController.php +++ b/app/controllers/AnimeController.php @@ -54,8 +54,8 @@ class AnimeController extends BaseController { unset($this->nav_routes['Collection']); } - $this->model = new AnimeModel(); - $this->collection_model = new AnimeCollectionModel(); + $this->model = new AnimeModel($config); + $this->collection_model = new AnimeCollectionModel($config); $this->base_data = [ 'message' => '', 'url_type' => 'anime', diff --git a/app/controllers/MangaController.php b/app/controllers/MangaController.php index 550b28c5..846a6eb5 100644 --- a/app/controllers/MangaController.php +++ b/app/controllers/MangaController.php @@ -41,7 +41,7 @@ class MangaController extends BaseController { public function __construct(Config $config, Array $web) { parent::__construct($config, $web); - $this->model = new MangaModel(); + $this->model = new MangaModel($config); $this->base_data = [ 'url_type' => 'manga', 'other_type' => 'anime', diff --git a/app/models/AnimeCollectionModel.php b/app/models/AnimeCollectionModel.php index 184fed84..e350a835 100644 --- a/app/models/AnimeCollectionModel.php +++ b/app/models/AnimeCollectionModel.php @@ -25,12 +25,12 @@ class AnimeCollectionModel extends BaseDBModel { /** * Constructor */ - public function __construct() + public function __construct(Config $config) { - parent::__construct(); + parent::__construct($config); $this->db = \Query($this->db_config['collection']); - $this->anime_model = new AnimeModel(); + $this->anime_model = new AnimeModel($config); // Is database valid? If not, set a flag so the // app can be run without a valid database diff --git a/app/models/AnimeModel.php b/app/models/AnimeModel.php index 52a269cf..a4bd5be3 100644 --- a/app/models/AnimeModel.php +++ b/app/models/AnimeModel.php @@ -18,9 +18,9 @@ class AnimeModel extends BaseApiModel { /** * Constructor */ - public function __construct() + public function __construct(Config $config) { - parent::__construct(); + parent::__construct($config); } /** diff --git a/app/models/MangaModel.php b/app/models/MangaModel.php index 7a23622d..ebef7243 100644 --- a/app/models/MangaModel.php +++ b/app/models/MangaModel.php @@ -15,6 +15,13 @@ class MangaModel extends BaseApiModel { */ protected $base_url = "https://hummingbird.me/"; + /** + * Constructor + */ + public function __construct(Config $config) + { + parent::__construct($config); + } /** * Update the selected manga diff --git a/app/views/header.php b/app/views/header.php index cc1095c0..5705f68f 100644 --- a/app/views/header.php +++ b/app/views/header.php @@ -11,7 +11,11 @@

- ["> List] + + "> + + ["> List] + [">Logout] @@ -20,6 +24,7 @@

+ -
\ No newline at end of file +
+ \ No newline at end of file diff --git a/app/views/login.php b/app/views/login.php index 488f2a95..44f4ba22 100644 --- a/app/views/login.php +++ b/app/views/login.php @@ -3,8 +3,8 @@