Bit of a style update

This commit is contained in:
Timothy Warren 2015-06-17 08:50:01 -04:00
parent 38a2b470c5
commit 401c21e98f
13 changed files with 195 additions and 74 deletions

View File

@ -44,17 +44,5 @@ class BaseApiModel extends BaseModel {
] ]
]); ]);
} }
/**
* Get the full url path, since the base_url in Guzzle doesn't work correctly
*
* @param string $path
* @return string
*/
protected function _url($path)
{
return "{$this->base_url}{$path}";
}
} }
// End of BaseApiModel.php // End of BaseApiModel.php

View File

@ -97,5 +97,16 @@ class BaseController {
header("Location: {$url}"); header("Location: {$url}");
die(); die();
} }
/**
* Clear the api session
*
* @return void
*/
public function logout()
{
session_destroy();
$this->redirect('');
}
} }
// End of BaseController.php // End of BaseController.php

View File

@ -90,8 +90,7 @@ class Router {
} }
else else
{ {
$controller_name = $route->params['controller']; list($controller_name, $action_method) = $route->params['action'];
$action_method = $route->params['action'];
$params = (isset($route->params['params'])) ? $route->params['params'] : []; $params = (isset($route->params['params'])) ? $route->params['params'] : [];
if ( ! empty($route->tokens)) if ( ! empty($route->tokens))
@ -133,7 +132,7 @@ class Router {
$routes = $this->config->routes; $routes = $this->config->routes;
// Add routes by the configuration file // Add routes for the current controller
foreach($routes[$route_type] as $name => $route) foreach($routes[$route_type] as $name => $route)
{ {
$path = $route['path']; $path = $route['path'];
@ -153,6 +152,21 @@ class Router {
->addTokens($tokens); ->addTokens($tokens);
} }
} }
// Add routes by required http verb
foreach(['get', 'post'] as $verb)
{
$add = "add" . ucfirst($verb);
foreach($routes[$verb] as $name => $route)
{
$path = $route['path'];
unset($route['path']);
$this->router->$add($name, $path)
->addValues($route);
}
}
} }
} }
// End of Router.php // End of Router.php

View File

