Version 5.1 - All the GraphQL #32
@ -5,47 +5,24 @@
|
||||
|
||||
namespace Aviat\AnimeClient;
|
||||
|
||||
use \Whoops\Handler\PrettyPageHandler;
|
||||
use \Whoops\Handler\JsonResponseHandler;
|
||||
use Aura\Html\HelperLocatorFactory;
|
||||
use \Aura\Web\WebFactory;
|
||||
use \Aura\Router\RouterFactory;
|
||||
use \Aura\Session\SessionFactory;
|
||||
|
||||
use Aura\Web\WebFactory;
|
||||
use Aura\Router\RouterFactory;
|
||||
use Aura\Session\SessionFactory;
|
||||
use Aviat\Ion\Di\Container;
|
||||
|
||||
require _dir(SRC_DIR, '/functions.php');
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Setup DI container
|
||||
// -----------------------------------------------------------------------------
|
||||
$di = function() {
|
||||
return function(array $config_array = []) {
|
||||
$container = new Container();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Setup error handling
|
||||
// -------------------------------------------------------------------------
|
||||
$whoops = new \Whoops\Run();
|
||||
|
||||
// Set up default handler for general errors
|
||||
$defaultHandler = new PrettyPageHandler();
|
||||
$whoops->pushHandler($defaultHandler);
|
||||
|
||||
// Set up json handler for ajax errors
|
||||
$jsonHandler = new JsonResponseHandler();
|
||||
$jsonHandler->onlyForAjaxRequests(TRUE);
|
||||
$whoops->pushHandler($jsonHandler);
|
||||
|
||||
$whoops->register();
|
||||
|
||||
$container->set('error-handler', $defaultHandler);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Injected Objects
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Create Config Object
|
||||
$config = new Config();
|
||||
$config = new Config($config_array);
|
||||
$container->set('config', $config);
|
||||
|
||||
// Create Aura Router Object
|
||||
@ -79,14 +56,11 @@ $di = function() {
|
||||
$container->set('url-generator', new UrlGenerator($container));
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Router
|
||||
// Dispatcher
|
||||
// -------------------------------------------------------------------------
|
||||
$router = new Router($container);
|
||||
$container->set('router', $router);
|
||||
$container->set('dispatcher', new Dispatcher($container));
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
$di()->get('router')->dispatch();
|
||||
|
||||
// End of bootstrap.php
|
@ -1,24 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'top' => [
|
||||
'default' => '',
|
||||
'items' => [
|
||||
'anime_list' => '{anime_list}',
|
||||
'manga_list' => '{manga_list}',
|
||||
'collection' => '{collection}'
|
||||
]
|
||||
],
|
||||
'view_type' => [
|
||||
'is_parent' => FALSE,
|
||||
'default' => 'cover_view',
|
||||
'items' => [
|
||||
'cover_view' => '{parent}',
|
||||
'list_view' => '{parent}/list'
|
||||
]
|
||||
],
|
||||
'anime_list' => [
|
||||
'default' => '',
|
||||
'route_prefix' => '/anime',
|
||||
'items' => [
|
||||
'watching' => '/watching',
|
||||
@ -27,13 +10,9 @@ return [
|
||||
'dropped' => '/dropped',
|
||||
'completed' => '/completed',
|
||||
'all' => '/all'
|
||||
],
|
||||
'children' => [
|
||||
'view_type'
|
||||
]
|
||||
],
|
||||
'manga_list' => [
|
||||
'default' => '',
|
||||
'route_prefix' => '/manga',
|
||||
'items' => [
|
||||
'reading' => '/reading',
|
||||
@ -42,20 +21,13 @@ return [
|
||||
'dropped' => '/dropped',
|
||||
'completed' => '/completed',
|
||||
'all' => '/all'
|
||||
],
|
||||
'children' => [
|
||||
'view_type'
|
||||
]
|
||||
],
|
||||
'collection' => [
|
||||
'default' => '',
|
||||
'route_prefix' => '/collection',
|
||||
'items' => [
|
||||
'anime' => '/anime',
|
||||
'manga' => '/manga',
|
||||
],
|
||||
'children' => [
|
||||
'view_type'
|
||||
]
|
||||
]
|
||||
];
|
@ -8,7 +8,6 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Alternate Title</th>
|
||||
<th>Airing Status</th>
|
||||
<th>Score</th>
|
||||
<th>Type</th>
|
||||
@ -25,19 +24,21 @@
|
||||
<a href="<?= $item['anime']['url'] ?>">
|
||||
<?= $item['anime']['title'] ?>
|
||||
</a>
|
||||
<?= ( ! empty($item['anime']['alternate_title'])) ? " <br /> " . $item['anime']['alternate_title'] : "" ?>
|
||||
</td>
|
||||
<td class="align_left"><?= $item['anime']['alternate_title'] ?></td>
|
||||
<td class="align_left"><?= $item['airing']['status'] ?></td>
|
||||
<td><?= $item['user_rating'] ?> / 10 </td>
|
||||
<td><?= $item['anime']['type'] ?></td>
|
||||
<td>Episodes: <?= $item['episodes']['watched'] ?> / <?= $item['episodes']['total'] ?></td>
|
||||
<td><?= $item['anime']['age_rating'] ?></td>
|
||||
<td><?= $item['notes'] ?></td>
|
||||
<td class="flex flex-justify-space-around align-left">
|
||||
<td class="align-left">
|
||||
<ul>
|
||||
<?php sort($item['anime']['genres']) ?>
|
||||
<?php foreach($item['anime']['genres'] as $genre): ?>
|
||||
<span><?= $genre ?></span>
|
||||
<li><?= $genre ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
|
@ -24,20 +24,14 @@
|
||||
<?php endif */ ?>
|
||||
</span>
|
||||
</h1>
|
||||
<?php if ( ! empty($nav_routes)): ?>
|
||||
<nav>
|
||||
<ul>
|
||||
<?php foreach($nav_routes as $title => $nav_path): ?>
|
||||
<li class="<?= is_selected($nav_path, $route_path) ?>"><a href="<?= $urlGenerator->url($nav_path) ?>"><?= $title ?></a></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?= $helper->menu($menu_name) ?>
|
||||
<?php if (is_view_page()): ?>
|
||||
<br />
|
||||
<ul>
|
||||
<li class="<?= is_not_selected('list', last_segment()) ?>"><a href="<?= $urlGenerator->url($route_path) ?>">Cover View</a></li>
|
||||
<li class="<?= is_selected('list', last_segment()) ?>"><a href="<?= $urlGenerator->url("{$route_path}/list") ?>">List View</a></li>
|
||||
<ul class="align_right">
|
||||
<li class="<?= is_not_selected('list', $urlGenerator->last_segment()) ?>"><a href="<?= $urlGenerator->url($route_path) ?>">Cover View</a></li>
|
||||
<li class="<?= is_selected('list', $urlGenerator->last_segment()) ?>"><a href="<?= $urlGenerator->url("{$route_path}/list") ?>">List View</a></li>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
</nav>
|
||||
<br />
|
||||
<?php endif ?>
|
||||
|
37
index.php
37
index.php
@ -2,6 +2,10 @@
|
||||
/**
|
||||
* Here begins everything!
|
||||
*/
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Whoops\Handler\JsonResponseHandler;
|
||||
|
||||
use Aviat\AnimeClient\Config;
|
||||
|
||||
// Work around the silly timezone error
|
||||
$timezone = ini_get('date.timezone');
|
||||
@ -47,6 +51,37 @@ spl_autoload_register(function($class) {
|
||||
|
||||
// Dependency setup
|
||||
require _dir(ROOT_DIR, '/vendor/autoload.php');
|
||||
require _dir(APP_DIR, 'bootstrap.php');
|
||||
require _dir(SRC_DIR, '/functions.php');
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Setup error handling
|
||||
// -------------------------------------------------------------------------
|
||||
$whoops = new \Whoops\Run();
|
||||
|
||||
// Set up default handler for general errors
|
||||
$defaultHandler = new PrettyPageHandler();
|
||||
$whoops->pushHandler($defaultHandler);
|
||||
|
||||
// Set up json handler for ajax errors
|
||||
$jsonHandler = new JsonResponseHandler();
|
||||
$jsonHandler->onlyForAjaxRequests(TRUE);
|
||||
$whoops->pushHandler($jsonHandler);
|
||||
|
||||
//$whoops->register();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dependency Injection setup
|
||||
// -----------------------------------------------------------------------------
|
||||
require _dir(CONF_DIR, 'base_config.php'); // $base_config
|
||||
require _dir(CONF_DIR, 'config.php'); // $config
|
||||
$config_array = array_merge($base_config, $config);
|
||||
$di = require _dir(APP_DIR, 'bootstrap.php');
|
||||
$container = $di($config_array);
|
||||
$container->set('error-handler', $defaultHandler);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dispatch to the current route
|
||||
// -----------------------------------------------------------------------------
|
||||
$container->get('dispatcher')();
|
||||
|
||||
// End of index.php
|
@ -5,6 +5,9 @@ namespace Aviat\AnimeClient\Auth;
|
||||
use Aviat\Ion\Di\ContainerInterface;
|
||||
use Aviat\AnimeClient\Model\Anime as AnimeModel;
|
||||
|
||||
/**
|
||||
* Hummingbird API Authentication
|
||||
*/
|
||||
class HummingbirdAuth {
|
||||
|
||||
use \Aviat\Ion\Di\ContainerAware;
|
||||
@ -31,19 +34,32 @@ class HummingbirdAuth {
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->setContainer($container);
|
||||
$this->session = $container->get('sesion')
|
||||
$this->session = $container->get('session')
|
||||
->getSegment(__NAMESPACE__);
|
||||
$this->model = new AnimeModel($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the appropriate authentication call,
|
||||
* and save the resulting auth token if successful
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
|
||||
return $this->model->authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the authentication token from the session
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_auth_token()
|
||||
{
|
||||
|
||||
return $this->session->get('auth_token');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,27 +15,16 @@ class Config {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [];
|
||||
protected $map = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $config_files
|
||||
*/
|
||||
public function __construct(array $config_files = [])
|
||||
public function __construct(array $config_array = [])
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (empty($config_files))
|
||||
{
|
||||
require_once \_dir(CONF_DIR, 'config.php'); // $config
|
||||
require_once \_dir(CONF_DIR, 'base_config.php'); // $base_config
|
||||
|
||||
$this->config = array_merge($config, $base_config);
|
||||
}
|
||||
else // @codeCoverageIgnoreEnd
|
||||
{
|
||||
$this->config = $config_files;
|
||||
}
|
||||
$this->map = $config_array;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,9 +35,9 @@ class Config {
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (isset($this->config[$key]))
|
||||
if (array_key_exists($key, $this->map))
|
||||
{
|
||||
return $this->config[$key];
|
||||
return $this->map[$key];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -63,7 +52,7 @@ class Config {
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->config[$key] = $value;
|
||||
$this->map[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class Controller {
|
||||
protected $base_data = [
|
||||
'url_type' => 'anime',
|
||||
'other_type' => 'manga',
|
||||
'nav_routes' => []
|
||||
'menu_name' => ''
|
||||
];
|
||||
|
||||
/**
|
||||
@ -105,7 +105,7 @@ class Controller {
|
||||
{
|
||||
$errorHandler = $this->container->get('error-handler');
|
||||
$errorHandler->addDataTable('Template Data', $data);
|
||||
$router = $this->container->get('router');
|
||||
$router = $this->container->get('dispatcher');
|
||||
|
||||
if (isset($this->base_data))
|
||||
{
|
||||
@ -131,7 +131,7 @@ class Controller {
|
||||
*
|
||||
* @param HtmlView $view
|
||||
* @param string $template
|
||||
* @param array|object $data
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function render_full_page($view, $template, array $data)
|
||||
@ -145,10 +145,10 @@ class Controller {
|
||||
* Output a template to HTML, using the provided data
|
||||
*
|
||||
* @param string $template
|
||||
* @param array|object $data
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function outputHTML($template, $data = [])
|
||||
public function outputHTML($template, array $data = [])
|
||||
{
|
||||
$view = new HtmlView($this->container);
|
||||
$this->render_full_page($view, $template, $data);
|
||||
|
@ -34,20 +34,6 @@ class Anime extends BaseController {
|
||||
*/
|
||||
protected $base_data;
|
||||
|
||||
/**
|
||||
* Route mapping for main navigation
|
||||
* @var array $nav_routes
|
||||
*/
|
||||
private $nav_routes = [
|
||||
'Watching' => '/anime/watching{/view}',
|
||||
'Plan to Watch' => '/anime/plan_to_watch{/view}',
|
||||
'On Hold' => '/anime/on_hold{/view}',
|
||||
'Dropped' => '/anime/dropped{/view}',
|
||||
'Completed' => '/anime/completed{/view}',
|
||||
'Collection' => '/collection/view{/view}',
|
||||
'All' => '/anime/all{/view}'
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -65,10 +51,10 @@ class Anime extends BaseController {
|
||||
$this->model = new AnimeModel($container);
|
||||
$this->collection_model = new AnimeCollectionModel($container);
|
||||
$this->base_data = array_merge($this->base_data, [
|
||||
'menu_name' => 'anime_list',
|
||||
'message' => '',
|
||||
'url_type' => 'anime',
|
||||
'other_type' => 'manga',
|
||||
'nav_routes' => $this->nav_routes,
|
||||
'config' => $this->config,
|
||||
]);
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ class Collection extends BaseController {
|
||||
|
||||
/**
|
||||
* The anime collection model
|
||||
* @var object $collection_model
|
||||
* @var object $anime_collection_model
|
||||
*/
|
||||
private $collection_model;
|
||||
private $anime_collection_model;
|
||||
|
||||
/**
|
||||
* Data to ve sent to all routes in this controller
|
||||
@ -35,20 +35,6 @@ class Collection extends BaseController {
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* Route mapping for main navigation
|
||||
* @var array $nav_routes
|
||||
*/
|
||||
private $nav_routes = [
|
||||
'Watching' => '/anime/watching{/view}',
|
||||
'Plan to Watch' => '/anime/plan_to_watch{/view}',
|
||||
'On Hold' => '/anime/on_hold{/view}',
|
||||
'Dropped' => '/anime/dropped{/view}',
|
||||
'Completed' => '/anime/completed{/view}',
|
||||
'Collection' => '/collection/view{/view}',
|
||||
'All' => '/anime/all{/view}'
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -58,18 +44,13 @@ class Collection extends BaseController {
|
||||
{
|
||||
parent::__construct($container);
|
||||
|
||||
if ($this->config->get('show_anime_collection') === FALSE)
|
||||
{
|
||||
unset($this->nav_routes['Collection']);
|
||||
}
|
||||
|
||||
$this->urlGenerator = $container->get('url-generator');
|
||||
$this->collection_model = new AnimeCollectionModel($container);
|
||||
$this->anime_anime_collection_model = new AnimeCollectionModel($container);
|
||||
$this->base_data = array_merge($this->base_data, [
|
||||
'menu_name' => 'collection',
|
||||
'message' => '',
|
||||
'url_type' => 'anime',
|
||||
'other_type' => 'manga',
|
||||
'nav_routes' => $this->nav_routes,
|
||||
'config' => $this->config,
|
||||
]);
|
||||
}
|
||||
@ -98,12 +79,12 @@ class Collection extends BaseController {
|
||||
'list' => 'list'
|
||||
];
|
||||
|
||||
$data = $this->collection_model->get_collection();
|
||||
$data = $this->anime_collection_model->get_collection();
|
||||
|
||||
$this->outputHTML('collection/' . $view_map[$view], [
|
||||
'title' => $this->config->get('whose_list') . "'s Anime Collection",
|
||||
'sections' => $data,
|
||||
'genres' => $this->collection_model->get_genre_list()
|
||||
'genres' => $this->anime_collection_model->get_genre_list()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -121,8 +102,8 @@ class Collection extends BaseController {
|
||||
'action' => $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) : []
|
||||
'media_items' => $this->anime_collection_model->get_media_type_list(),
|
||||
'item' => ($action === "Edit") ? $this->anime_collection_model->get($id) : []
|
||||
]);
|
||||
}
|
||||
|
||||
@ -139,7 +120,7 @@ class Collection extends BaseController {
|
||||
$this->redirect("collection/view", 303, "anime");
|
||||
}
|
||||
|
||||
$this->collection_model->update($data);
|
||||
$this->anime_collection_model->update($data);
|
||||
|
||||
$this->redirect("collection/view", 303, "anime");
|
||||
}
|
||||
@ -157,7 +138,7 @@ class Collection extends BaseController {
|
||||
$this->redirect("collection/view", 303, "anime");
|
||||
}
|
||||
|
||||
$this->collection_model->add($data);
|
||||
$this->anime_collection_model->add($data);
|
||||
|
||||
$this->redirect("collection/view", 303, "anime");
|
||||
}
|
||||
|
@ -26,20 +26,6 @@ class Manga extends Controller {
|
||||
*/
|
||||
protected $base_data;
|
||||
|
||||
|
||||
/**
|
||||
* Route mapping for main navigation
|
||||
* @var array $nav_routes
|
||||
*/
|
||||
private $nav_routes = [
|
||||
'Reading' => '/manga/reading{/view}',
|
||||
'Plan to Read' => '/manga/plan_to_read{/view}',
|
||||
'On Hold' => '/manga/on_hold{/view}',
|
||||
'Dropped' => '/manga/dropped{/view}',
|
||||
'Completed' => '/manga/completed{/view}',
|
||||
'All' => '/manga/all{/view}'
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -51,10 +37,10 @@ class Manga extends Controller {
|
||||
$config = $container->get('config');
|
||||
$this->model = new MangaModel($container);
|
||||
$this->base_data = array_merge($this->base_data, [
|
||||
'menu_name' => 'manga_list',
|
||||
'config' => $this->config,
|
||||
'url_type' => 'manga',
|
||||
'other_type' => 'anime',
|
||||
'nav_routes' => $this->nav_routes
|
||||
'other_type' => 'anime'
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ use Aviat\Ion\Di\ContainerInterface;
|
||||
/**
|
||||
* Basic routing/ dispatch
|
||||
*/
|
||||
class Router extends RoutingBase {
|
||||
class Dispatcher extends RoutingBase {
|
||||
|
||||
/**
|
||||
* The route-matching object
|
||||
@ -109,7 +109,7 @@ class Router extends RoutingBase {
|
||||
* @param object $route
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch($route = NULL)
|
||||
public function __invoke($route = NULL)
|
||||
{
|
||||
$error_handler = $this->container->get('error-handler');
|
||||
|
||||
@ -264,4 +264,4 @@ class Router extends RoutingBase {
|
||||
return $output_routes;
|
||||
}
|
||||
}
|
||||
// End of Router.php
|
||||
// End of Dispatcher.php
|
@ -2,11 +2,9 @@
|
||||
|
||||
namespace Aviat\AnimeClient\Helper;
|
||||
|
||||
use Aura\Html\Helper\AbstractHelper;
|
||||
|
||||
use Aviat\AnimeClient\MenuGenerator;
|
||||
|
||||
class Menu extends AbstractHelper {
|
||||
class Menu {
|
||||
|
||||
use \Aviat\Ion\Di\ContainerAware;
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Aviat\AnimeClient\Helper;
|
||||
|
||||
use Aura\Html\Helper\AbstractHelper;
|
||||
use Aviat\AnimeClient\UrlGenerator;
|
||||
|
||||
class UrlHelper extends AbstractHelper {
|
||||
|
||||
/**
|
||||
* Helper entry point
|
||||
*
|
||||
* @return UrlHelper
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -7,9 +7,8 @@ use Aviat\Ion\Di\ContainerInterface;
|
||||
/**
|
||||
* Helper object to manage menu creation and selection
|
||||
*/
|
||||
class MenuGenerator extends RoutingBase {
|
||||
class MenuGenerator extends UrlGenerator {
|
||||
|
||||
use \Aviat\Ion\Di\ContainerAware;
|
||||
use \Aviat\Ion\StringWrapper;
|
||||
use \Aviat\Ion\ArrayWrapper;
|
||||
|
||||
@ -27,6 +26,13 @@ class MenuGenerator extends RoutingBase {
|
||||
*/
|
||||
protected $menus;
|
||||
|
||||
/**
|
||||
* Request object
|
||||
*
|
||||
* @var Aura\Web\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Create menu generator
|
||||
*
|
||||
@ -37,6 +43,7 @@ class MenuGenerator extends RoutingBase {
|
||||
parent::__construct($container);
|
||||
$this->menus = $this->config->get('menus');
|
||||
$this->helper = $container->get('html-helper');
|
||||
$this->request = $container->get('request');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,16 +56,11 @@ class MenuGenerator extends RoutingBase {
|
||||
// Note: Children menus have urls based on the
|
||||
// current url path
|
||||
/*
|
||||
$parsed = [
|
||||
'menu_name' => [
|
||||
'items' => [
|
||||
'title' => 'full_url_path',
|
||||
],
|
||||
'children' => [
|
||||
'title' => 'full_url_path'
|
||||
]
|
||||
]
|
||||
]
|
||||
parsed = {
|
||||
menu_name: {
|
||||
title: 'full_url_path'
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
$parsed = [];
|
||||
@ -68,14 +70,8 @@ class MenuGenerator extends RoutingBase {
|
||||
$parsed[$name] = [];
|
||||
foreach ($menu['items'] as $path_name => $partial_path)
|
||||
{
|
||||
$title = $this->string($path_name)->humanize()->titleize();
|
||||
$parsed[$name]['items'][$title] = $this->string($menu['route_prefix'])->append($partial_path);
|
||||
}
|
||||
|
||||
// @TODO: Handle child menu(s)
|
||||
if (count($menu['children']) > 0)
|
||||
{
|
||||
|
||||
$title = (string) $this->string($path_name)->humanize()->titleize();
|
||||
$parsed[$name][$title] = (string) $this->string($menu['route_prefix'])->append($partial_path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,16 +87,29 @@ class MenuGenerator extends RoutingBase {
|
||||
public function generate($menu)
|
||||
{
|
||||
$parsed_config = $this->parse_config();
|
||||
|
||||
// Bail out early on invalid menu
|
||||
if ( ! $this->arr($parsed_config)->has_key($menu))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$menu_config = $parsed_config[$menu];
|
||||
|
||||
// Array of list items to add to the main menu
|
||||
$main_menu = [];
|
||||
foreach($menu_config as $title => $path)
|
||||
{
|
||||
$selected = $this->string($path)->contains($this->path());
|
||||
$link = $this->helper->a($this->url($path), $title);
|
||||
|
||||
$attrs = ($selected)
|
||||
? ['class' => 'selected']
|
||||
: [];
|
||||
|
||||
// Start the menu list
|
||||
$helper->ul();
|
||||
|
||||
$this->helper->ul()->rawItem($link, $attrs);
|
||||
}
|
||||
|
||||
// Create the menu html
|
||||
return $this->helper->ul();
|
||||
}
|
||||
}
|
||||
// End of MenuGenerator.php
|
@ -11,6 +11,9 @@ use Aviat\Ion\Di\ContainerInterface;
|
||||
* Base for routing/url classes
|
||||
*/
|
||||
class RoutingBase {
|
||||
|
||||
use \Aviat\Ion\StringWrapper;
|
||||
|
||||
/**
|
||||
* Injection Container
|
||||
* @var Container $container
|
||||
@ -56,5 +59,58 @@ class RoutingBase {
|
||||
return $routing_config[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current url path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function path()
|
||||
{
|
||||
$request = $this->container->get('request');
|
||||
$path = $request->server->get('REQUEST_URI');
|
||||
$cleaned_path = $this->string($path)
|
||||
->trim()
|
||||
->trimRight('/')
|
||||
->ensureLeft('/');
|
||||
|
||||
return (string) $cleaned_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url segments
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function segments()
|
||||
{
|
||||
$path = $this->path();
|
||||
$segments = explode('/', $path);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a segment of the current url
|
||||
*
|
||||
* @param int $num
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_segment($num)
|
||||
{
|
||||
$segments = $this->segments();
|
||||
return (array_key_exists($num, $segments)) ? $segments[$num] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the last url segment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function last_segment()
|
||||
{
|
||||
$segments = $this->segments();
|
||||
return end($segments);
|
||||
}
|
||||
}
|
||||
// End of RoutingBase.php
|
@ -28,7 +28,6 @@ class ArrayType {
|
||||
'filter' => 'array_filter',
|
||||
'flip' => 'array_flip',
|
||||
'intersect' => 'array_intersect',
|
||||
'has_key' => 'array_key_exists',
|
||||
'keys' => 'array_keys',
|
||||
'merge' => 'array_merge',
|
||||
'pad' => 'array_pad',
|
||||
@ -90,6 +89,16 @@ class ArrayType {
|
||||
return $this->arr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the passed key exist in the current array?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_key($key)
|
||||
{
|
||||
return array_key_exists($key, $this->arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill an array with the specified value
|
||||
|
@ -28,18 +28,6 @@ function is_not_selected($a, $b)
|
||||
return ($a !== $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last segment of the current url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function last_segment()
|
||||
{
|
||||
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$segments = explode('/', $path);
|
||||
return end($segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to show the sub-menu
|
||||
*
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?php
|
||||
|
||||
use Aviat\Ion\Di\Container;
|
||||
use Aviat\AnimeClient\Router;
|
||||
use Aviat\AnimeClient\Dispatcher;
|
||||
use Aviat\AnimeClient\Config;
|
||||
use Aviat\AnimeClient\UrlGenerator;
|
||||
use Aura\Web\WebFactory;
|
||||
use Aura\Router\RouterFactory;
|
||||
|
||||
class RouterTest extends AnimeClient_TestCase {
|
||||
class DispatcherTest extends AnimeClient_TestCase {
|
||||
|
||||
protected $container;
|
||||
protected $router;
|
||||
@ -33,16 +33,24 @@ class RouterTest extends AnimeClient_TestCase {
|
||||
'_FILES' => []
|
||||
]);
|
||||
|
||||
$old_config = $this->container->get('config');
|
||||
|
||||
// Add the appropriate objects to the container
|
||||
$this->container = new Container([
|
||||
'config' => new Config($config),
|
||||
'config' => $old_config,
|
||||
'request' => $web_factory->newRequest(),
|
||||
'response' => $web_factory->newResponse(),
|
||||
'aura-router' => $router_factory->newInstance(),
|
||||
'error-handler' => new MockErrorHandler()
|
||||
]);
|
||||
|
||||
$this->router = new Router($this->container);
|
||||
if ( ! empty($config))
|
||||
{
|
||||
$config = new Config($config);
|
||||
$this->container->set('config', $config);
|
||||
}
|
||||
|
||||
$this->router = new Dispatcher($this->container);
|
||||
$this->config = $this->container->get('config');
|
||||
$this->urlGenerator = new UrlGenerator($this->container);
|
||||
$this->container->set('url-generator', $this->urlGenerator);
|
59
tests/AnimeClient/MenuGeneratorTest.php
Normal file
59
tests/AnimeClient/MenuGeneratorTest.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use Aura\Html\HelperLocatorFactory;
|
||||
|
||||
use Aviat\Ion\Friend;
|
||||
use Aviat\Ion\Di\Container;
|
||||
use Aviat\AnimeClient\Helper;
|
||||
use Aviat\AnimeClient\Config;
|
||||
use Aviat\AnimeClient\MenuGenerator;
|
||||
|
||||
class MenuGeneratorTest extends AnimeClient_TestCase {
|
||||
|
||||
protected $generator;
|
||||
protected $friend;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$config = $this->container->get('config');
|
||||
$config->set('menus', [
|
||||
'anime_list' => [
|
||||
'route_prefix' => '/anime',
|
||||
'items' => [
|
||||
'watching' => '/watching',
|
||||
'plan_to_watch' => '/plan_to_watch',
|
||||
'on_hold' => '/on_hold',
|
||||
'dropped' => '/dropped',
|
||||
'completed' => '/completed',
|
||||
'all' => '/all'
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->generator = new MenuGenerator($this->container);
|
||||
|
||||
}
|
||||
|
||||
public function testSanity()
|
||||
{
|
||||
$generator = new MenuGenerator($this->container);
|
||||
$this->assertInstanceOf('Aviat\AnimeClient\MenuGenerator', $generator);
|
||||
}
|
||||
|
||||
public function testParseConfig()
|
||||
{
|
||||
$friend = new Friend($this->generator);
|
||||
$expected = [
|
||||
'anime_list' => [
|
||||
'Watching' => '/anime/watching',
|
||||
'Plan To Watch' => '/anime/plan_to_watch',
|
||||
'On Hold' => '/anime/on_hold',
|
||||
'Dropped' => '/anime/dropped',
|
||||
'Completed' => '/anime/completed',
|
||||
'All' => '/anime/all'
|
||||
]
|
||||
];
|
||||
$this->assertEquals($expected, $friend->parse_config());
|
||||
}
|
||||
}
|
51
tests/AnimeClient/RoutingBaseTest.php
Normal file
51
tests/AnimeClient/RoutingBaseTest.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Aviat\AnimeClient\RoutingBase;
|
||||
|
||||
class RoutingBaseTest extends AnimeClient_TestCase {
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->routingBase = new RoutingBase($this->container);
|
||||
}
|
||||
|
||||
public function dataSegments()
|
||||
{
|
||||
return [
|
||||
'empty_segment' => [
|
||||
'request_uri' => ' // ',
|
||||
'path' => '/',
|
||||
'segments' => ['', ''],
|
||||
'last_segment' => NULL
|
||||
],
|
||||
'three_segments' => [
|
||||
'request_uri' => '/anime/watching/list ',
|
||||
'path' => '/anime/watching/list',
|
||||
'segments' => ['', 'anime', 'watching', 'list'],
|
||||
'last_segment' => 'list'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataSegments
|
||||
*/
|
||||
public function testSegments($request_uri, $path, $segments, $last_segment)
|
||||
{
|
||||
$this->setSuperGlobals([
|
||||
'_SERVER' => [
|
||||
'REQUEST_URI' => $request_uri
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($path, $this->routingBase->path(), "Path is invalid");
|
||||
$this->assertEquals($segments, $this->routingBase->segments(), "Segments array is invalid");
|
||||
$this->assertEquals($last_segment, $this->routingBase->last_segment(), "Last segment is invalid");
|
||||
|
||||
foreach($segments as $i => $value)
|
||||
{
|
||||
$this->assertEquals($value, $this->routingBase->get_segment($i), "Segment {$i} is invalid");
|
||||
}
|
||||
}
|
||||
}
|
@ -2,54 +2,12 @@
|
||||
/**
|
||||
* Global setup for unit tests
|
||||
*/
|
||||
use Aura\Web\WebFactory;
|
||||
|
||||
use Aviat\AnimeClient\Config;
|
||||
use Aviat\Ion\Di\Container;
|
||||
use Aviat\AnimeClient\UrlGenerator;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Mock the default error handler
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class MockErrorHandler {
|
||||
public function addDataTable($name, Array $values) {}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Define a base testcase class
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Base class for TestCases
|
||||
*/
|
||||
class AnimeClient_TestCase extends PHPUnit_Framework_TestCase {
|
||||
protected $container;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$config = new Config([
|
||||
'asset_path' => '//localhost/assets/',
|
||||
'databaase' => [],
|
||||
'routes' => [
|
||||
'common' => [],
|
||||
'anime' => [],
|
||||
'manga' => []
|
||||
]
|
||||
]);
|
||||
|
||||
$container = new Container([
|
||||
'config' => $config,
|
||||
'error-handler' => new MockErrorHandler()
|
||||
]);
|
||||
|
||||
$container->set('url-generator', new UrlGenerator($container));
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Autoloaders
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -72,7 +30,7 @@ define('CONF_DIR', _dir(APP_DIR, 'config'));
|
||||
define('SRC_DIR', _dir(ROOT_DIR, 'src'));
|
||||
define('BASE_DIR', _dir(SRC_DIR, 'Base'));
|
||||
require _dir(ROOT_DIR, '/vendor/autoload.php');
|
||||
require _dir(SRC_DIR, 'functions.php');
|
||||
require _dir(SRC_DIR, '/functions.php');
|
||||
|
||||
/**
|
||||
* Set up autoloaders
|
||||
@ -95,4 +53,71 @@ spl_autoload_register(function ($class) {
|
||||
$_SESSION = [];
|
||||
$_COOKIE = [];
|
||||
|
||||
// End of bootstrap.php
|
||||
// -----------------------------------------------------------------------------
|
||||
// Mock the default error handler
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class MockErrorHandler {
|
||||
public function addDataTable($name, array $values=[]) {}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Define a base testcase class
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Base class for TestCases
|
||||
*/
|
||||
class AnimeClient_TestCase extends PHPUnit_Framework_TestCase {
|
||||
protected $container;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$config_array = [
|
||||
'asset_path' => '//localhost/assets/',
|
||||
'databaase' => [],
|
||||
'routing' => [
|
||||
|
||||
],
|
||||
'routes' => [
|
||||
'convention' => [
|
||||
'default_controller' => '',
|
||||
'default_method' => '',
|
||||
],
|
||||
'common' => [],
|
||||
'anime' => [],
|
||||
'manga' => []
|
||||
]
|
||||
];
|
||||
|
||||
$di = require _dir(APP_DIR, 'bootstrap.php');
|
||||
$container = $di($config_array);
|
||||
$container->set('error-handler', new MockErrorHandler());
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set arbitrary superglobal values for testing purposes
|
||||
*
|
||||
* @param array $supers
|
||||
* @return void
|
||||
*/
|
||||
public function setSuperGlobals($supers = [])
|
||||
{
|
||||
$default = [
|
||||
'_GET' => $_GET,
|
||||
'_POST' => $_POST,
|
||||
'_COOKIE' => $_COOKIE,
|
||||
'_SERVER' => $_SERVER,
|
||||
'_FILES' => $_FILES
|
||||
];
|
||||
$web_factory = new WebFactory(array_merge($default,$supers));
|
||||
$this->container->set('request', $web_factory->newRequest());
|
||||
$this->container->set('response', $web_factory->newResponse());
|
||||
}
|
||||
}
|
||||
|
||||
// End of bootstrap.php
|
Loading…
Reference in New Issue
Block a user