diff --git a/README.md b/README.md
index 4f8c5677..28053f2a 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,8 @@ A self-hosted client that allows custom formatting of data from the hummingbird
### Installation
1. Install dependencies via composer: `composer install`
-2. Change the `WHOSE` constant declaration in `index.php` to your name
-3. Configure settings in `app/config/config.php` and `app/config/routing.php` to your liking
-4. Create the following directories if they don't exist, and make sure they are world writable
+2. Configure settings in `app/config/config.php` and `app/config/routing.php` to your liking
+3. Create the following directories if they don't exist, and make sure they are world writable
* app/cache
* public/images/manga
* public/images/anime
diff --git a/app/config/config.php b/app/config/config.php
index 198199fa..7e59cf92 100644
--- a/app/config/config.php
+++ b/app/config/config.php
@@ -5,6 +5,11 @@ $config = [
// ----------------------------------------------------------------------------
'hummingbird_username' => 'timw4mail',
+ // ----------------------------------------------------------------------------
+ // Whose list is it?
+ // ----------------------------------------------------------------------------
+ 'whose_list' => 'Tim',
+
// ----------------------------------------------------------------------------
// General config
// ----------------------------------------------------------------------------
diff --git a/app/config/routes.php b/app/config/routes.php
index 92e46c47..154f0c4d 100644
--- a/app/config/routes.php
+++ b/app/config/routes.php
@@ -1,6 +1,14 @@
[
+ 'default_namespace' => '\\Aviat\\AnimeClient\\Controller',
+ 'default_controller' => '\\Aviat\\AnimeClient\\Controller\\Anime',
+ 'default_method' => 'index'
+ ],
+ 'configuration' => [
+
+ ],
// Routes on all controllers
'common' => [
'update' => [
@@ -55,10 +63,6 @@ return [
'view' => '[a-z_]+'
]
],
- ],
- // Routes on stats controller
- 'stats' => [
-
],
// Routes on anime controller
'anime' => [
@@ -79,7 +83,6 @@ return [
'action' => ['anime_list'],
'params' => [
'type' => 'all',
- 'title' => WHOSE . " Anime List · All"
],
'tokens' => [
'view' => '[a-z_]+'
@@ -89,8 +92,7 @@ return [
'path' => '/anime/watching{/view}',
'action' => ['anime_list'],
'params' => [
- 'type' => 'currently-watching',
- 'title' => WHOSE . " Anime List · Watching"
+ 'type' => 'watching',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -100,8 +102,7 @@ return [
'path' => '/anime/plan_to_watch{/view}',
'action' => ['anime_list'],
'params' => [
- 'type' => 'plan-to-watch',
- 'title' => WHOSE . " Anime List · Plan to Watch"
+ 'type' => 'plan_to_watch',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -111,8 +112,7 @@ return [
'path' => '/anime/on_hold{/view}',
'action' => ['anime_list'],
'params' => [
- 'type' => 'on-hold',
- 'title' => WHOSE . " Anime List · On Hold"
+ 'type' => 'on_hold',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -123,7 +123,6 @@ return [
'action' => ['anime_list'],
'params' => [
'type' => 'dropped',
- 'title' => WHOSE . " Anime List · Dropped"
],
'tokens' => [
'view' => '[a-z_]+'
@@ -134,7 +133,6 @@ return [
'action' => ['anime_list'],
'params' => [
'type' => 'completed',
- 'title' => WHOSE . " Anime List · Completed"
],
'tokens' => [
'view' => '[a-z_]+'
@@ -156,7 +154,6 @@ return [
'action' => ['manga_list'],
'params' => [
'type' => 'all',
- 'title' => WHOSE . " Manga List · All"
],
'tokens' => [
'view' => '[a-z_]+'
@@ -166,8 +163,7 @@ return [
'path' => '/manga/reading{/view}',
'action' => ['manga_list'],
'params' => [
- 'type' => 'Reading',
- 'title' => WHOSE . " Manga List · Reading"
+ 'type' => 'reading',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -177,8 +173,7 @@ return [
'path' => '/manga/plan_to_read{/view}',
'action' => ['manga_list'],
'params' => [
- 'type' => 'Plan to Read',
- 'title' => WHOSE . " Manga List · Plan to Read"
+ 'type' => 'plan_to_read',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -188,8 +183,7 @@ return [
'path' => '/manga/on_hold{/view}',
'action' => ['manga_list'],
'params' => [
- 'type' => 'On Hold',
- 'title' => WHOSE . " Manga List · On Hold"
+ 'type' => 'on_hold',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -199,8 +193,7 @@ return [
'path' => '/manga/dropped{/view}',
'action' => ['manga_list'],
'params' => [
- 'type' => 'Dropped',
- 'title' => WHOSE . " Manga List · Dropped"
+ 'type' => 'dropped',
],
'tokens' => [
'view' => '[a-z_]+'
@@ -210,8 +203,7 @@ return [
'path' => '/manga/completed{/view}',
'action' => ['manga_list'],
'params' => [
- 'type' => 'Completed',
- 'title' => WHOSE . " Manga List · Completed"
+ 'type' => 'completed',
],
'tokens' => [
'view' => '[a-z_]+'
diff --git a/app/views/header.php b/app/views/header.php
index e1209b97..b9161ec5 100644
--- a/app/views/header.php
+++ b/app/views/header.php
@@ -13,14 +13,14 @@
diff --git a/index.php b/index.php
index 243a05e1..5438dbd7 100644
--- a/index.php
+++ b/index.php
@@ -3,20 +3,7 @@
* Here begins everything!
*/
-// -----------------------------------------------------------------------------
-// ! Start config
-// -----------------------------------------------------------------------------
-
-/**
- * Well, whose list is it?
- */
-define('WHOSE', "Tim's");
-
-// -----------------------------------------------------------------------------
-// ! End config
-// -----------------------------------------------------------------------------
-
-\session_start();
+session_start();
// Work around the silly timezone error
$timezone = ini_get('date.timezone');
@@ -43,29 +30,25 @@ function _dir()
return implode(DIRECTORY_SEPARATOR, func_get_args());
}
+// Set up composer autoloader
+require _dir(ROOT_DIR, '/vendor/autoload.php');
+
/**
* Set up autoloaders
*
* @codeCoverageIgnore
* @return void
*/
-function _setup_autoloaders()
-{
- require _dir(ROOT_DIR, '/vendor/autoload.php');
- spl_autoload_register(function ($class) {
- $class_parts = explode('\\', $class);
- $ns_path = SRC_DIR . '/' . implode('/', $class_parts) . ".php";
+spl_autoload_register(function ($class) {
+ $class_parts = explode('\\', $class);
+ $ns_path = SRC_DIR . '/' . implode('/', $class_parts) . ".php";
- if (file_exists($ns_path))
- {
- require_once($ns_path);
- return;
- }
- });
-}
-
-// Setup autoloaders
-_setup_autoloaders();
+ if (file_exists($ns_path))
+ {
+ require_once($ns_path);
+ return;
+ }
+});
// Do dependency injection, and go!
require _dir(APP_DIR, 'bootstrap.php');
diff --git a/src/Aviat/AnimeClient/Controller.php b/src/Aviat/AnimeClient/Controller.php
index 59a35319..c6e75d9e 100644
--- a/src/Aviat/AnimeClient/Controller.php
+++ b/src/Aviat/AnimeClient/Controller.php
@@ -53,7 +53,6 @@ class Controller {
* Constructor
*
* @param Container $container
- * @param array $web
*/
public function __construct(Container $container)
{
@@ -150,23 +149,6 @@ class Controller {
$this->response->content->set($buffer);
}
- /**
- * Output json with the proper content type
- *
- * @param mixed $data
- * @return void
- */
- public function outputJSON($data)
- {
- if ( ! is_string($data))
- {
- $data = json_encode($data);
- }
-
- $this->response->content->setType('application/json');
- $this->response->content->set($data);
- }
-
/**
* Redirect to the selected page
*
diff --git a/src/Aviat/AnimeClient/Controller/Anime.php b/src/Aviat/AnimeClient/Controller/Anime.php
index 2f81cdf1..7befede0 100644
--- a/src/Aviat/AnimeClient/Controller/Anime.php
+++ b/src/Aviat/AnimeClient/Controller/Anime.php
@@ -50,6 +50,8 @@ class Anime extends BaseController {
/**
* Constructor
+ *
+ * @param Container $container
*/
public function __construct(Container $container)
{
@@ -89,17 +91,38 @@ class Anime extends BaseController {
*
* @param string $type - The section of the list
* @param string $title - The title of the page
+ * @param string $view - List or cover view
* @return void
*/
- public function anime_list($type, $title, $view)
+ public function anime_list($type, $view)
{
+ $type_title_map = [
+ 'all' => 'All',
+ 'watching' => 'Currently Watching',
+ 'plan_to_watch' => 'Plan to Watch',
+ 'on_hold' => 'On Hold',
+ 'dropped' => 'Dropped',
+ 'completed' => 'Completed'
+ ];
+
+ $model_map = [
+ 'watching' => 'currently-watching',
+ 'plan_to_watch' => 'plan-to-watch',
+ 'on_hold' => 'on-hold',
+ 'all' => 'all',
+ 'dropped' => 'dropped',
+ 'completed' => 'completed'
+ ];
+
+ $title = $this->config->whose_list . "'s Anime List · {$type_title_map[$type]}";
+
$view_map = [
'' => 'cover',
'list' => 'list'
];
$data = ($type != 'all')
- ? $this->model->get_list($type)
+ ? $this->model->get_list($model_map[$type])
: $this->model->get_all_lists();
$this->outputHTML('anime/' . $view_map[$view], [
diff --git a/src/Aviat/AnimeClient/Controller/Collection.php b/src/Aviat/AnimeClient/Controller/Collection.php
index d280ea5d..0e7b5c34 100644
--- a/src/Aviat/AnimeClient/Controller/Collection.php
+++ b/src/Aviat/AnimeClient/Controller/Collection.php
@@ -8,6 +8,7 @@ namespace Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\Container;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Config;
+use Aviat\AnimeClient\UrlGenerator;
use Aviat\AnimeClient\Model\Anime as AnimeModel;
use Aviat\AnimeClient\Model\AnimeCollection as AnimeCollectionModel;
@@ -28,6 +29,12 @@ class Collection extends BaseController {
*/
protected $base_data;
+ /**
+ * Url Generator class
+ * @var UrlGenerator
+ */
+ protected $urlGenerator;
+
/**
* Route mapping for main navigation
* @var array $nav_routes
@@ -56,6 +63,7 @@ class Collection extends BaseController {
unset($this->nav_routes['Collection']);
}
+ $this->urlGenerator = $container->get('url-generator');
$this->collection_model = new AnimeCollectionModel($container);
$this->base_data = array_merge($this->base_data, [
'message' => '',
@@ -93,7 +101,7 @@ class Collection extends BaseController {
$data = $this->collection_model->get_collection();
$this->outputHTML('collection/' . $view_map[$view], [
- 'title' => WHOSE . " Anime Collection",
+ 'title' => $this->config->whose_list . "'s Anime Collection",
'sections' => $data,
'genres' => $this->collection_model->get_genre_list()
]);
@@ -111,8 +119,8 @@ class Collection extends BaseController {
$this->outputHTML('collection/'. strtolower($action), [
'action' => $action,
- 'action_url' => $this->config->full_url("collection/" . strtolower($action)),
- 'title' => WHOSE . " Anime Collection · {$action}",
+ 'action_url' => $this->urlGenerator->full_url("collection/" . strtolower($action)),
+ 'title' => $this->config->whose_list . " Anime Collection · {$action}",
'media_items' => $this->collection_model->get_media_type_list(),
'item' => ($action === "Edit") ? $this->collection_model->get($id) : []
]);
diff --git a/src/Aviat/AnimeClient/Controller/Manga.php b/src/Aviat/AnimeClient/Controller/Manga.php
index 9b58d705..1a2f7218 100644
--- a/src/Aviat/AnimeClient/Controller/Manga.php
+++ b/src/Aviat/AnimeClient/Controller/Manga.php
@@ -72,19 +72,29 @@ class Manga extends Controller {
* Get a section of the manga list
*
* @param string $status
- * @param string $title
* @param string $view
* @return void
*/
- public function manga_list($status, $title, $view)
+ public function manga_list($status, $view)
{
+ $map = [
+ 'all' => 'All',
+ 'plan_to_read' => 'Plan to Read',
+ 'reading' => 'Reading',
+ 'completed' => 'Completed',
+ 'dropped' => 'Dropped',
+ 'on_hold' => 'On Hold'
+ ];
+
+ $title = $this->config->whose_list . "' Manga List · {$map[$status]}";
+
$view_map = [
'' => 'cover',
'list' => 'list'
];
$data = ($status !== 'all')
- ? [$status => $this->model->get_list($status)]
+ ? [$map[$status] => $this->model->get_list($map[$status])]
: $this->model->get_all_lists();
$this->outputHTML('manga/' . $view_map[$view], [
diff --git a/src/Aviat/AnimeClient/Model.php b/src/Aviat/AnimeClient/Model.php
index 8e70f8bf..69c4d5b0 100644
--- a/src/Aviat/AnimeClient/Model.php
+++ b/src/Aviat/AnimeClient/Model.php
@@ -25,6 +25,8 @@ class Model {
/**
* Constructor
+ *
+ * @param Container $container
*/
public function __construct(Container $container)
{
diff --git a/src/Aviat/AnimeClient/Model/API.php b/src/Aviat/AnimeClient/Model/API.php
index 1a0501ff..b774eda1 100644
--- a/src/Aviat/AnimeClient/Model/API.php
+++ b/src/Aviat/AnimeClient/Model/API.php
@@ -33,6 +33,8 @@ class API extends \Aviat\AnimeClient\Model {
/**
* Constructor
+ *
+ * @param Container $container
*/
public function __construct(Container $container)
{
diff --git a/src/Aviat/AnimeClient/Model/AnimeCollection.php b/src/Aviat/AnimeClient/Model/AnimeCollection.php
index 20c2fc90..78c89ac7 100644
--- a/src/Aviat/AnimeClient/Model/AnimeCollection.php
+++ b/src/Aviat/AnimeClient/Model/AnimeCollection.php
@@ -28,6 +28,8 @@ class AnimeCollection extends DB {
/**
* Constructor
+ *
+ * @param Container $container
*/
public function __construct(Container $container)
{
diff --git a/src/Aviat/AnimeClient/Model/DB.php b/src/Aviat/AnimeClient/Model/DB.php
index 0cbda864..2f813aee 100644
--- a/src/Aviat/AnimeClient/Model/DB.php
+++ b/src/Aviat/AnimeClient/Model/DB.php
@@ -24,6 +24,8 @@ class DB extends \Aviat\AnimeClient\Model {
/**
* Constructor
+ *
+ * @param Container $container
*/
public function __construct(Container $container)
{
diff --git a/src/Aviat/AnimeClient/Model/Stats.php b/src/Aviat/AnimeClient/Model/Stats.php
index 32533fb1..993ea1be 100644
--- a/src/Aviat/AnimeClient/Model/Stats.php
+++ b/src/Aviat/AnimeClient/Model/Stats.php
@@ -15,7 +15,7 @@ class Stats extends DB {
/**
* Constructor
*
- * @param Config $config
+ * @param Container $container
*/
public function __construct(Container $container)
{
diff --git a/src/Aviat/AnimeClient/Router.php b/src/Aviat/AnimeClient/Router.php
index 8b0b6b7e..f496b59f 100644
--- a/src/Aviat/AnimeClient/Router.php
+++ b/src/Aviat/AnimeClient/Router.php
@@ -24,12 +24,6 @@ class Router extends RoutingBase {
*/
protected $request;
- /**
- * Array containing request and response objects
- * @var array $web
- */
- protected $web;
-
/**
* Routes added to router
* @var array $output_routes
@@ -46,7 +40,6 @@ class Router extends RoutingBase {
parent::__construct($container);
$this->router = $container->get('aura-router');
$this->request = $container->get('request');
- $this->web = [$this->request, $container->get('response')];
$this->output_routes = $this->_setup_routes();
}
@@ -154,6 +147,35 @@ class Router extends RoutingBase {
return $controller;
}
+ /**
+ * Get the list of controllers in the default namespace
+ *
+ * @return array
+ */
+ public function get_controller_list()
+ {
+ $convention_routing = $this->routes['convention'];
+ $default_namespace = $convention_routing['default_namespace'];
+ $path = str_replace('\\', '/', $default_namespace);
+ $path = trim($path, '/');
+ $actual_path = \_dir(SRC_DIR, $path);
+
+ $class_files = glob("{$actual_path}/*.php");
+
+ $controllers = [];
+
+ foreach($class_files as $file)
+ {
+ $raw_class_name = basename(str_replace(".php", "", $file));
+ $path = strtolower(basename($raw_class_name));
+ $class_name = trim($default_namespace . '\\' . $raw_class_name, '\\');
+
+ $controllers[$path] = $class_name;
+ }
+
+ return $controllers;
+ }
+
/**
* Select controller based on the current url, and apply its relevent routes
*
@@ -176,7 +198,8 @@ class Router extends RoutingBase {
$path = $route['path'];
unset($route['path']);
- $controller_class = '\\Aviat\\AnimeClient\\Controller\\' . ucfirst($route_type);
+ $controller_map = $this->get_controller_list();
+ $controller_class = $controller_map[$route_type];
// Prepend the controller to the route parameters
array_unshift($route['action'], $controller_class);
diff --git a/src/Aviat/Ion/Base/Container.php b/src/Aviat/Ion/Base/Container.php
index dd9af5d5..cfb40db3 100644
--- a/src/Aviat/Ion/Base/Container.php
+++ b/src/Aviat/Ion/Base/Container.php
@@ -8,12 +8,16 @@ namespace Aviat\Ion\Base;
class Container {
/**
+ * Array with class instances
+ *
* @var array
*/
protected $container = [];
/**
* Constructor
+ *
+ * @param array $values (optional)
*/
public function __construct(array $values = [])
{
diff --git a/src/Aviat/Ion/Base/Page.php b/src/Aviat/Ion/Base/Page.php
deleted file mode 100644
index e054be94..00000000
--- a/src/Aviat/Ion/Base/Page.php
+++ /dev/null
@@ -1,72 +0,0 @@
-request = $request;
- $this->response = $response;
- }
-
- /**
- * __destruct function.
- */
- public function __destruct()
- {
- $this->output();
- }
-
- /**
- * Output the response to the client
- */
- protected function output()
- {
- // send status
- @header($this->response->status->get(), true, $this->response->status->getCode());
-
- // headers
- foreach($this->response->headers->get() as $label => $value)
- {
- @header("{$label}: {$value}");
- }
-
- // cookies
- foreach($this->response->cookies->get() as $name => $cookie)
- {
- @setcookie(
- $name,
- $cookie['value'],
- $cookie['expire'],
- $cookie['path'],
- $cookie['domain'],
- $cookie['secure'],
- $cookie['httponly']
- );
- }
-
- // send the actual response
- echo $this->response->content->get();
- }
-}
-// End of Page.php
\ No newline at end of file
diff --git a/tests/AnimeClient/RouterTest.php b/tests/AnimeClient/RouterTest.php
index 8d66198c..1fe6c295 100644
--- a/tests/AnimeClient/RouterTest.php
+++ b/tests/AnimeClient/RouterTest.php
@@ -58,6 +58,9 @@ class RouterTest extends AnimeClient_TestCase {
{
$default_config = array(
'routes' => [
+ 'convention' => [
+ 'default_namespace' => '\\Aviat\\AnimeClient\\Controller'
+ ],
'common' => [
'login_form' => [
'path' => '/login',
@@ -171,6 +174,9 @@ class RouterTest extends AnimeClient_TestCase {
'default_list' => 'manga'
],
'routes' => [
+ 'convention' => [
+ 'default_namespace' => '\\Aviat\\AnimeClient\\Controller'
+ ],
'common' => [
'login_form' => [
'path' => '/login',
@@ -207,4 +213,58 @@ class RouterTest extends AnimeClient_TestCase {
$this->assertEquals('//localhost/anime/watching', $this->urlGenerator->default_url('anime'), "Incorrect default url");
$this->assertEquals('', $this->urlGenerator->default_url('foo'), "Incorrect default url");
}
+
+ public function dataGetControllerList()
+ {
+ return array(
+ 'controller_list_sanity_check' => [
+ 'config' => [
+ 'routing' => [
+ 'anime_path' => 'anime',
+ 'manga_path' => 'manga',
+ 'default_anime_path' => "/anime/watching",
+ 'default_manga_path' => '/manga/all',
+ 'default_list' => 'manga'
+ ],
+ 'routes' => [
+ 'convention' => [
+ 'default_namespace' => '\\Aviat\\AnimeClient\\Controller'
+ ]
+ ]
+ ],
+ 'expected' => [
+ 'anime' => 'Aviat\AnimeClient\Controller\Anime',
+ 'manga' => 'Aviat\AnimeClient\Controller\Manga',
+ 'collection' => 'Aviat\AnimeClient\Controller\Collection',
+ 'stats' => 'Aviat\AnimeClient\Controller\Stats'
+ ]
+ ],
+ 'empty_controller_list' => [
+ 'config' => [
+ 'routing' => [
+ 'anime_path' => 'anime',
+ 'manga_path' => 'manga',
+ 'default_anime_path' => "/anime/watching",
+ 'default_manga_path' => '/manga/all',
+ 'default_list' => 'manga'
+ ],
+ 'routes' => [
+ 'convention' => [
+ 'default_namespace' => '\\Aviat\\Ion\\Controller'
+ ]
+ ]
+ ],
+ 'expected' => []
+ ]
+ );
+ }
+
+ /**
+ * @dataProvider dataGetControllerList
+ */
+ public function testGetControllerList($config, $expected)
+ {
+ $this->_set_up($config, '/', 'localhost');
+ $this->assertEquals($expected, $this->router->get_controller_list());
+ }
}
\ No newline at end of file