@ -4,8 +4,7 @@ return [
'anime' => [ 'anime' => [
'index' => [ 'index' => [
'path' => '/', 'path' => '/',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'redirect'],
'action' => 'redirect',
'params' => [ 'params' => [
'url' => '', // Determined by config 'url' => '', // Determined by config
'code' => '301' 'code' => '301'
@ -13,8 +12,7 @@ return [
], ],
'all' => [ 'all' => [
'path' => '/all{/view}', 'path' => '/all{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'all', 'type' => 'all',
'title' => WHOSE . " Anime List · All" 'title' => WHOSE . " Anime List · All"
@ -25,8 +23,7 @@ return [
], ],
'watching' => [ 'watching' => [
'path' => '/watching{/view}', 'path' => '/watching{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'currently-watching', 'type' => 'currently-watching',
'title' => WHOSE . " Anime List · Watching" 'title' => WHOSE . " Anime List · Watching"
@ -37,8 +34,7 @@ return [
], ],
'plan_to_watch' => [ 'plan_to_watch' => [
'path' => '/plan_to_watch{/view}', 'path' => '/plan_to_watch{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'plan-to-watch', 'type' => 'plan-to-watch',
'title' => WHOSE . " Anime List · Plan to Watch" 'title' => WHOSE . " Anime List · Plan to Watch"
@ -49,8 +45,7 @@ return [
], ],
'on_hold' => [ 'on_hold' => [
'path' => '/on_hold{/view}', 'path' => '/on_hold{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'on-hold', 'type' => 'on-hold',
'title' => WHOSE . " Anime List · On Hold" 'title' => WHOSE . " Anime List · On Hold"
@ -61,8 +56,7 @@ return [
], ],
'dropped' => [ 'dropped' => [
'path' => '/dropped{/view}', 'path' => '/dropped{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'dropped', 'type' => 'dropped',
'title' => WHOSE . " Anime List · Dropped" 'title' => WHOSE . " Anime List · Dropped"
@ -73,8 +67,7 @@ return [
], ],
'completed' => [ 'completed' => [
'path' => '/completed{/view}', 'path' => '/completed{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'anime_list'],
'action' => 'anime_list',
'params' => [ 'params' => [
'type' => 'completed', 'type' => 'completed',
'title' => WHOSE . " Anime List · Completed" 'title' => WHOSE . " Anime List · Completed"
@ -85,8 +78,7 @@ return [
], ],
'collection' => [ 'collection' => [
'path' => '/collection{/view}', 'path' => '/collection{/view}',
'controller' => 'AnimeController', 'action' => ['AnimeController', 'collection'],
'action' => 'collection',
'params' => [], 'params' => [],
'tokens' => [ 'tokens' => [
'view' => '[a-z_]+' 'view' => '[a-z_]+'
@ -96,8 +88,7 @@ return [
'manga' => [ 'manga' => [
'index' => [ 'index' => [
'path' => '/', 'path' => '/',
'controller' => 'MangaController', 'action' => ['MangaController', 'redirect'],
'action' => 'redirect',
'params' => [ 'params' => [
'url' => '', // Determined by config 'url' => '', // Determined by config
'code' => '301', 'code' => '301',
@ -106,8 +97,7 @@ return [
], ],
'all' => [ 'all' => [
'path' => '/all{/view}', 'path' => '/all{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'all', 'type' => 'all',
'title' => WHOSE . " Manga List · All" 'title' => WHOSE . " Manga List · All"
@ -118,8 +108,7 @@ return [
], ],
'reading' => [ 'reading' => [
'path' => '/reading{/view}', 'path' => '/reading{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'Reading', 'type' => 'Reading',
'title' => WHOSE . " Manga List · Reading" 'title' => WHOSE . " Manga List · Reading"
@ -130,8 +119,7 @@ return [
], ],
'plan_to_read' => [ 'plan_to_read' => [
'path' => '/plan_to_read{/view}', 'path' => '/plan_to_read{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'Plan to Read', 'type' => 'Plan to Read',
'title' => WHOSE . " Manga List · Plan to Read" 'title' => WHOSE . " Manga List · Plan to Read"
@ -142,8 +130,7 @@ return [
], ],
'on_hold' => [ 'on_hold' => [
'path' => '/on_hold{/view}', 'path' => '/on_hold{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'On Hold', 'type' => 'On Hold',
'title' => WHOSE . " Manga List · On Hold" 'title' => WHOSE . " Manga List · On Hold"
@ -154,8 +141,7 @@ return [
], ],
'dropped' => [ 'dropped' => [
'path' => '/dropped{/view}', 'path' => '/dropped{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'Dropped', 'type' => 'Dropped',
'title' => WHOSE . " Manga List · Dropped" 'title' => WHOSE . " Manga List · Dropped"
@ -166,8 +152,7 @@ return [
], ],
'completed' => [ 'completed' => [
'path' => '/completed{/view}', 'path' => '/completed{/view}',
'controller' => 'MangaController', 'action' => ['MangaController', 'manga_list'],
'action' => 'manga_list',
'params' => [ 'params' => [
'type' => 'Completed', 'type' => 'Completed',
'title' => WHOSE . " Manga List · Completed" 'title' => WHOSE . " Manga List · Completed"
@ -176,5 +161,22 @@ return [
'view' => '[a-z_]+' 'view' => '[a-z_]+'
] ]
], ],
],
// These routes are limited to a specific HTTP verb
'get' => [
'login_form' => [
'path' => '/login',
'action' => ['AnimeController', 'login'],
],
'logout' => [
'path' => '/logout',
'action' => ['BaseController', 'logout']
]
],
'post' => [
'login_action' => [
'path' => '/login',
'action' => ['AnimeController', 'login_action'],
]
] ]
]; ];

View File

@ -104,5 +104,30 @@ class AnimeController extends BaseController {
'sections' => $data 'sections' => $data
])); ]));
} }
/**
* Show the login form
*
* @return void
*/
public function login()
{
$this->outputHTML('login', array_merge($this->base_data, [
'title' => 'Api login'
]));
}
/**
* Attempt to log in with the api
*
* @return void
*/
public function login_action()
{
if ($this->model->authenticate($this->config->hummingbird_username, $_POST['password']))
{
$this->redirect('');
}
}
} }
// End of AnimeController.php // End of AnimeController.php

View File

@ -11,7 +11,7 @@ class AnimeModel extends BaseApiModel {
* The base url for api requests * The base url for api requests
* @var string $base_url * @var string $base_url
*/ */
protected $base_url = "https://hummingbird.me/api/v1"; protected $base_url = "https://hummingbird.me/api/v1/";
/** /**
* Constructor * Constructor
@ -21,6 +21,31 @@ class AnimeModel extends BaseApiModel {
parent::__construct(); parent::__construct();
} }
/**
* Attempt login via the api
*
* @param string $username
* @param string $password
* @return bool
*/
public function authenticate($username, $password)
{
$result = $this->client->post('users/authenticate', [
'form_params' => [
'username' => $this->config->hummingbird_username,
'password' => $password
]
]);
if ($response->getStatusCode() === 201)
{
$_SESSION['hummingbird_anime_token'] = $response->json();
return TRUE;
}
return FALSE;
}
/** /**
* Get the full set of anime lists * Get the full set of anime lists
* *
@ -111,9 +136,9 @@ class AnimeModel extends BaseApiModel {
$cache_file = "{$this->config->data_cache_path}/anime-{$status}.json"; $cache_file = "{$this->config->data_cache_path}/anime-{$status}.json";
$config = [ $config = [
'query' => [ /*'query' => [
'username' => $this->config->hummingbird_username, 'username' => $this->config->hummingbird_username,
], ],*/
'allow_redirects' => false 'allow_redirects' => false
]; ];
@ -122,7 +147,7 @@ class AnimeModel extends BaseApiModel {
$config['query']['status'] = $status; $config['query']['status'] = $status;
} }
$response = $this->client->get($this->_url('/users/' . $this->config->hummingbird_username . '/library'), $config); $response = $this->client->get("users/{$this->config->hummingbird_username}/library", $config);
$defaultHandler->addDataTable('anime_list_response', (array)$response); $defaultHandler->addDataTable('anime_list_response', (array)$response);
@ -171,7 +196,7 @@ class AnimeModel extends BaseApiModel {
] ]
]; ];
$response = $this->client->get($this->_url("/anime/{$anime_id}"), $config); $response = $this->client->get("anime/{$anime_id}", $config);
return $response->json(); return $response->json();
} }
@ -192,7 +217,7 @@ class AnimeModel extends BaseApiModel {
] ]
]; ];
$response = $this->client->get($this->_url('/search/anime'), $config); $response = $this->client->get('search/anime', $config);
$defaultHandler->addDataTable('anime_search_response', (array)$response); $defaultHandler->addDataTable('anime_search_response', (array)$response);
if ($response->getStatusCode() != 200) if ($response->getStatusCode() != 200)

View File

@ -11,7 +11,7 @@ class MangaModel extends BaseApiModel {
/** /**
* @var string $base_url - The base url for api requests * @var string $base_url - The base url for api requests
*/ */
protected $base_url = "https://hummingbird.me"; protected $base_url = "https://hummingbird.me/";
/** /**
* Constructor * Constructor
@ -72,7 +72,7 @@ class MangaModel extends BaseApiModel {
'allow_redirects' => false 'allow_redirects' => false
]; ];
$response = $this->client->get($this->_url('/manga_library_entries'), $config); $response = $this->client->get('manga_library_entries', $config);
$defaultHandler->addDataTable('response', (array)$response); $defaultHandler->addDataTable('response', (array)$response);

View File

@ -11,13 +11,14 @@
<?= $item['title'] ?> <?= $item['title'] ?>
<?= ($item['alternate_title'] != "") ? "<br />({$item['alternate_title']})" : ""; ?> <?= ($item['alternate_title'] != "") ? "<br />({$item['alternate_title']})" : ""; ?>
</div> </div>
<div class="media_metadata"> <div class="table">
<div class="row">
<div class="completion">Episodes: <?= $item['episode_count'] ?></div> <div class="completion">Episodes: <?= $item['episode_count'] ?></div>
</div>
<div class="medium_metadata">
<div class="media_type"><?= $item['show_type'] ?></div> <div class="media_type"><?= $item['show_type'] ?></div>
<div class="age_rating"><?= $item['age_rating'] ?></div> <div class="age_rating"><?= $item['age_rating'] ?></div>
</div> </div>
</div>
</article> </article>
</a> </a>
<?php endforeach ?> <?php endforeach ?>

View File

View File

@ -6,19 +6,21 @@
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<a href="<?= $item['anime']['url'] ?>"> <a href="<?= $item['anime']['url'] ?>">
<article class="media" id="a-<?= $item['anime']['id'] ?>"> <article class="media" id="a-<?= $item['anime']['id'] ?>">
<img class="round_all" src="<?= $item['anime']['cover_image'] ?>" /> <img src="<?= $item['anime']['cover_image'] ?>" />
<div class="round_all name"> <div class="name">
<?= $item['anime']['title'] ?> <?= $item['anime']['title'] ?>
<?= ($item['anime']['alternate_title'] != "") ? "<br />({$item['anime']['alternate_title']})" : ""; ?> <?= ($item['anime']['alternate_title'] != "") ? "<br />({$item['anime']['alternate_title']})" : ""; ?>
</div> </div>
<div class="media_metadata"> <div class="table">
<div class="round_top airing_status"><?= $item['anime']['status'] ?></div> <div class="row">
<div class="user_rating"><?= (int)($item['rating']['value'] * 2) ?> / 10</div> <div class="user_rating">Rating: <?= (int)($item['rating']['value'] * 2) ?> / 10</div>
<div class="round_bottom completion">Episodes: <?= $item['episodes_watched'] ?> / <?= $item['anime']['episode_count'] ?></div> <div class="completion">Episodes: <?= $item['episodes_watched'] ?>&nbsp;/&nbsp;<?= ($item['anime']['episode_count'] != 0) ? $item['anime']['episode_count'] : "-" ?></div>
</div>
<div class="row">
<div class="media_type"><?= $item['anime']['show_type'] ?></div>
<div class="airing_status"><?= $item['anime']['status'] ?></div>
<div class="age_rating"><?= $item['anime']['age_rating'] ?></div>
</div> </div>
<div class="medium_metadata">
<div class="round_top media_type"><?= $item['anime']['show_type'] ?></div>
<div class="round_bottom age_rating"><?= $item['anime']['age_rating'] ?></div>
</div> </div>
</article> </article>
</a> </a>

View File

@ -0,0 +1,16 @@
<main>
<aside>
<form method="post" action="<?= full_url('/login', $url_type) ?>">
<dl>
<dt><label for="username">Username: </label></dt>
<dd><input type="text" id="username" name="username" required="required" /></dd>
<dt><label for="password">Password: </label></dt>
<dd><input type="password" id="password" name="password" required="required" /></dd>
<dt>&nbsp;</dt>
<dd><input type="submit" value="Login" /></dd>
</dl>
</form>
</aside>
</main>

View File

@ -12,7 +12,7 @@
<?= (isset($item['manga']['english_title'])) ? "<br />({$item['manga']['english_title']})" : ""; ?> <?= (isset($item['manga']['english_title'])) ? "<br />({$item['manga']['english_title']})" : ""; ?>
</div> </div>
<div class="media_metadata"> <div class="media_metadata">
<div class="user_rating"><?= ($item['rating'] > 0) ? (int)($item['rating'] * 2) : '-' ?> / 10</div> <div class="user_rating">Rating: <?= ($item['rating'] > 0) ? (int)($item['rating'] * 2) : '-' ?> / 10</div>
<div class="completion"> <div class="completion">
Chapters: <?= $item['chapters_read'] ?> / <?= ($item['manga']['chapter_count'] > 0) ? $item['manga']['chapter_count'] : "-" ?><?php /*<br /> Chapters: <?= $item['chapters_read'] ?> / <?= ($item['manga']['chapter_count'] > 0) ? $item['manga']['chapter_count'] : "-" ?><?php /*<br />
Volumes: <?= $item['volumes_read'] ?> / <?= ($item['manga']['volume_count'] > 0) ? $item['manga']['volume_count'] : "-" ?>*/ ?> Volumes: <?= $item['volumes_read'] ?> / <?= ($item['manga']['volume_count'] > 0) ? $item['manga']['volume_count'] : "-" ?>*/ ?>

View File

@ -50,6 +50,8 @@ tbody > tr:nth-child(odd) {
margin:0.25em; margin:0.25em;
} }
.name, .media_type, .airing_status, .user_rating, .completion, .age_rating { .name, .media_type, .airing_status, .user_rating, .completion, .age_rating {
text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.85); text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.85);
background: rgba(0, 0, 0, 0.45); background: rgba(0, 0, 0, 0.45);
@ -81,9 +83,10 @@ tbody > tr:nth-child(odd) {
.media:hover > .name, .media:hover > .name,
.media:hover > .media_metadata > div, .media:hover > .media_metadata > div,
.media:hover > .medium_metadata > div .media:hover > .medium_metadata > div,
.media:hover > .table .row
{ {
background:rgba(0,0,0,0.9); background:rgba(0,0,0,0.75);
} }
.media > .name > a { .media > .name > a {
@ -93,8 +96,42 @@ tbody > tr:nth-child(odd) {
text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.85); text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.85);
} }
.user_rating::before {
content: "Rating: "; /* -----------------------------------------------------------------------------
Anime-list-specific styles
------------------------------------------------------------------------------*/
.anime .name {width:100%;}
.anime .media_type,
.anime .airing_status,
.anime .user_rating,
.anime .completion,
.anime .age_rating {
background: none;
text-align:center;
}
.anime .table {
position:absolute;
bottom:0;
left:0;
width:100%;
}
.anime .row {
width:100%;
background: rgba(0, 0, 0, 0.45);
display:table;
text-align:center;
padding:0 inherit;
}
.anime .row > div {
font-size:0.8em;
display:table-cell;
text-align:center;
vertical-align:middle;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------