Merge branch 'develop' into 'master'

Develop

See merge request !14
This commit is contained in:
Timothy Warren 2017-02-28 16:58:53 -05:00
commit e0e1b59777
126 changed files with 3434 additions and 1196 deletions

View File

@ -1,38 +1,21 @@
# Composer stores all downloaded packages in the vendor/ directory.
# Do not use the following if the vendor/ directory is commited to
# your git repository.
cache:
paths:
- vendor/
services:
- redis:latest
test:7: test:7:
stage: test
before_script: before_script:
- bash build/docker_install.sh > /dev/null - sh build/docker_install.sh > /dev/null
- apk add --no-cache php7-phpdbg
- curl -sS https://getcomposer.org/installer | php - curl -sS https://getcomposer.org/installer | php
- php composer.phar install --no-dev - php composer.phar install --ignore-platform-reqs
image: php:7 image: php:7-alpine
script: script:
- phpunit -c build --coverage-text --colors=never - phpdbg -qrr -- ./vendor/bin/phpunit --coverage-text --colors=never
test:7.1:
before_script:
- bash build/docker_install.sh > /dev/null
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --no-dev
image: php:7.1
script:
- phpunit -c build --coverage-text --colors=never
test:hhvm: test:7.1:
allow_failure: true stage: test
before_script: before_script:
- /usr/local/bin/composer self-update - sh build/docker_install.sh > /dev/null
- curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar - apk add --no-cache php7.1-phpdbg
- chmod +x /usr/local/bin/phpunit - curl -sS https://getcomposer.org/installer | php
- composer install --no-dev --ignore-platform-reqs - php composer.phar install --ignore-platform-reqs
image: 51systems/docker-gitlab-ci-runner-hhvm image: php:7.1-alpine
script: script:
- hhvm -d hhvm.php7.all=true /usr/local/bin/phpunit -c build --coverage-text --colors=never - phpdbg -qrr -- ./vendor/bin/phpunit --coverage-text --colors=never

View File

@ -11,10 +11,7 @@ php:
script: script:
- mkdir -p build/logs - mkdir -p build/logs
- vendor/bin/phpunit -c build - phpdbg -qrr -- vendor/bin/phpunit -c build
services:
- redis
after_script: after_script:
- CODECLIMATE_REPO_TOKEN=2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 vendor/bin/test-reporter - CODECLIMATE_REPO_TOKEN=2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 vendor/bin/test-reporter

View File

@ -58,40 +58,6 @@ or
### Server Setup ### Server Setup
#### Caching See the [wiki](https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient/wikis/home)
for more in-depth information
Update `app/config/cache.toml` based on the instructions [here](https://git.timshomepage.net/timw4mail/banker/blob/master/README.md).
#### nginx
Basic nginx setup
```nginx
server {
location / {
try_files $uri $uri/ /index.php$uri?$args;
}
location ~ ^(.+\.php)($|/) {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_index index.php;
}
location ^~ /vendor {
deny all;
}
}
```
#### Apache
Make sure to have `mod_rewrite` and `AllowOverride All` enabled in order to take
advantage of the included `.htaccess` file. If you don't wish to use an `.htaccess` file,
include the contents of the `.htaccess` file in your Apache configuration.
#### Anime Collection Additional Installation
* Run `php /vendor/bin/phinx migrate -e development` to create the database tables
* For importing anime:
1. Login
2. Use the form to select your media
3. Save & Repeat as needed

View File

@ -1,4 +1,7 @@
<?php <?php declare(strict_types=1);
use Robo\Tasks;
if ( ! function_exists('glob_recursive')) if ( ! function_exists('glob_recursive'))
{ {
// Does not support flag GLOB_BRACE // Does not support flag GLOB_BRACE
@ -20,7 +23,7 @@ if ( ! function_exists('glob_recursive'))
* *
* @see http://robo.li/ * @see http://robo.li/
*/ */
class RoboFile extends \Robo\Tasks { class RoboFile extends Tasks {
/** /**
* Directories used by analysis tools * Directories used by analysis tools
@ -102,10 +105,7 @@ class RoboFile extends \Robo\Tasks {
*/ */
public function coverage() public function coverage()
{ {
$this->taskPhpUnit() $this->_run(['vendor/bin/phpunit -c build']);
->configFile('build/phpunit.xml')
->printed(true)
->run();
} }
/** /**
@ -114,9 +114,7 @@ class RoboFile extends \Robo\Tasks {
public function docs() public function docs()
{ {
$cmd_parts = [ $cmd_parts = [
'cd build', 'phpdox',
'../vendor/bin/phpdox',
'cd ..'
]; ];
$this->_run($cmd_parts, ' && '); $this->_run($cmd_parts, ' && ');
} }
@ -128,7 +126,7 @@ class RoboFile extends \Robo\Tasks {
{ {
$files = $this->getAllSourceFiles(); $files = $this->getAllSourceFiles();
$chunks = array_chunk($files, 6); $chunks = array_chunk($files, 12);
foreach($chunks as $chunk) foreach($chunks as $chunk)
{ {
@ -136,29 +134,6 @@ class RoboFile extends \Robo\Tasks {
} }
} }
/**
* Run mutation tests with humbug
*
* @param bool $stats - if true, generates stats rather than running mutation tests
*/
public function mutate($stats = FALSE)
{
$test_parts = [
'vendor/bin/humbug'
];
$stat_parts = [
'vendor/bin/humbug',
'--skip-killed=yes',
'-v',
'./build/humbug.json'
];
$cmd_parts = ($stats) ? $stat_parts : $test_parts;
$this->_run($cmd_parts);
}
/** /**
* Run the phpcs tool * Run the phpcs tool
* *
@ -226,10 +201,8 @@ class RoboFile extends \Robo\Tasks {
public function test() public function test()
{ {
$this->lint(); $this->lint();
$this->taskPHPUnit()
->configFile('phpunit.xml') $this->_run(['phpunit']);
->printed(true)
->run();
} }
/** /**
@ -275,7 +248,9 @@ class RoboFile extends \Robo\Tasks {
$files = array_merge( $files = array_merge(
glob_recursive('build/*.php'), glob_recursive('build/*.php'),
glob_recursive('src/*.php'), glob_recursive('src/*.php'),
glob_recursive('src/**/*.php'),
glob_recursive('tests/*.php'), glob_recursive('tests/*.php'),
glob_recursive('tests/**/*.php'),
glob('*.php') glob('*.php')
); );

View File

@ -1,19 +1,20 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Lower level configuration // Lower level configuration
// //

View File

@ -1,19 +1,20 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
return [ return [
'anime_list' => [ 'anime_list' => [
'route_prefix' => '/anime', 'route_prefix' => '/anime',

View File

@ -1,16 +1,16 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */

View File

@ -1,19 +1,20 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/** /**

View File

@ -1,19 +1,20 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/** /**

View File

@ -1,19 +1,20 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 5.6 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
use const Aviat\AnimeClient\{ use const Aviat\AnimeClient\{
DEFAULT_CONTROLLER_METHOD, DEFAULT_CONTROLLER_METHOD,
DEFAULT_CONTROLLER_NAMESPACE DEFAULT_CONTROLLER_NAMESPACE
@ -53,7 +54,7 @@ return [
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
'anime.add.get' => [ 'anime.add.get' => [
'path' => '/anime/add', 'path' => '/anime/add',
'action' => 'add_form', 'action' => 'addForm',
'verb' => 'get', 'verb' => 'get',
], ],
'anime.add.post' => [ 'anime.add.post' => [
@ -82,7 +83,7 @@ return [
], ],
'manga.add.get' => [ 'manga.add.get' => [
'path' => '/manga/add', 'path' => '/manga/add',
'action' => 'add_form', 'action' => 'addForm',
'verb' => 'get', 'verb' => 'get',
], ],
'manga.add.post' => [ 'manga.add.post' => [
@ -183,7 +184,7 @@ return [
], ],
'update.post' => [ 'update.post' => [
'path' => '/{controller}/update_form', 'path' => '/{controller}/update_form',
'action' => 'form_update', 'action' => 'formUpdate',
'verb' => 'post', 'verb' => 'post',
'tokens' => [ 'tokens' => [
'controller' => '[a-z_]+', 'controller' => '[a-z_]+',

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -11,14 +11,8 @@ whose_list = "Tim"
# do you wish to show the anime collection? # do you wish to show the anime collection?
show_anime_collection = true show_anime_collection = true
# do you wish to show the manga collection?
show_manga_collection = false
# do you have a My Anime List account set up in mal.toml? # do you have a My Anime List account set up in mal.toml?
use_mal_api = false use_mal_api = false
# cache driver for api calls (NullDriver, SQLDriver, RedisDriver)
cache_driver = "NullDriver"
# path to public directory on the server # path to public directory on the server
asset_dir = "/../../public" asset_dir = "/../../public"

View File

@ -8,16 +8,5 @@ host = ""
user = "" user = ""
pass = "" pass = ""
port = "" port = ""
name = "default"
database = "" database = ""
file = "anime_collection.sqlite" file = "anime_collection.sqlite"
[cache]
type = "sqlite"
host = ""
user = ""
pass = ""
port = ""
name = "default"
database = ""
file = "anime_collection.sqlite"

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h2>Add Anime to your List</h2> <h2>Add Anime to your List</h2>
<form action="<?= $action_url ?>" method="post"> <form action="<?= $action_url ?>" method="post">
@ -36,5 +36,5 @@
</table> </table>
</form> </form>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/anime_collection') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/anime_collection') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,5 +1,5 @@
<main> <main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $url->generate('anime.add.get') ?>">Add Item</a> <a class="bracketed" href="<?= $url->generate('anime.add.get') ?>">Add Item</a>
<?php endif ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
@ -10,9 +10,9 @@
<h2><?= $escape->html($name) ?></h2> <h2><?= $escape->html($name) ?></h2>
<section class="media-wrap"> <section class="media-wrap">
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<?php if ($item['private'] && ! $auth->is_authenticated()) continue; ?> <?php if ($item['private'] && ! $auth->isAuthenticated()) continue; ?>
<article class="media" data-kitsu-id="<?= $item['id'] ?>" data-mal-id="<?= $item['mal_id'] ?>"> <article class="media" data-kitsu-id="<?= $item['id'] ?>" data-mal-id="<?= $item['mal_id'] ?>">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<button title="Increment episode count" class="plus_one" hidden>+1 Episode</button> <button title="Increment episode count" class="plus_one" hidden>+1 Episode</button>
<?php endif ?> <?php endif ?>
<img src="<?= $item['anime']['image'] ?>" alt="" /> <img src="<?= $item['anime']['image'] ?>" alt="" />
@ -25,10 +25,16 @@
</a> </a>
</div> </div>
<div class="table"> <div class="table">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<div class="row"> <div class="row">
<span class="edit"> <span class="edit">
<a class="bracketed" title="Edit information about this anime" href="<?= $urlGenerator->url("anime/edit/{$item['id']}/{$item['watching_status']}") ?>">Edit</a> <a class="bracketed" title="Edit information about this anime" href="<?=
$url->generate('edit', [
'controller' => 'anime',
'id' => $item['id'],
'status' => $item['watching_status']
]);
?>">Edit</a>
</span> </span>
</div> </div>
<?php endif ?> <?php endif ?>
@ -55,10 +61,10 @@
<div class="cover_streaming_link"> <div class="cover_streaming_link">
<?php if($link['meta']['link']): ?> <?php if($link['meta']['link']): ?>
<a href="<?= $link['link']?>" title="Stream '<?= $item['anime']['title'] ?>' on <?= $link['meta']['name'] ?>"> <a href="<?= $link['link']?>" title="Stream '<?= $item['anime']['title'] ?>' on <?= $link['meta']['name'] ?>">
<?= $link['meta']['logo'] ?> <img class="streaming-logo" width="20" height="20" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
</a> </a>
<?php else: ?> <?php else: ?>
<?= $link['meta']['logo'] ?> <img class="streaming-logo" width="20" height="20" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
<?php endif ?> <?php endif ?>
</div> </div>
<?php endforeach ?> <?php endforeach ?>
@ -85,6 +91,6 @@
<?php endforeach ?> <?php endforeach ?>
<?php endif ?> <?php endif ?>
</main> </main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<script src="<?= $urlGenerator->asset_url('js.php/g/edit') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/edit') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,7 +1,7 @@
<main class="details"> <main class="details">
<section class="flex flex-no-wrap"> <section class="flex flex-no-wrap">
<div> <div>
<img class="cover" src="<?= $data['cover_image'] ?>" alt="" /> <img class="cover" width="402" height="284" src="<?= $data['cover_image'] ?>" alt="" />
<br /> <br />
<br /> <br />
<table class="media_details"> <table class="media_details">
@ -54,21 +54,21 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach($data['streaming_links'] as $streaming_link): ?> <?php foreach($data['streaming_links'] as $link): ?>
<tr> <tr>
<td class="align_left"> <td class="align_left">
<?php if ($streaming_link['meta']['link'] !== FALSE): ?> <?php if ($link['meta']['link'] !== FALSE): ?>
<a href="<?= $streaming_link['link'] ?>"> <a href="<?= $link['link'] ?>" title="Stream '<?= $data['title'] ?>' on <?= $link['meta']['name'] ?>">
<?= $streaming_link['meta']['logo'] ?> <img class="streaming-logo" width="50" height="50" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
&nbsp;&nbsp;<?= $streaming_link['meta']['name'] ?> &nbsp;&nbsp;<?= $link['meta']['name'] ?>
</a> </a>
<?php else: ?> <?php else: ?>
<?= $streaming_link['meta']['logo'] ?> <img class="streaming-logo" width="50" height="50" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
&nbsp;&nbsp;<?= $streaming_link['meta']['name'] ?> &nbsp;&nbsp;<?= $link['meta']['name'] ?>
<?php endif ?> <?php endif ?>
</td> </td>
<td><?= implode(', ', $streaming_link['subs']) ?></td> <td><?= implode(', ', $link['subs']) ?></td>
<td><?= implode(', ', $streaming_link['dubs']) ?></td> <td><?= implode(', ', $link['dubs']) ?></td>
</tr> </tr>
<?php endforeach ?> <?php endforeach ?>
</tbody> </tbody>

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h2>Edit Anime List Item</h2> <h2>Edit Anime List Item</h2>
<form action="<?= $action ?>" method="post"> <form action="<?= $action ?>" method="post">
@ -107,5 +107,5 @@
</form> </form>
</fieldset> </fieldset>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/edit') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/edit') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,5 +1,5 @@
<main> <main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $url->generate('anime.add.get') ?>">Add Item</a> <a class="bracketed" href="<?= $url->generate('anime.add.get') ?>">Add Item</a>
<?php endif ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
@ -10,7 +10,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<?php if($auth->is_authenticated()): ?> <?php if($auth->isAuthenticated()): ?>
<td class="no_border">&nbsp;</td> <td class="no_border">&nbsp;</td>
<?php endif ?> <?php endif ?>
<th>Title</th> <th>Title</th>
@ -26,9 +26,9 @@
</thead> </thead>
<tbody> <tbody>
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<?php if ($item['private'] && ! $auth->is_authenticated()) continue; ?> <?php if ($item['private'] && ! $auth->isAuthenticated()) continue; ?>
<tr id="a-<?= $item['id'] ?>"> <tr id="a-<?= $item['id'] ?>">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<td> <td>
<a class="bracketed" href="<?= $urlGenerator->url("/anime/edit/{$item['id']}/{$item['watching_status']}") ?>">Edit</a> <a class="bracketed" href="<?= $urlGenerator->url("/anime/edit/{$item['id']}/{$item['watching_status']}") ?>">Edit</a>
</td> </td>
@ -64,11 +64,11 @@
<td> <td>
<?php foreach($item['anime']['streaming_links'] as $link): ?> <?php foreach($item['anime']['streaming_links'] as $link): ?>
<?php if ($link['meta']['link'] !== FALSE): ?> <?php if ($link['meta']['link'] !== FALSE): ?>
<a href="<?= $link['link'] ?>"> <a href="<?= $link['link'] ?>" title="Stream '<?= $item['anime']['title'] ?>' on <?= $link['meta']['name'] ?>">
<?= $link['meta']['logo'] ?> <img class="streaming-logo" width="50" height="50" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
</a> </a>
<?php else: ?> <?php else: ?>
<?= $link['meta']['logo'] ?> <img class="streaming-logo" width="50" height="50" src="<?= $urlGenerator->assetUrl('images', $link['meta']['image']) ?>" alt="<?= $link['meta']['name'] ?> logo" />
<?php endif ?> <?php endif ?>
<?php endforeach ?> <?php endforeach ?>
</td> </td>
@ -86,5 +86,5 @@
<?php endforeach ?> <?php endforeach ?>
<?php endif ?> <?php endif ?>
</main> </main>
<?php $group = ($auth->is_authenticated()) ? 'table_edit' : 'table' ?> <?php $group = ($auth->isAuthenticated()) ? 'table_edit' : 'table' ?>
<script src="<?= $urlGenerator->asset_url("js.php/g/{$group}") ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl("js.php/g/{$group}") ?>"></script>

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h2>Add Anime to your Collection</h2> <h2>Add Anime to your Collection</h2>
<form action="<?= $action_url ?>" method="post"> <form action="<?= $action_url ?>" method="post">
@ -39,5 +39,5 @@
</table> </table>
</form> </form>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/anime_collection') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/anime_collection') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,5 +1,5 @@
<main> <main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $url->generate('collection.add.get') ?>">Add Item</a> <a class="bracketed" href="<?= $url->generate('collection.add.get') ?>">Add Item</a>
<?php endif ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
@ -19,7 +19,7 @@
</a> </a>
</div> </div>
<div class="table"> <div class="table">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<div class="row"> <div class="row">
<span class="edit"><a class="bracketed" href="<?= $urlGenerator->url("collection/edit/{$item['hummingbird_id']}") ?>">Edit</a></span> <span class="edit"><a class="bracketed" href="<?= $urlGenerator->url("collection/edit/{$item['hummingbird_id']}") ?>">Edit</a></span>
<?php /*<span class="delete"><a class="bracketed" href="<?= $urlGenerator->url("collection/delete/{$item['hummingbird_id']}") ?>">Delete</a></span> */ ?> <?php /*<span class="delete"><a class="bracketed" href="<?= $urlGenerator->url("collection/delete/{$item['hummingbird_id']}") ?>">Delete</a></span> */ ?>

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h2>Edit Anime Collection Item</h2> <h2>Edit Anime Collection Item</h2>
<form action="<?= $action_url ?>" method="post"> <form action="<?= $action_url ?>" method="post">
@ -62,5 +62,5 @@
</form> </form>
</fieldset> </fieldset>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/anime_collection') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/anime_collection') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,6 +1,6 @@
<main> <main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $urlGenerator->full_url('collection/add', 'anime') ?>">Add Item</a> <a class="bracketed" href="<?= $urlGenerator->fullUrl('collection/add', 'anime') ?>">Add Item</a>
<?php endif ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
<h3>There's nothing here!</h3> <h3>There's nothing here!</h3>
@ -10,7 +10,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<?php if($auth->is_authenticated()): ?> <?php if($auth->isAuthenticated()): ?>
<th>Actions</th> <th>Actions</th>
<?php endif ?> <?php endif ?>
<th>Title</th> <th>Title</th>
@ -24,10 +24,10 @@
<tbody> <tbody>
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<tr> <tr>
<?php if($auth->is_authenticated()): ?> <?php if($auth->isAuthenticated()): ?>
<td> <td>
<a class="bracketed" href="<?= $urlGenerator->full_url("collection/edit/{$item['hummingbird_id']}") ?>">Edit</a> <a class="bracketed" href="<?= $urlGenerator->fullUrl("collection/edit/{$item['hummingbird_id']}") ?>">Edit</a>
<?php /*<a class="bracketed" href="<?= $urlGenerator->full_url("collection/delete/{$item['hummingbird_id']}") ?>">Delete</a>*/ ?> <?php /*<a class="bracketed" href="<?= $urlGenerator->fullUrl("collection/delete/{$item['hummingbird_id']}") ?>">Delete</a>*/ ?>
</td> </td>
<?php endif ?> <?php endif ?>
<td class="align_left"> <td class="align_left">
@ -49,4 +49,4 @@
<?php endforeach ?> <?php endforeach ?>
<?php endif ?> <?php endif ?>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/table') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/table') ?>"></script>

View File

@ -1,3 +1,3 @@
<script src="<?= $urlGenerator->asset_url('js.php/g/event') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/event') ?>"></script>
</body> </body>
</html> </html>

View File

@ -6,15 +6,18 @@
<meta http-equiv="cache-control" content="no-store" /> <meta http-equiv="cache-control" content="no-store" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self'" /> <meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="<?= $urlGenerator->assetUrl('favicon.ico') ?>" />
<link rel="stylesheet" href="<?= $urlGenerator->asset_url('css.php/g/base') ?>" /> <link rel="stylesheet" href="<?= $urlGenerator->assetUrl('css.php/g/base/debug') ?>" />
<script src="<?= $urlGenerator->asset_url('js.php/g/base') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/base') ?>"></script>
</head> </head>
<body class="<?= $escape->attr($url_type) ?> list"> <body class="<?= $escape->attr($url_type) ?> list">
<header> <header>
<?php include 'main-menu.php' ?> <?php include 'main-menu.php' ?>
<?php if(isset($message) && is_array($message)): <?php if(isset($message) && is_array($message)):
extract($message); foreach($message as $m)
include 'message.php'; {
extract($m);
include 'message.php';
}
endif ?> endif ?>
</header> </header>

View File

@ -2,22 +2,22 @@
<h1 class="flex flex-align-end flex-wrap"> <h1 class="flex flex-align-end flex-wrap">
<span class="flex-no-wrap grow-1"> <span class="flex-no-wrap grow-1">
<?php if(strpos($route_path, 'collection') === FALSE): ?> <?php if(strpos($route_path, 'collection') === FALSE): ?>
<a href="<?= $escape->attr($urlGenerator->default_url($url_type)) ?>"> <a href="<?= $escape->attr($urlGenerator->defaultUrl($url_type)) ?>">
<?= $config->get('whose_list') ?>'s <?= ucfirst($url_type) ?> List <?= $config->get('whose_list') ?>'s <?= ucfirst($url_type) ?> List
</a> </a>
<?php if($config->get("show_{$url_type}_collection")): ?> <?php if($config->get("show_{$url_type}_collection")): ?>
[<a href="<?= $urlGenerator->url('collection/view') ?>"><?= ucfirst($url_type) ?> Collection</a>] [<a href="<?= $urlGenerator->url('collection/view') ?>"><?= ucfirst($url_type) ?> Collection</a>]
<?php endif ?> <?php endif ?>
[<a href="<?= $urlGenerator->default_url($other_type) ?>"><?= ucfirst($other_type) ?> List</a>] [<a href="<?= $urlGenerator->defaultUrl($other_type) ?>"><?= ucfirst($other_type) ?> List</a>]
<?php else: ?> <?php else: ?>
<a href="<?= $urlGenerator->url('collection/view') ?>"> <a href="<?= $urlGenerator->url('collection/view') ?>">
<?= $config->get('whose_list') ?>'s <?= ucfirst($url_type) ?> Collection <?= $config->get('whose_list') ?>'s <?= ucfirst($url_type) ?> Collection
</a> </a>
[<a href="<?= $urlGenerator->default_url('anime') ?>">Anime List</a>] [<a href="<?= $urlGenerator->defaultUrl('anime') ?>">Anime List</a>]
[<a href="<?= $urlGenerator->default_url('manga') ?>">Manga List</a>] [<a href="<?= $urlGenerator->defaultUrl('manga') ?>">Manga List</a>]
<?php endif ?> <?php endif ?>
</span> </span>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<span class="flex-no-wrap">&nbsp;</span> <span class="flex-no-wrap">&nbsp;</span>
<span class="flex-no-wrap small-font"> <span class="flex-no-wrap small-font">
<button type="button" class="js-clear-cache user-btn">Clear API Cache</button> <button type="button" class="js-clear-cache user-btn">Clear API Cache</button>
@ -25,7 +25,7 @@
<span class="flex-no-wrap">&nbsp;</span> <span class="flex-no-wrap">&nbsp;</span>
<?php endif ?> <?php endif ?>
<span class="flex-no-wrap small-font"> <span class="flex-no-wrap small-font">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $url->generate('logout') ?>">Logout</a> <a class="bracketed" href="<?= $url->generate('logout') ?>">Logout</a>
<?php else: ?> <?php else: ?>
[<a href="<?= $url->generate('login'); ?>"><?= $config->get('whose_list') ?>'s Login</a>] [<a href="<?= $url->generate('login'); ?>"><?= $config->get('whose_list') ?>'s Login</a>]
@ -33,12 +33,12 @@
</span> </span>
</h1> </h1>
<nav> <nav>
<?php if ($container->get('util')->is_view_page()): ?> <?php if ($container->get('util')->isViewPage()): ?>
<?= $helper->menu($menu_name) ?> <?= $helper->menu($menu_name) ?>
<br /> <br />
<ul> <ul>
<li class="<?= Util::is_not_selected('list', $urlGenerator->last_segment()) ?>"><a href="<?= $urlGenerator->url($route_path) ?>">Cover View</a></li> <li class="<?= Util::isNotSelected('list', $urlGenerator->lastSegment()) ?>"><a href="<?= $urlGenerator->url($route_path) ?>">Cover View</a></li>
<li class="<?= Util::is_selected('list', $urlGenerator->last_segment()) ?>"><a href="<?= $urlGenerator->url("{$route_path}/list") ?>">List View</a></li> <li class="<?= Util::isSelected('list', $urlGenerator->lastSegment()) ?>"><a href="<?= $urlGenerator->url("{$route_path}/list") ?>">List View</a></li>
</ul> </ul>
<?php endif ?> <?php endif ?>
</nav> </nav>

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h2>Add Manga to your List</h2> <h2>Add Manga to your List</h2>
<form action="<?= $action_url ?>" method="post"> <form action="<?= $action_url ?>" method="post">
@ -36,5 +36,5 @@
</table> </table>
</form> </form>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/manga_collection') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/manga_collection') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,5 +1,5 @@
<main> <main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $urlGenerator->url('manga/add') ?>">Add Item</a> <a class="bracketed" href="<?= $urlGenerator->url('manga/add') ?>">Add Item</a>
<?php endif ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
@ -11,7 +11,7 @@
<section class="media-wrap"> <section class="media-wrap">
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<article class="media" id="manga-<?= $item['id'] ?>"> <article class="media" id="manga-<?= $item['id'] ?>">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<div class="edit_buttons" hidden> <div class="edit_buttons" hidden>
<button class="plus_one_chapter">+1 Chapter</button> <button class="plus_one_chapter">+1 Chapter</button>
</div> </div>
@ -26,7 +26,7 @@
</a> </a>
</div> </div>
<div class="table"> <div class="table">
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<div class="row"> <div class="row">
<span class="edit"> <span class="edit">
<a class="bracketed" title="Edit information about this manga" href="<?= $urlGenerator->url("manga/edit/{$item['id']}/{$name}") ?>">Edit</a> <a class="bracketed" title="Edit information about this manga" href="<?= $urlGenerator->url("manga/edit/{$item['id']}/{$name}") ?>">Edit</a>
@ -55,6 +55,6 @@
<?php endforeach ?> <?php endforeach ?>
<?php endif ?> <?php endif ?>
</main> </main>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<script src="<?= $urlGenerator->asset_url('js.php/g/edit') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/edit') ?>"></script>
<?php endif ?> <?php endif ?>

View File

@ -1,4 +1,4 @@
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<main> <main>
<h1> <h1>
Edit <?= $item['manga']['titles'][0] ?> Edit <?= $item['manga']['titles'][0] ?>

View File

@ -1,7 +1,7 @@
<main> <main>
<?php /*if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<a class="bracketed" href="<?= $urlGenerator->url('manga/add') ?>">Add Item</a> <a class="bracketed" href="<?= $urlGenerator->url('manga/add') ?>">Add Item</a>
<?php endif*/ ?> <?php endif ?>
<?php if (empty($sections)): ?> <?php if (empty($sections)): ?>
<h3>There's nothing here!</h3> <h3>There's nothing here!</h3>
<?php else: ?> <?php else: ?>
@ -10,7 +10,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<?php if ($auth->is_authenticated()): ?> <?php if ($auth->isAuthenticated()): ?>
<th>&nbsp;</th> <th>&nbsp;</th>
<?php endif ?> <?php endif ?>
<th>Title</th> <th>Title</th>
@ -23,7 +23,7 @@
<tbody> <tbody>
<?php foreach($items as $item): ?> <?php foreach($items as $item): ?>
<tr id="manga-<?= $item['id'] ?>"> <tr id="manga-<?= $item['id'] ?>">
<?php if($auth->is_authenticated()): ?> <?php if($auth->isAuthenticated()): ?>
<td> <td>
<a class="bracketed" href="<?= $urlGenerator->url("manga/edit/{$item['id']}/{$name}") ?>">Edit</a> <a class="bracketed" href="<?= $urlGenerator->url("manga/edit/{$item['id']}/{$name}") ?>">Edit</a>
</td> </td>
@ -47,4 +47,4 @@
<?php endforeach ?> <?php endforeach ?>
<?php endif ?> <?php endif ?>
</main> </main>
<script src="<?= $urlGenerator->asset_url('js.php/g/table') ?>"></script> <script defer="defer" src="<?= $urlGenerator->assetUrl('js.php/g/table') ?>"></script>

View File

@ -65,7 +65,7 @@ class LogicalNotSpacingSniff implements Sniff
$next_token = $tokens[$stackPtr + 1]; $next_token = $tokens[$stackPtr + 1];
if (T_WHITESPACE !== $previous_token['code'] || T_WHITESPACE !== $next_token['code']) { if (T_WHITESPACE !== $previous_token['code'] || T_WHITESPACE !== $next_token['code']) {
$error = 'Logical operator ! should always be preceded and followed with a whitespace.'; $error = 'Logical operator ! should always be preceded and followed with a whitespace.';
$phpcsFile->addError($error, $stackPtr); $phpcsFile->addError($error, $stackPtr, 'badNot');
} }
}//end process() }//end process()

View File

@ -3,27 +3,10 @@
# We need to install dependencies only for Docker # We need to install dependencies only for Docker
[[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0 [[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0
# Where am I?
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
set -xe set -xe
# Install git (the php image doesn't have it) which is required by composer # Install git (the php image doesn't have it) which is required by composer
apt-get update -yqq echo -e 'http://dl-cdn.alpinelinux.org/alpine/edge/main\nhttp://dl-cdn.alpinelinux.org/alpine/edge/community\nhttp://dl-cdn.alpinelinux.org/alpine/edge/testing' > /etc/apk/repositories
apt-get install \ apk upgrade --update && apk add --no-cache \
git \ curl \
libxslt1-dev \ git
libxslt1.1 \
zlib1g-dev \
unzip \
-yqq
# Install phpunit, the tool that we will use for testing
curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar
chmod +x /usr/local/bin/phpunit
# Install extensions
pecl install xdebug
echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini
docker-php-ext-install xsl
docker-php-ext-install zip

View File

@ -1,11 +1,11 @@
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -5,7 +5,9 @@ $file_patterns = [
'app/bootstrap.php', 'app/bootstrap.php',
'migrations/*.php', 'migrations/*.php',
'src/**/*.php', 'src/**/*.php',
'src/*.php',
'tests/**/*.php', 'tests/**/*.php',
'tests/*.php'
]; ];
if ( ! function_exists('glob_recursive')) if ( ! function_exists('glob_recursive'))
@ -60,6 +62,7 @@ function get_tokens($source)
function replace_files(array $files, $template) function replace_files(array $files, $template)
{ {
print_r($files);
foreach ($files as $file) foreach ($files as $file)
{ {
$source = file_get_contents($file); $source = file_get_contents($file);

View File

@ -1,5 +1,5 @@
{ {
"name": "timw4mail/hummingbird-anime-client", "name": "aviat/hummingbird-anime-client",
"description": "A self-hosted anime/manga client for Kitsu.", "description": "A self-hosted anime/manga client for Kitsu.",
"license":"MIT", "license":"MIT",
"autoload": { "autoload": {
@ -21,7 +21,7 @@
"aura/router": "^3.0", "aura/router": "^3.0",
"aura/session": "^2.0", "aura/session": "^2.0",
"aviat/banker": "^1.0.0", "aviat/banker": "^1.0.0",
"aviat/ion": "1.0.*", "aviat/ion": "dev-master",
"filp/whoops": "^2.1.5", "filp/whoops": "^2.1.5",
"monolog/monolog": "^1.0", "monolog/monolog": "^1.0",
"psr/http-message": "~1.0", "psr/http-message": "~1.0",
@ -34,18 +34,23 @@
"require-dev": { "require-dev": {
"pdepend/pdepend": "^2.2", "pdepend/pdepend": "^2.2",
"sebastian/phpcpd": "^3.0", "sebastian/phpcpd": "^3.0",
"theseer/phpdox": "^0.9.0", "theseer/phpdox": "0.9.0",
"phploc/phploc": "^3.0", "phploc/phploc": "^3.0",
"phpmd/phpmd": "^2.4", "phpmd/phpmd": "^2.4",
"phpunit/phpunit": "^6.0", "phpunit/phpunit": "^6.0",
"robmorgan/phinx": "^0.6.4", "robmorgan/phinx": "~0.6.4",
"consolidation/robo": "~1.0", "consolidation/robo": "~1.0",
"henrikbjorn/lurker": "^1.1.0", "henrikbjorn/lurker": "^1.1.0",
"symfony/var-dumper": "^3.1", "symfony/var-dumper": "^3.1",
"squizlabs/php_codesniffer": "^3.0.0@beta" "squizlabs/php_codesniffer": "^3.0.0@beta",
"phpstan/phpstan": "^0.6.4"
}, },
"scripts": { "scripts": {
"build:css": "cd public && npm run build && cd ..", "build:css": "cd public && npm run build && cd ..",
"watch:css": "cd public && npm run watch" "coverage": "phpdbg -qrr -- vendor/bin/phpunit -c build",
"docs": "vendor/bin/phpdox",
"phpstan": "phpstan analyse src tests",
"watch:css": "cd public && npm run watch",
"test": "vendor/bin/phpunit"
} }
} }

View File

@ -28,25 +28,14 @@ if ($timezone === '' || $timezone === FALSE)
ini_set('date.timezone', 'GMT'); ini_set('date.timezone', 'GMT');
} }
/** // Load composer autoloader
* Joins paths together. Variadic to take an require __DIR__ . '/vendor/autoload.php';
* arbitrary number of arguments
*
* @return string
*/
function _dir()
{
return implode(DIRECTORY_SEPARATOR, func_get_args());
}
// Define base directories // Define base directories
$APP_DIR = _dir(__DIR__, 'app'); $APP_DIR = _dir(__DIR__, 'app');
$APPCONF_DIR = _dir($APP_DIR, 'appConf'); $APPCONF_DIR = _dir($APP_DIR, 'appConf');
$CONF_DIR = _dir($APP_DIR, 'config'); $CONF_DIR = _dir($APP_DIR, 'config');
// Load composer autoloader
require _dir(__DIR__, 'vendor/autoload.php');
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Setup error handling // Setup error handling
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View File

@ -8,11 +8,11 @@
<target>phpdoc</target> <target>phpdoc</target>
</transformer> </transformer>
<transformations> <transformations>
<template name="zend" /> <template name="clean" />
</transformations> </transformations>
<files> <files>
<directory>src</directory> <directory>src</directory>
<directory>vendor/aviat/ion/src</directory> <!-- <directory>vendor/aviat/ion/src</directory>
<directory>vendor/container-interop/container-interop/src</directory> <directory>vendor/container-interop/container-interop/src</directory> -->
</files> </files>
</phpdoc> </phpdoc>

View File

@ -9,7 +9,7 @@
<bootstrap /> <bootstrap />
<!-- A phpDox project to process, you can have multiple projects in one config file --> <!-- A phpDox project to process, you can have multiple projects in one config file -->
<project name="Hummingbird Anime Client" source="../src" workdir="phpdox/xml"> <project name="Hummingbird Anime Client" source="src" workdir="build/phpdox/xml">
<!-- @name - The name of the project --> <!-- @name - The name of the project -->
<!-- @source - The source directory of the application to process --> <!-- @source - The source directory of the application to process -->
<!-- @workdir - The directory to store the xml data files in --> <!-- @workdir - The directory to store the xml data files in -->
@ -56,12 +56,12 @@
</collector> </collector>
<!-- Configuration of generation process --> <!-- Configuration of generation process -->
<generator output="../docs"> <generator output="docs">
<!-- @output - (Base-)Directory to store output data in --> <!-- @output - (Base-)Directory to store output data in -->
<!-- A generation process consists of one or more build tasks and of (optional) enrich sources --> <!-- A generation process consists of one or more build tasks and of (optional) enrich sources -->
<enrich base="logs"> <enrich base="build/logs">
<!-- @base - (Base-)Directory of datafiles used for enrich process --> <!-- @base - (Base-)Directory of datafiles used for enrich process -->
<!--<source type="...">--> <!--<source type="...">-->
@ -117,10 +117,10 @@
<!-- An engine and thus build node can have additional configuration child nodes, please check the documentation for the engine to find out more --> <!-- An engine and thus build node can have additional configuration child nodes, please check the documentation for the engine to find out more -->
<!-- default engine "html" --> <!-- default engine "html" -->
<build engine="html" enabled="true"> <build engine="html" output="html" />
<template dir="${phpDox.home}/templates/html" /> <!-- <template dir="${phpDox.home}/templates/html" /> -
<file extension="html" /> <file extension="html" />
</build> </build> -->
</generator> </generator>
</project> </project>

View File

@ -1,19 +1,20 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
namespace Aviat\EasyMin; namespace Aviat\EasyMin;
require_once('./min.php'); require_once('./min.php');
@ -23,21 +24,21 @@ require_once('./min.php');
*/ */
class CSSMin extends BaseMin { class CSSMin extends BaseMin {
protected $css_root; protected $cssRoot;
protected $path_from; protected $pathFrom;
protected $path_to; protected $pathTo;
protected $group; protected $group;
protected $last_modified; protected $lastModified;
protected $requested_time; protected $requestedTime;
public function __construct(array $config, array $groups) public function __construct(array $config, array $groups)
{ {
$group = $_GET['g']; $group = $_GET['g'];
$this->css_root = $config['css_root']; $this->cssRoot = $config['css_root'];
$this->path_from = $config['path_from']; $this->pathFrom = $config['path_from'];
$this->path_to = $config['path_to']; $this->pathTo = $config['path_to'];
$this->group = $groups[$group]; $this->group = $groups[$group];
$this->last_modified = $this->get_last_modified(); $this->lastModified = $this->getLastModified();
$this->send(); $this->send();
} }
@ -49,14 +50,14 @@ class CSSMin extends BaseMin {
*/ */
protected function send() protected function send()
{ {
if($this->last_modified >= $this->get_if_modified() && $this->is_not_debug()) if($this->lastModified >= $this->getIfModified() && $this->isNotDebug())
{ {
throw new FileNotChangedException(); throw new FileNotChangedException();
} }
$css = ( ! array_key_exists('debug', $_GET)) $css = ( ! array_key_exists('debug', $_GET))
? $this->compress($this->get_css()) ? $this->compress($this->getCss())
: $this->get_css(); : $this->getCss();
$this->output($css); $this->output($css);
} }
@ -74,7 +75,7 @@ class CSSMin extends BaseMin {
//Remove tabs, spaces, newlines, etc. //Remove tabs, spaces, newlines, etc.
$buffer = preg_replace('`\s+`', ' ', $buffer); $buffer = preg_replace('`\s+`', ' ', $buffer);
$replace = array( $replace = [
' )' => ')', ' )' => ')',
') ' => ')', ') ' => ')',
' }' => '}', ' }' => '}',
@ -84,7 +85,7 @@ class CSSMin extends BaseMin {
', ' => ',', ', ' => ',',
': ' => ':', ': ' => ':',
'; ' => ';', '; ' => ';',
); ];
//Eradicate every last space! //Eradicate every last space!
$buffer = trim(strtr($buffer, $replace)); $buffer = trim(strtr($buffer, $replace));
@ -99,17 +100,17 @@ class CSSMin extends BaseMin {
* *
* @return int * @return int
*/ */
protected function get_last_modified() protected function getLastModified()
{ {
$modified = array(); $modified = [];
// Get all the css files, and concatenate them together // Get all the css files, and concatenate them together
if(isset($this->group)) if(isset($this->group))
{ {
foreach($this->group as $file) foreach($this->group as $file)
{ {
$new_file = realpath("{$this->css_root}{$file}"); $newFile = realpath("{$this->cssRoot}{$file}");
$modified[] = filemtime($new_file); $modified[] = filemtime($newFile);
} }
} }
@ -127,19 +128,19 @@ class CSSMin extends BaseMin {
* *
* @return string * @return string
*/ */
protected function get_css() protected function getCss()
{ {
$css = ''; $css = '';
foreach($this->group as $file) foreach($this->group as $file)
{ {
$new_file = realpath("{$this->css_root}{$file}"); $newFile = realpath("{$this->cssRoot}{$file}");
$css .= file_get_contents($new_file); $css .= file_get_contents($newFile);
} }
// Correct paths that have changed due to concatenation // Correct paths that have changed due to concatenation
// based on rules in the config file // based on rules in the config file
$css = str_replace($this->path_from, $this->path_to, $css); $css = str_replace($this->pathFrom, $this->pathTo, $css);
return $css; return $css;
} }
@ -151,7 +152,7 @@ class CSSMin extends BaseMin {
*/ */
protected function output($css) protected function output($css)
{ {
$this->send_final_output($css, 'text/css', $this->last_modified); $this->sendFinalOutput($css, 'text/css', $this->lastModified);
} }
} }

View File

@ -371,7 +371,7 @@ hr
img img
{ {
height:auto; height:auto;
max-width:100%; /* max-width:100%; */
vertical-align:baseline; vertical-align:baseline;
} }
@ -1035,6 +1035,10 @@ a:hover, a:active {
margin:0.25em 0.125em; margin:0.25em 0.125em;
} }
.media > img {
width: 100%;
}
.media .edit_buttons > button { .media .edit_buttons > button {
margin:0.5em auto; margin:0.5em auto;
} }
@ -1044,6 +1048,7 @@ a:hover, a:active {
.medium_metadata > div, .medium_metadata > div,
.row { .row {
text-shadow:1px 2px 1px rgba(0, 0, 0, .85); text-shadow:1px 2px 1px rgba(0, 0, 0, .85);
background:#000;
background:rgba(0, 0, 0, .45); background:rgba(0, 0, 0, .45);
color:#ffffff; color:#ffffff;
padding:0.25em 0.125em; padding:0.25em 0.125em;
@ -1127,6 +1132,7 @@ a:hover, a:active {
.anime .row, .manga .row { .anime .row, .manga .row {
width:100%; width:100%;
background:#000;
background:rgba(0, 0, 0, .45); background:rgba(0, 0, 0, .45);
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
@ -1316,6 +1322,7 @@ a:hover, a:active {
.streaming-logo { .streaming-logo {
width: 50px; width: 50px;
height: 50px; height: 50px;
vertical-align:middle;
} }
.cover_streaming_link .streaming-logo { .cover_streaming_link .streaming-logo {

View File

@ -4,6 +4,7 @@
--link-shadow: 1px 1px 1px #000; --link-shadow: 1px 1px 1px #000;
--shadow: 1px 2px 1px rgba(0, 0, 0, 0.85); --shadow: 1px 2px 1px rgba(0, 0, 0, 0.85);
--title-overlay: rgba(0, 0, 0, 0.45); --title-overlay: rgba(0, 0, 0, 0.45);
--title-overlay-fallback: #000;
--text-color: #ffffff; --text-color: #ffffff;
--normal-padding: 0.25em 0.125em; --normal-padding: 0.25em 0.125em;
--link-hover-color: #7d12db; --link-hover-color: #7d12db;
@ -306,6 +307,10 @@ a:hover, a:active {
margin: var(--normal-padding); margin: var(--normal-padding);
} }
.media > img {
width: 100%;
}
.media .edit_buttons > button { .media .edit_buttons > button {
margin:0.5em auto; margin:0.5em auto;
} }
@ -315,6 +320,7 @@ a:hover, a:active {
.medium_metadata > div, .medium_metadata > div,
.row { .row {
text-shadow: var(--shadow); text-shadow: var(--shadow);
background: var(--title-overlay-fallback);
background: var(--title-overlay); background: var(--title-overlay);
color: var(--text-color); color: var(--text-color);
padding: var(--normal-padding); padding: var(--normal-padding);
@ -398,6 +404,7 @@ a:hover, a:active {
.anime .row, .manga .row { .anime .row, .manga .row {
width:100%; width:100%;
background: var(--title-overlay-fallback);
background: var(--title-overlay); background: var(--title-overlay);
display: flex; display: flex;
align-content: space-around; align-content: space-around;
@ -568,6 +575,7 @@ a:hover, a:active {
.streaming-logo { .streaming-logo {
width: 50px; width: 50px;
height: 50px; height: 50px;
vertical-align:middle;
} }
.cover_streaming_link .streaming-logo { .cover_streaming_link .streaming-logo {

View File

@ -337,7 +337,7 @@ hr
img img
{ {
height:auto; height:auto;
max-width:100%; /* max-width:100%; */
vertical-align:baseline; vertical-align:baseline;
} }

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,16 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
@ -29,27 +29,27 @@ require_once('./min.php');
*/ */
class JSMin extends BaseMin { class JSMin extends BaseMin {
protected $js_root; protected $jsRoot;
protected $js_group; protected $jsGroup;
protected $js_groups_file; protected $jsGroupsFile;
protected $cache_file; protected $cacheFile;
protected $last_modified; protected $lastModified;
protected $requested_time; protected $requestedTime;
protected $cache_modified; protected $cacheModified;
public function __construct(array $config, array $groups) public function __construct(array $config, array $groups)
{ {
$group = $_GET['g']; $group = $_GET['g'];
$this->js_root = $config['js_root']; $this->jsRoot = $config['js_root'];
$this->js_group = $groups[$group]; $this->jsGroup = $groups[$group];
$this->js_groups_file = $config['js_groups_file']; $this->jsGroupsFile = $config['js_groups_file'];
$this->cache_file = "{$this->js_root}cache/{$group}"; $this->cacheFile = "{$this->jsRoot}cache/{$group}";
$this->last_modified = $this->get_last_modified(); $this->lastModified = $this->getLastModified();
$this->cache_modified = (is_file($this->cache_file)) $this->cacheModified = (is_file($this->cacheFile))
? filemtime($this->cache_file) ? filemtime($this->cacheFile)
: 0; : 0;
// Output some JS! // Output some JS!
@ -59,24 +59,24 @@ class JSMin extends BaseMin {
protected function send() protected function send()
{ {
// Override caching if debug key is set // Override caching if debug key is set
if($this->is_debug_call()) if($this->isDebugCall())
{ {
return $this->output($this->get_files()); return $this->output($this->getFiles());
} }
// If the browser's cached version is up to date, // If the browser's cached version is up to date,
// don't resend the file // don't resend the file
if($this->last_modified == $this->get_if_modified() && $this->is_not_debug()) if($this->lastModified == $this->getIfModified() && $this->isNotDebug())
{ {
throw new FileNotChangedException(); throw new FileNotChangedException();
} }
if($this->cache_modified < $this->last_modified) if($this->cacheModified < $this->lastModified)
{ {
$js = $this->minify($this->get_files()); $js = $this->minify($this->getFiles());
//Make sure cache file gets created/updated //Make sure cache file gets created/updated
if (file_put_contents($this->cache_file, $js) === FALSE) if (file_put_contents($this->cacheFile, $js) === FALSE)
{ {
echo 'Cache file was not created. Make sure you have the correct folder permissions.'; echo 'Cache file was not created. Make sure you have the correct folder permissions.';
return; return;
@ -86,7 +86,7 @@ class JSMin extends BaseMin {
} }
else else
{ {
return $this->output(file_get_contents($this->cache_file)); return $this->output(file_get_contents($this->cacheFile));
} }
} }
@ -96,7 +96,7 @@ class JSMin extends BaseMin {
* @param array $options - Form parameters * @param array $options - Form parameters
* @return object * @return object
*/ */
protected function closure_call(array $options) protected function closureCall(array $options)
{ {
$formFields = http_build_query($options); $formFields = http_build_query($options);
@ -123,19 +123,19 @@ class JSMin extends BaseMin {
* @param array $options * @param array $options
* @return void * @return void
*/ */
protected function check_minify_errors($options) protected function checkMinifyErrors($options)
{ {
$error_res = $this->closure_call($options); $errorRes = $this->closureCall($options);
$error_json = $error_res->getBody(); $errorJson = $errorRes->getBody();
$error_obj = Json::decode($error_json) ?: (object)[]; $errorObj = Json::decode($errorJson) ?: (object)[];
// Show error if exists // Show error if exists
if ( ! empty($error_obj->errors) || ! empty($error_obj->serverErrors)) if ( ! empty($errorObj->errors) || ! empty($errorObj->serverErrors))
{ {
$error_json = Json::encode($error_obj, JSON_PRETTY_PRINT); $errorJson = Json::encode($errorObj, JSON_PRETTY_PRINT);
header('Content-type: application/javascript'); header('Content-type: application/javascript');
echo "console.error(${error_json});"; echo "console.error(${errorJson});";
die(); die();
} }
} }
@ -148,14 +148,14 @@ class JSMin extends BaseMin {
* *
* @return string * @return string
*/ */
protected function get_files() protected function getFiles()
{ {
$js = ''; $js = '';
foreach($this->js_group as $file) foreach($this->jsGroup as $file)
{ {
$new_file = realpath("{$this->js_root}{$file}"); $newFile = realpath("{$this->jsRoot}{$file}");
$js .= file_get_contents($new_file) . "\n\n"; $js .= file_get_contents($newFile) . "\n\n";
} }
return $js; return $js;
@ -166,24 +166,24 @@ class JSMin extends BaseMin {
* *
* @return int * @return int
*/ */
protected function get_last_modified() protected function getLastModified()
{ {
$modified = array(); $modified = [];
foreach($this->js_group as $file) foreach($this->jsGroup as $file)
{ {
$new_file = realpath("{$this->js_root}{$file}"); $newFile = realpath("{$this->jsRoot}{$file}");
$modified[] = filemtime($new_file); $modified[] = filemtime($newFile);
} }
//Add this page too, as well as the groups file //Add this page too, as well as the groups file
$modified[] = filemtime(__FILE__); $modified[] = filemtime(__FILE__);
$modified[] = filemtime($this->js_groups_file); $modified[] = filemtime($this->jsGroupsFile);
rsort($modified); rsort($modified);
$last_modified = $modified[0]; $lastModified = $modified[0];
return $last_modified; return $lastModified;
} }
/** /**
@ -205,11 +205,11 @@ class JSMin extends BaseMin {
]; ];
// Check for errors // Check for errors
$this->check_minify_errors($options); $this->checkMinifyErrors($options);
// Now actually retrieve the compiled code // Now actually retrieve the compiled code
$options['output_info'] = 'compiled_code'; $options['output_info'] = 'compiled_code';
$res = $this->closure_call($options); $res = $this->closureCall($options);
$json = $res->getBody(); $json = $res->getBody();
$obj = Json::decode($json); $obj = Json::decode($json);
@ -225,7 +225,7 @@ class JSMin extends BaseMin {
*/ */
protected function output($js) protected function output($js)
{ {
$this->send_final_output($js, 'application/javascript', $this->last_modified); $this->sendFinalOutput($js, 'application/javascript', $this->lastModified);
} }
} }
@ -235,11 +235,11 @@ class JSMin extends BaseMin {
$config = require_once('../app/appConf/minify_config.php'); $config = require_once('../app/appConf/minify_config.php');
$groups = require_once($config['js_groups_file']); $groups = require_once($config['js_groups_file']);
$cache_dir = "{$config['js_root']}cache"; $cacheDir = "{$config['js_root']}cache";
if ( ! is_dir($cache_dir)) if ( ! is_dir($cacheDir))
{ {
mkdir($cache_dir); mkdir($cacheDir);
} }
if ( ! array_key_exists($_GET['g'], $groups)) if ( ! array_key_exists($_GET['g'], $groups))

View File

@ -4,7 +4,7 @@
const search = (tempHtml, query) => { const search = (tempHtml, query) => {
_.$('.cssload-loader')[0].removeAttribute('hidden'); _.$('.cssload-loader')[0].removeAttribute('hidden');
_.get(_.url('/collection/search'), {'query':query}, (searchResults, status) => { _.get(_.url('/collection/search'), {query}, (searchResults, status) => {
searchResults = JSON.parse(searchResults); searchResults = JSON.parse(searchResults);
_.$('.cssload-loader')[0].setAttribute('hidden', 'hidden'); _.$('.cssload-loader')[0].setAttribute('hidden', 'hidden');
@ -18,7 +18,7 @@
}); });
}; };
_.get('/public/templates/anime-ajax-search-results.html', tempHtml => { _.get('/public/templates/anime-ajax-search-results.html', (tempHtml) => {
_.on('#search', 'keyup', _.throttle(250, function(e) { _.on('#search', 'keyup', _.throttle(250, function(e) {
let query = encodeURIComponent(this.value); let query = encodeURIComponent(this.value);
if (query === '') { if (query === '') {

View File

@ -6,48 +6,47 @@
'use strict'; 'use strict';
// Action to increment episode count // Action to increment episode count
_.on('body.anime.list', 'click', '.plus_one', e => { _.on('body.anime.list', 'click', '.plus_one', (e) => {
let parent_sel = _.closestParent(e.target, 'article'); let parentSel = _.closestParent(e.target, 'article');
let watched_count = parseInt(_.$('.completed_number', parent_sel)[0].textContent, 10); let watchedCount = parseInt(_.$('.completed_number', parentSel)[0].textContent, 10);
let total_count = parseInt(_.$('.total_number', parent_sel)[0].textContent, 10); let totalCount = parseInt(_.$('.total_number', parentSel)[0].textContent, 10);
let title = _.$('.name a', parent_sel)[0].textContent; let title = _.$('.name a', parentSel)[0].textContent;
// Setup the update data // Setup the update data
let data = { let data = {
id: parent_sel.dataset.kitsuId, id: parentSel.dataset.kitsuId,
mal_id: parent_sel.dataset.malId, mal_id: parentSel.dataset.malId,
data: { data: {
progress: watched_count + 1 progress: watchedCount + 1
} }
}; };
// If the episode count is 0, and incremented, // If the episode count is 0, and incremented,
// change status to currently watching // change status to currently watching
if (isNaN(watched_count) || watched_count === 0) { if (isNaN(watchedCount) || watchedCount === 0) {
data.data.status = 'current'; data.data.status = 'current';
} }
// If you increment at the last episode, mark as completed // If you increment at the last episode, mark as completed
if (( ! isNaN(watched_count)) && (watched_count + 1) == total_count) { if (( ! isNaN(watchedCount)) && (watchedCount + 1) === totalCount) {
data.data.status = 'completed'; data.data.status = 'completed';
} }
// okay, lets actually make some changes! // okay, lets actually make some changes!
_.ajax(_.url('/anime/update'), { _.ajax(_.url('/anime/update'), {
data: data, data,
dataType: 'json', dataType: 'json',
type: 'POST', type: 'POST',
success: () => { success: () => {
if (data.data.status == 'completed') { if (data.data.status === 'completed') {
_.hide(parent_sel); _.hide(parentSel);
} }
_.showMessage('success', `Successfully updated ${title}`); _.showMessage('success', `Successfully updated ${title}`);
_.$('.completed_number', parent_sel)[0].textContent = ++watched_count; _.$('.completed_number', parentSel)[0].textContent = ++watchedCount;
_.scrollToTop(); _.scrollToTop();
}, },
error: (xhr, errorType, error) => { error: (xhr, errorType, error) => {
console.error(error);
_.showMessage('error', `Failed to update ${title}. `); _.showMessage('error', `Failed to update ${title}. `);
_.scrollToTop(); _.scrollToTop();
} }

View File

@ -26,7 +26,7 @@ var AnimeClient = (function(w) {
* @return {array} - array of dom elements * @return {array} - array of dom elements
*/ */
$(selector, context) { $(selector, context) {
if (typeof selector != "string" || selector === undefined) { if (typeof selector !== 'string') {
return selector; return selector;
} }
@ -78,10 +78,10 @@ var AnimeClient = (function(w) {
*/ */
showMessage(type, message) { showMessage(type, message) {
let template = let template =
`<div class="message ${type}"> `<div class='message ${type}'>
<span class="icon"></span> <span class='icon'></span>
${message} ${message}
<span class="close"></span> <span class='close'></span>
</div>`; </div>`;
let sel = AnimeClient.$('.message'); let sel = AnimeClient.$('.message');
@ -200,7 +200,7 @@ var AnimeClient = (function(w) {
delegateEvent(el, target, event, listener); delegateEvent(el, target, event, listener);
}); });
} }
} };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// ! Ajax // ! Ajax
@ -225,8 +225,8 @@ var AnimeClient = (function(w) {
pairs.push(`${name}=${value}`); pairs.push(`${name}=${value}`);
}); });
return pairs.join("&"); return pairs.join('&');
}; }
/** /**
* Make an ajax request * Make an ajax request
@ -255,7 +255,7 @@ var AnimeClient = (function(w) {
let request = new XMLHttpRequest(); let request = new XMLHttpRequest();
let method = String(config.type).toUpperCase(); let method = String(config.type).toUpperCase();
if (method === "GET") { if (method === 'GET') {
url += (url.match(/\?/)) url += (url.match(/\?/))
? ajaxSerialize(config.data) ? ajaxSerialize(config.data)
: `?${ajaxSerialize(config.data)}`; : `?${ajaxSerialize(config.data)}`;
@ -267,7 +267,7 @@ var AnimeClient = (function(w) {
if (request.readyState === 4) { if (request.readyState === 4) {
let responseText = ''; let responseText = '';
if (request.responseType == 'json') { if (request.responseType === 'json') {
responseText = JSON.parse(request.responseText); responseText = JSON.parse(request.responseText);
} else { } else {
responseText = request.responseText; responseText = request.responseText;
@ -291,7 +291,7 @@ var AnimeClient = (function(w) {
request.setRequestHeader('Content-Type', config.mimeType); request.setRequestHeader('Content-Type', config.mimeType);
switch (method) { switch (method) {
case "GET": case 'GET':
request.send(null); request.send(null);
break; break;
@ -308,7 +308,7 @@ var AnimeClient = (function(w) {
} }
return _.ajax(url, { return _.ajax(url, {
data: data, data,
success: callback success: callback
}); });
}; };

View File

@ -11,8 +11,8 @@
}); });
// Confirm deleting of list or library items // Confirm deleting of list or library items
ac.on('form.js-delete', 'submit', function (event) { ac.on('form.js-delete', 'submit', (event) => {
let proceed = confirm("Are you ABSOLUTELY SURE you want to delete this item?"); const proceed = confirm('Are you ABSOLUTELY SURE you want to delete this item?');
if (proceed === false) { if (proceed === false) {
event.preventDefault(); event.preventDefault();
@ -21,9 +21,9 @@
}); });
// Clear the api cache // Clear the api cache
ac.on('.js-clear-cache', 'click', function () { ac.on('.js-clear-cache', 'click', () => {
ac.get('/cache_purge', () => { ac.get('/cache_purge', () => {
ac.showMessage('success', `Sucessfully purged api cache`); ac.showMessage('success', 'Successfully purged api cache');
}); });
}); });

View File

@ -4,7 +4,7 @@
const search = (tempHtml, query) => { const search = (tempHtml, query) => {
_.$('.cssload-loader')[0].removeAttribute('hidden'); _.$('.cssload-loader')[0].removeAttribute('hidden');
_.get(_.url('/manga/search'), {'query':query,}, (searchResults, status) => { _.get(_.url('/manga/search'), {query}, (searchResults, status) => {
searchResults = JSON.parse(searchResults); searchResults = JSON.parse(searchResults);
_.$('.cssload-loader')[0].setAttribute('hidden', 'hidden'); _.$('.cssload-loader')[0].setAttribute('hidden', 'hidden');
@ -13,7 +13,7 @@
}); });
}; };
_.get('/public/templates/manga-ajax-search-results.html', tempHtml => { _.get('/public/templates/manga-ajax-search-results.html', (tempHtml) => {
_.on('#search', 'keyup', _.throttle(250, function(e) { _.on('#search', 'keyup', _.throttle(250, function(e) {
let query = encodeURIComponent(this.value); let query = encodeURIComponent(this.value);
if (query === '') { if (query === '') {

View File

@ -5,14 +5,14 @@
'use strict'; 'use strict';
_.on('.manga.list', 'click', '.edit_buttons button', e => { _.on('.manga.list', 'click', '.edit_buttons button', (e) => {
let this_sel = e.target; let thisSel = e.target;
let parent_sel = _.closestParent(e.target, 'article'); let parentSel = _.closestParent(e.target, 'article');
let manga_id = parent_sel.id.replace("manga-", ""); let mangaId = parentSel.id.replace('manga-', '');
let type = this_sel.classList.contains("plus_one_chapter") ? 'chapter' : 'volume'; let type = thisSel.classList.contains('plus_one_chapter') ? 'chapter' : 'volume';
let completed = parseInt(_.$(`.${type}s_read`, parent_sel)[0].textContent, 10); let completed = parseInt(_.$(`.${type}s_read`, parentSel)[0].textContent, 10);
let total = parseInt(_.$(`.${type}_count`, parent_sel)[0].textContent, 10); let total = parseInt(_.$(`.${type}_count`, parentSel)[0].textContent, 10);
let manga_name = _.$('.name', parent_sel)[0].textContent; let mangaName = _.$('.name', parentSel)[0].textContent;
if (isNaN(completed)) { if (isNaN(completed)) {
completed = 0; completed = 0;
@ -20,7 +20,7 @@
// Setup the update data // Setup the update data
let data = { let data = {
id: manga_id, id: mangaId,
data: { data: {
progress: completed progress: completed
} }
@ -33,7 +33,7 @@
} }
// If you increment at the last chapter, mark as completed // If you increment at the last chapter, mark as completed
if (( ! isNaN(completed)) && (completed + 1) == total) { if (( ! isNaN(completed)) && (completed + 1) === total) {
data.data.status = 'completed'; data.data.status = 'completed';
} }
@ -41,22 +41,21 @@
data.data.progress = ++completed; data.data.progress = ++completed;
_.ajax(_.url('/manga/update'), { _.ajax(_.url('/manga/update'), {
data: data, data,
dataType: 'json', dataType: 'json',
type: 'POST', type: 'POST',
mimeType: 'application/json', mimeType: 'application/json',
success: () => { success: () => {
if (data.data.status == 'completed') { if (data.data.status === 'completed') {
_.hide(parent_sel); _.hide(parentSel);
} }
_.$(`.${type}s_read`, parent_sel)[0].textContent = completed; _.$(`.${type}s_read`, parentSel)[0].textContent = completed;
_.showMessage('success', `Sucessfully updated ${manga_name}`); _.showMessage('success', `Sucessfully updated ${mangaName}`);
_.scrollToTop(); _.scrollToTop();
}, },
error: (xhr, errorType, error) => { error: () => {
console.error(error); _.showMessage('error', `Failed to updated ${mangaName}`);
_.showMessage('error', `Failed to updated ${manga_name}`);
_.scrollToTop(); _.scrollToTop();
} }
}); });

View File

@ -1,26 +1,30 @@
<?php <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* @package HummingbirdAnimeClient * PHP version 7
* @author Timothy J. Warren *
* @copyright Copyright (c) 2015 - 2016 * @package HummingbirdAnimeClient
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @author Timothy J. Warren <tim@timshomepage.net>
* @license MIT * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
namespace Aviat\EasyMin; namespace Aviat\EasyMin;
//Creative rewriting of /g/groupname to ?g=groupname //Creative rewriting of /g/groupname to ?g=groupname
$pi = $_SERVER['PATH_INFO']; $pi = $_SERVER['PATH_INFO'];
$pia = explode('/', $pi); $pia = explode('/', $pi);
$pia_len = count($pia); $piaLen = count($pia);
$i = 1; $i = 1;
while($i < $pia_len) while($i < $piaLen)
{ {
$j = $i+1; $j = $i+1;
$j = (isset($pia[$j])) ? $j : $i; $j = (isset($pia[$j])) ? $j : $i;
@ -38,7 +42,7 @@ class BaseMin {
* *
* @return int - timestamp to compare for cache control * @return int - timestamp to compare for cache control
*/ */
protected function get_if_modified() protected function getIfModified()
{ {
return (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) return (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER))
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
@ -50,7 +54,7 @@ class BaseMin {
* *
* @return string - the etag to compare * @return string - the etag to compare
*/ */
protected function get_if_none_match() protected function getIfNoneMatch()
{ {
return (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) return (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER))
? $_SERVER['HTTP_IF_NONE_MATCH'] ? $_SERVER['HTTP_IF_NONE_MATCH']
@ -62,9 +66,9 @@ class BaseMin {
* *
* @return boolean * @return boolean
*/ */
protected function is_not_debug() protected function isNotDebug()
{ {
return ! $this->is_debug_call(); return ! $this->isDebugCall();
} }
/** /**
@ -72,7 +76,7 @@ class BaseMin {
* *
* @return boolean * @return boolean
*/ */
protected function is_debug_call() protected function isDebugCall()
{ {
return array_key_exists('debug', $_GET); return array_key_exists('debug', $_GET);
} }
@ -81,24 +85,24 @@ class BaseMin {
* Send actual output to browser * Send actual output to browser
* *
* @param string $content - the body of the response * @param string $content - the body of the response
* @param string $mime_type - the content type * @param string $mimeType - the content type
* @param int $last_modified - the last modified date * @param int $lastModified - the last modified date
* @return void * @return void
*/ */
protected function send_final_output($content, $mime_type, $last_modified) protected function sendFinalOutput($content, $mimeType, $lastModified)
{ {
//This GZIPs the CSS for transmission to the user //This GZIPs the CSS for transmission to the user
//making file size smaller and transfer rate quicker //making file size smaller and transfer rate quicker
ob_start("ob_gzhandler"); ob_start("ob_gzhandler");
$expires = $last_modified + 691200; $expires = $lastModified + 691200;
$last_modified_date = gmdate('D, d M Y H:i:s', $last_modified); $lastModifiedDate = gmdate('D, d M Y H:i:s', $lastModified);
$expires_date = gmdate('D, d M Y H:i:s', $expires); $expiresDate = gmdate('D, d M Y H:i:s', $expires);
header("Content-Type: {$mime_type}; charset=utf8"); header("Content-Type: {$mimeType}; charset=utf8");
header("Cache-control: public, max-age=691200, must-revalidate"); header("Cache-control: public, max-age=691200, must-revalidate");
header("Last-Modified: {$last_modified_date} GMT"); header("Last-Modified: {$lastModifiedDate} GMT");
header("Expires: {$expires_date} GMT"); header("Expires: {$expiresDate} GMT");
echo $content; echo $content;

1979
public/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -207,6 +207,7 @@ class APIRequestBuilder {
* *
* @param string $type * @param string $type
* @param string $uri * @param string $uri
* @throws InvalidArgumentException
* @return self * @return self
*/ */
public function newRequest(string $type, string $uri): self public function newRequest(string $type, string $uri): self

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -18,6 +18,9 @@ namespace Aviat\AnimeClient\API;
use UnexpectedValueException; use UnexpectedValueException;
/**
* Exception for an API Request that fails validation
*/
class FailedResponseException extends UnexpectedValueException { class FailedResponseException extends UnexpectedValueException {
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -27,7 +27,7 @@ class JsonAPI {
* The full data array * The full data array
* *
* Basic structure is generally like so: * Basic structure is generally like so:
* @example [ * [
* 'id' => '12016665', * 'id' => '12016665',
* 'type' => 'libraryEntries', * 'type' => 'libraryEntries',
* 'links' => [ * 'links' => [

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -74,7 +74,7 @@ class Kitsu {
* @param string $endDate * @param string $endDate
* @return string * @return string
*/ */
public static function getAiringStatus(string $startDate = null, string $endDate = null): string public static function getAiringStatus(string $startDate = NULL, string $endDate = NULL): string
{ {
$startAirDate = new DateTimeImmutable($startDate ?? 'tomorrow'); $startAirDate = new DateTimeImmutable($startDate ?? 'tomorrow');
$endAirDate = new DateTimeImmutable($endDate ?? 'next year'); $endAirDate = new DateTimeImmutable($endDate ?? 'next year');
@ -83,7 +83,7 @@ class Kitsu {
$isDoneAiring = $now > $endAirDate; $isDoneAiring = $now > $endAirDate;
$isCurrentlyAiring = ($now > $startAirDate) && ! $isDoneAiring; $isCurrentlyAiring = ($now > $startAirDate) && ! $isDoneAiring;
switch (true) switch (TRUE)
{ {
case $isCurrentlyAiring: case $isCurrentlyAiring:
return AnimeAiringStatus::AIRING; return AnimeAiringStatus::AIRING;
@ -102,29 +102,29 @@ class Kitsu {
* @param string $hostname * @param string $hostname
* @return array * @return array
*/ */
protected static function getServiceMetaData(string $hostname = null): array protected static function getServiceMetaData(string $hostname = NULL): array
{ {
switch($hostname) switch($hostname)
{ {
case 'www.crunchyroll.com': case 'www.crunchyroll.com':
return [ return [
'name' => 'Crunchyroll', 'name' => 'Crunchyroll',
'link' => true, 'link' => TRUE,
'logo' => '<svg class="streaming-logo" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><g fill="#F78B24" fill-rule="evenodd"><path d="M22.549 49.145c-.815-.077-2.958-.456-3.753-.663-6.873-1.79-12.693-6.59-15.773-13.009C1.335 31.954.631 28.807.633 24.788c.003-4.025.718-7.235 2.38-10.686 1.243-2.584 2.674-4.609 4.706-6.66 3.8-3.834 8.614-6.208 14.067-6.936 1.783-.239 5.556-.161 7.221.148 3.463.642 6.571 1.904 9.357 3.797 5.788 3.934 9.542 9.951 10.52 16.861.21 1.48.332 4.559.19 4.816-.077.14-.117-.007-.167-.615-.25-3.015-1.528-6.66-3.292-9.388C40.253 7.836 30.249 4.32 20.987 7.467c-7.15 2.43-12.522 8.596-13.997 16.06-.73 3.692-.51 7.31.658 10.882a21.426 21.426 0 0 0 13.247 13.518c1.475.515 3.369.944 4.618 1.047 1.496.122 1.119.239-.727.224-1.006-.008-2.013-.032-2.237-.053z"></path><path d="M27.685 46.1c-7.731-.575-14.137-6.455-15.474-14.204-.243-1.41-.29-4.047-.095-5.345 1.16-7.706 6.97-13.552 14.552-14.639 1.537-.22 4.275-.143 5.746.162 1.28.266 2.7.737 3.814 1.266l.865.411-.814.392c-2.936 1.414-4.748 4.723-4.323 7.892.426 3.173 2.578 5.664 5.667 6.56 1.112.322 2.812.322 3.925 0 1.438-.417 2.566-1.1 3.593-2.173.346-.362.652-.621.68-.576.027.046.106.545.176 1.11.171 1.395.07 4.047-.204 5.371-.876 4.218-3.08 7.758-6.463 10.374-3.2 2.476-7.434 3.711-11.645 3.399z"></path></g></svg>' 'image' => 'streaming-logos/crunchyroll.svg',
]; ];
case 'www.funimation.com': case 'www.funimation.com':
return [ return [
'name' => 'Funimation', 'name' => 'Funimation',
'link' => true, 'link' => TRUE,
'logo' => '<svg class="streaming-logo" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><path d="M24.066.017a24.922 24.922 0 0 1 13.302 3.286 25.098 25.098 0 0 1 7.833 7.058 24.862 24.862 0 0 1 4.207 9.575c.82 4.001.641 8.201-.518 12.117a24.946 24.946 0 0 1-4.868 9.009 24.98 24.98 0 0 1-7.704 6.118 24.727 24.727 0 0 1-10.552 2.718A24.82 24.82 0 0 1 13.833 47.3c-5.815-2.872-10.408-8.107-12.49-14.25-2.162-6.257-1.698-13.375 1.303-19.28C5.483 8.07 10.594 3.55 16.602 1.435A24.94 24.94 0 0 1 24.066.017zm-8.415 33.31c.464 2.284 1.939 4.358 3.99 5.48 2.174 1.217 4.765 1.444 7.202 1.181 2.002-.217 3.986-.992 5.455-2.397 1.173-1.151 2.017-2.648 2.33-4.267-1.189-.027-2.378 0-3.566-.03-.568.082-1.137-.048-1.705.014-1.232.012-2.465.003-3.697-.01-.655.066-1.309-.035-1.963.013-1.166-.053-2.334.043-3.5-.025-1.515.08-3.03-.035-4.546.042z" fill="#411299" fill-rule="evenodd"></path></svg>' 'image' => 'streaming-logos/funimation.svg',
]; ];
case 'www.hulu.com': case 'www.hulu.com':
return [ return [
'name' => 'Hulu', 'name' => 'Hulu',
'link' => true, 'link' => TRUE,
'logo' => '<svg class="streaming-logo" viewBox="0 0 34 50" xmlns="http://www.w3.org/2000/svg"><path d="M22.222 13.889h-11.11V0H0v50h11.111V27.778c0-1.39 1.111-2.778 2.778-2.778h5.555c1.39 0 2.778 1.111 2.778 2.778V50h11.111V25c0-6.111-5-11.111-11.11-11.111z" fill="#8BC34A" fill-rule="evenodd"></path></svg>' 'image' => 'streaming-logos/hulu.svg',
]; ];
// Default to Netflix, because the API links are broken, // Default to Netflix, because the API links are broken,
@ -132,8 +132,8 @@ class Kitsu {
default: default:
return [ return [
'name' => 'Netflix', 'name' => 'Netflix',
'link' => false, 'link' => FALSE,
'logo' => '<svg class="streaming-logo" viewBox="0 0 26 50" xmlns="http://www.w3.org/2000/svg"><path d="M.057.258C2.518.253 4.982.263 7.446.253c2.858 7.76 5.621 15.556 8.456 23.324.523 1.441 1.003 2.897 1.59 4.312.078-9.209.01-18.42.034-27.631h7.763v46.36c-2.812.372-5.637.627-8.457.957-1.203-3.451-2.396-6.902-3.613-10.348-1.796-5.145-3.557-10.302-5.402-15.428.129 8.954.015 17.912.057 26.871-2.603.39-5.227.637-7.815 1.119C.052 33.279.06 16.768.057.258z" fill="#E21221" fill-rule="evenodd"></path></svg>' 'image' => 'streaming-logos/netflix.svg',
]; ];
} }
} }
@ -172,6 +172,7 @@ class Kitsu {
* Reorganize streaming links for the current list item * Reorganize streaming links for the current list item
* *
* @param array $included * @param array $included
* @param string $animeId
* @return array * @return array
*/ */
public static function parseListItemStreamingLinks(array $included, string $animeId): array public static function parseListItemStreamingLinks(array $included, string $animeId): array
@ -235,11 +236,11 @@ class Kitsu {
* @param array $existingTitles * @param array $existingTitles
* @return bool * @return bool
*/ */
private static function titleIsUnique(string $title = null, array $existingTitles): bool private static function titleIsUnique(string $title = NULL, array $existingTitles = []): bool
{ {
if (empty($title)) if (empty($title))
{ {
return false; return FALSE;
} }
foreach($existingTitles as $existing) foreach($existingTitles as $existing)
@ -248,12 +249,12 @@ class Kitsu {
$diff = levenshtein($existing, $title); $diff = levenshtein($existing, $title);
$onlydifferentCase = (mb_strtolower($existing) === mb_strtolower($title)); $onlydifferentCase = (mb_strtolower($existing) === mb_strtolower($title));
if ($diff < 3 || $isSubset || $onlydifferentCase) if ($diff < 3 OR $isSubset OR $onlydifferentCase)
{ {
return false; return FALSE;
} }
} }
return true; return TRUE;
} }
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -36,14 +36,14 @@ class Auth {
/** /**
* Anime API Model * Anime API Model
* *
* @var \Aviat\AnimeClient\API\Kitsu\Model * @var Model
*/ */
protected $model; protected $model;
/** /**
* Session object * Session object
* *
* @var Aura\Session\Segment * @var \Aura\Session\Segment
*/ */
protected $segment; protected $segment;
@ -102,7 +102,7 @@ class Auth {
* *
* @return boolean * @return boolean
*/ */
public function is_authenticated() public function isAuthenticated()
{ {
return ($this->get_auth_token() !== FALSE); return ($this->get_auth_token() !== FALSE);
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -16,8 +16,10 @@
namespace Aviat\AnimeClient\API\Kitsu; namespace Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\API\APIRequestBuilder; use Aviat\AnimeClient\API\{
use Aviat\AnimeClient\API\Kitsu as K; APIRequestBuilder,
Kitsu as K
};
use Aviat\Ion\Json; use Aviat\Ion\Json;
class KitsuRequestBuilder extends APIRequestBuilder { class KitsuRequestBuilder extends APIRequestBuilder {

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -65,7 +65,7 @@ trait KitsuTrait {
->get('session') ->get('session')
->getSegment(SESSION_SEGMENT); ->getSegment(SESSION_SEGMENT);
if ($sessionSegment->get('auth_token') !== null && $url !== K::AUTH_URL) if ($sessionSegment->get('auth_token') !== NULL && $url !== K::AUTH_URL)
{ {
$token = $sessionSegment->get('auth_token'); $token = $sessionSegment->get('auth_token');
$request = $request->setAuth('bearer', $token); $request = $request->setAuth('bearer', $token);
@ -104,14 +104,6 @@ trait KitsuTrait {
$response = wait((new Client)->request($request)); $response = wait((new Client)->request($request));
/* $logger->debug('Kitsu api response', [
'status' => $response->getStatus(),
'reason' => $response->getReason(),
'body' => $response->getBody(),
'headers' => $response->getAllHeaders(),
'requestHeaders' => $request->getAllHeaders(),
]); */
return $response; return $response;
} }
@ -125,7 +117,7 @@ trait KitsuTrait {
*/ */
private function request(string $type, string $url, array $options = []): array private function request(string $type, string $url, array $options = []): array
{ {
$logger = null; $logger = NULL;
if ($this->getContainer()) if ($this->getContainer())
{ {
$logger = $this->container->getLogger('kitsu-request'); $logger = $this->container->getLogger('kitsu-request');
@ -133,7 +125,7 @@ trait KitsuTrait {
$response = $this->getResponse($type, $url, $options); $response = $this->getResponse($type, $url, $options);
if ((int) $response->getStatus() > 299 || (int) $response->getStatus() < 200) if ((int) $response->getStatus() > 299 OR (int) $response->getStatus() < 200)
{ {
if ($logger) if ($logger)
{ {
@ -147,7 +139,7 @@ trait KitsuTrait {
/** /**
* Remove some boilerplate for get requests * Remove some boilerplate for get requests
* *
* @param array $args * @param mixed ...$args
* @return array * @return array
*/ */
protected function getRequest(...$args): array protected function getRequest(...$args): array
@ -158,7 +150,7 @@ trait KitsuTrait {
/** /**
* Remove some boilerplate for patch requests * Remove some boilerplate for patch requests
* *
* @param array $args * @param mixed ...$args
* @return array * @return array
*/ */
protected function patchRequest(...$args): array protected function patchRequest(...$args): array
@ -169,12 +161,12 @@ trait KitsuTrait {
/** /**
* Remove some boilerplate for post requests * Remove some boilerplate for post requests
* *
* @param array $args * @param mixed ...$args
* @return array * @return array
*/ */
protected function postRequest(...$args): array protected function postRequest(...$args): array
{ {
$logger = null; $logger = NULL;
if ($this->getContainer()) if ($this->getContainer())
{ {
$logger = $this->container->getLogger('kitsu-request'); $logger = $this->container->getLogger('kitsu-request');
@ -197,7 +189,7 @@ trait KitsuTrait {
/** /**
* Remove some boilerplate for delete requests * Remove some boilerplate for delete requests
* *
* @param array $args * @param mixed ...$args
* @return bool * @return bool
*/ */
protected function deleteRequest(...$args): bool protected function deleteRequest(...$args): bool

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -37,7 +37,7 @@ class ListItem extends AbstractListItem {
->get('session') ->get('session')
->getSegment(SESSION_SEGMENT); ->getSegment(SESSION_SEGMENT);
if ($sessionSegment->get('auth_token') !== null) if ( ! is_null($sessionSegment->get('auth_token')))
{ {
$token = $sessionSegment->get('auth_token'); $token = $sessionSegment->get('auth_token');
return "bearer {$token}"; return "bearer {$token}";

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -17,9 +17,11 @@
namespace Aviat\AnimeClient\API\Kitsu; namespace Aviat\AnimeClient\API\Kitsu;
use Amp\Artax\Request; use Amp\Artax\Request;
use Aviat\AnimeClient\API\CacheTrait; use Aviat\AnimeClient\API\{
use Aviat\AnimeClient\API\JsonAPI; CacheTrait,
use Aviat\AnimeClient\API\Kitsu as K; JsonAPI,
Kitsu as K
};
use Aviat\AnimeClient\API\Kitsu\Transformer\{ use Aviat\AnimeClient\API\Kitsu\Transformer\{
AnimeTransformer, AnimeTransformer,
AnimeListTransformer, AnimeListTransformer,
@ -68,7 +70,9 @@ class Model {
/** /**
* Constructor. * Constructor
*
* @param ListItem $listItem
*/ */
public function __construct(ListItem $listItem) public function __construct(ListItem $listItem)
{ {
@ -136,7 +140,7 @@ class Model {
return $data; return $data;
} }
return false; return FALSE;
} }
/** /**
@ -189,7 +193,7 @@ class Model {
} }
} }
return null; return NULL;
} }
/** /**
@ -233,6 +237,8 @@ class Model {
/** /**
* Get and transform the entirety of the user's anime list * Get and transform the entirety of the user's anime list
* *
* @param int $limit
* @param int $offset
* @return Request * @return Request
*/ */
public function getFullAnimeList(int $limit = 100, int $offset = 0): Request public function getFullAnimeList(int $limit = 100, int $offset = 0): Request

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -33,7 +33,6 @@ class AnimeListTransformer extends AbstractTransformer {
*/ */
public function transform($item) public function transform($item)
{ {
/* ?><pre><?= json_encode($item, \JSON_PRETTY_PRINT) ?></pre><?php */
$included = $item['included']; $included = $item['included'];
$animeId = $item['relationships']['media']['data']['id']; $animeId = $item['relationships']['media']['data']['id'];
$anime = $included['anime'][$animeId]; $anime = $included['anime'][$animeId];
@ -95,7 +94,7 @@ class AnimeListTransformer extends AbstractTransformer {
'rewatching' => (bool) $item['attributes']['reconsuming'], 'rewatching' => (bool) $item['attributes']['reconsuming'],
'rewatched' => (int) $item['attributes']['reconsumeCount'], 'rewatched' => (int) $item['attributes']['reconsumeCount'],
'user_rating' => ($rating === 0) ? '-' : (int) $rating, 'user_rating' => ($rating === 0) ? '-' : (int) $rating,
'private' => (bool) $item['attributes']['private'] ?? false, 'private' => (bool) $item['attributes']['private'] ?? FALSE,
]; ];
} }
@ -113,7 +112,7 @@ class AnimeListTransformer extends AbstractTransformer {
$untransformed = [ $untransformed = [
'id' => $item['id'], 'id' => $item['id'],
'mal_id' => $item['mal_id'] ?? null, 'mal_id' => $item['mal_id'] ?? NULL,
'data' => [ 'data' => [
'status' => $item['watching_status'], 'status' => $item['watching_status'],
'reconsuming' => $rewatching, 'reconsuming' => $rewatching,

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -35,18 +35,17 @@ class MangaListTransformer extends AbstractTransformer {
*/ */
public function transform($item) public function transform($item)
{ {
/*?><pre><?= print_r($item, TRUE) ?></pre><?php*/
$manga =& $item['manga']; $manga =& $item['manga'];
$rating = (is_numeric($item['attributes']['rating'])) $rating = (is_numeric($item['attributes']['rating']))
? intval(2 * $item['attributes']['rating']) ? intval(2 * $item['attributes']['rating'])
: '-'; : '-';
$total_chapters = ($manga['attributes']['chapterCount'] > 0) $totalChapters = ($manga['attributes']['chapterCount'] > 0)
? $manga['attributes']['chapterCount'] ? $manga['attributes']['chapterCount']
: '-'; : '-';
$total_volumes = ($manga['attributes']['volumeCount'] > 0) $totalVolumes = ($manga['attributes']['volumeCount'] > 0)
? $manga['attributes']['volumeCount'] ? $manga['attributes']['volumeCount']
: '-'; : '-';
@ -54,11 +53,11 @@ class MangaListTransformer extends AbstractTransformer {
'id' => $item['id'], 'id' => $item['id'],
'chapters' => [ 'chapters' => [
'read' => $item['attributes']['progress'], 'read' => $item['attributes']['progress'],
'total' => $total_chapters 'total' => $totalChapters
], ],
'volumes' => [ 'volumes' => [
'read' => '-', //$item['attributes']['volumes_read'], 'read' => '-', //$item['attributes']['volumes_read'],
'total' => $total_volumes 'total' => $totalVolumes
], ],
'manga' => [ 'manga' => [
'titles' => Kitsu::filterTitles($manga['attributes']), 'titles' => Kitsu::filterTitles($manga['attributes']),

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -58,7 +58,7 @@ class MangaTransformer extends AbstractTransformer {
]; ];
} }
private function count(int $value = null) private function count(int $value = NULL)
{ {
return ((int)$value === 0) return ((int)$value === 0)
? '-' ? '-'

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -73,7 +73,7 @@ class MAL {
'completed' => MangaReadingStatus::COMPLETED, 'completed' => MangaReadingStatus::COMPLETED,
'onhold' => MangaReadingStatus::ON_HOLD, 'onhold' => MangaReadingStatus::ON_HOLD,
'dropped' => MangaReadingStatus::DROPPED, 'dropped' => MangaReadingStatus::DROPPED,
'plantoread' => MangaReadingStatus::PLAN_TO_WATCH 'plantoread' => MangaReadingStatus::PLAN_TO_READ
]; ];
} }
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -118,7 +118,7 @@ trait MALTrait {
*/ */
private function getResponse(string $type, string $url, array $options = []) private function getResponse(string $type, string $url, array $options = [])
{ {
$logger = null; $logger = NULL;
if ($this->getContainer()) if ($this->getContainer())
{ {
$logger = $this->container->getLogger('mal-request'); $logger = $this->container->getLogger('mal-request');
@ -148,7 +148,7 @@ trait MALTrait {
*/ */
private function request(string $type, string $url, array $options = []): array private function request(string $type, string $url, array $options = []): array
{ {
$logger = null; $logger = NULL;
if ($this->getContainer()) if ($this->getContainer())
{ {
$logger = $this->container->getLogger('mal-request'); $logger = $this->container->getLogger('mal-request');
@ -156,7 +156,7 @@ trait MALTrait {
$response = $this->getResponse($type, $url, $options); $response = $this->getResponse($type, $url, $options);
if ((int) $response->getStatus() > 299 || (int) $response->getStatus() < 200) if ((int) $response->getStatus() > 299 OR (int) $response->getStatus() < 200)
{ {
if ($logger) if ($logger)
{ {
@ -170,7 +170,7 @@ trait MALTrait {
/** /**
* Remove some boilerplate for get requests * Remove some boilerplate for get requests
* *
* @param array $args * @param mixed ...$args
* @return array * @return array
*/ */
protected function getRequest(...$args): array protected function getRequest(...$args): array
@ -181,12 +181,12 @@ trait MALTrait {
/** /**
* Remove some boilerplate for post requests * Remove some boilerplate for post requests
* *
* @param array $args * @param mixed ...$args
* @return array * @return array
*/ */
protected function postRequest(...$args): array protected function postRequest(...$args): array
{ {
$logger = null; $logger = NULL;
if ($this->getContainer()) if ($this->getContainer())
{ {
$logger = $this->container->getLogger('mal-request'); $logger = $this->container->getLogger('mal-request');

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -34,9 +34,16 @@ class Model {
* @var AnimeListTransformer * @var AnimeListTransformer
*/ */
protected $animeListTransformer; protected $animeListTransformer;
/**
* @var ListItem
*/
protected $listItem;
/** /**
* MAL Model constructor. * MAL Model constructor.
*
* @param ListItem $listItem
*/ */
public function __construct(ListItem $listItem) public function __construct(ListItem $listItem)
{ {

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -24,7 +24,7 @@ use Aviat\Ion\Transformer\AbstractTransformer;
*/ */
class AnimeListTransformer extends AbstractTransformer { class AnimeListTransformer extends AbstractTransformer {
const statusMap = [ const STATUS_MAP = [
AnimeWatchingStatus::WATCHING => '1', AnimeWatchingStatus::WATCHING => '1',
AnimeWatchingStatus::COMPLETED => '2', AnimeWatchingStatus::COMPLETED => '2',
AnimeWatchingStatus::ON_HOLD => '3', AnimeWatchingStatus::ON_HOLD => '3',
@ -45,7 +45,7 @@ class AnimeListTransformer extends AbstractTransformer {
return [ return [
'id' => $item['mal_id'], 'id' => $item['mal_id'],
'data' => [ 'data' => [
'status' => self::statusMap[$item['watching_status']], 'status' => self::STATUS_MAP[$item['watching_status']],
'rating' => $item['user_rating'], 'rating' => $item['user_rating'],
'rewatch_value' => (int) $rewatching, 'rewatch_value' => (int) $rewatching,
'times_rewatched' => $item['rewatched'], 'times_rewatched' => $item['rewatched'],
@ -58,7 +58,7 @@ class AnimeListTransformer extends AbstractTransformer {
/** /**
* Transform Kitsu episode data to MAL episode data * Transform Kitsu episode data to MAL episode data
* *
* @param array $item * @param array $item
* @return array * @return array
*/ */
public function untransform(array $item): array public function untransform(array $item): array
@ -93,7 +93,7 @@ class AnimeListTransformer extends AbstractTransformer {
break; break;
case 'status': case 'status':
$map['data']['status'] = self::statusMap[$value]; $map['data']['status'] = self::STATUS_MAP[$value];
break; break;
default: default:

View File

@ -0,0 +1,82 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\API;
use Amp;
use Amp\Artax\Client;
/**
* Class to simplify making and validating simultaneous requests
*/
class ParallelAPIRequest {
/**
* Set of requests to make in parallel
*
* @var array
*/
protected $requests = [];
/**
* Add a request
*
* @param string|Request $request
* @param string|number $key
* @return self
*/
public function addRequest($request, $key = NULL): self
{
if ( ! is_null($key))
{
$this->requests[$key] = $request;
return $this;
}
$this->requests[] = $request;
return $this;
}
/**
* Add multiple requests
*
* @param string[]|Request[] $requests
* @return self
*/
public function addRequests(array $requests): self
{
array_walk($requests, [$this, 'addRequest']);
return $this;
}
/**
* Actually make the requests
*
* @param bool $allowFailingRequests
* @return array
*/
public function makeRequests(bool $allowFailingRequests = FALSE): array
{
$client = new Client();
$promises = $client->requestMulti($this->requests);
$func = ($allowFailingRequests) ? '\Amp\some' : '\Amp\all';
$results = Amp\wait($func($promises));
return $results;
}
}

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -39,6 +39,9 @@ class XML {
/** /**
* XML constructor * XML constructor
*
* @param string $xml
* @param array $data
*/ */
public function __construct(string $xml = '', array $data = []) public function __construct(string $xml = '', array $data = [])
{ {
@ -47,6 +50,8 @@ class XML {
/** /**
* Serialize the data to an xml string * Serialize the data to an xml string
*
* @return string
*/ */
public function __toString(): string public function __toString(): string
{ {
@ -67,7 +72,7 @@ class XML {
* Set the data to create xml from * Set the data to create xml from
* *
* @param array $data * @param array $data
* @return $this * @return self
*/ */
public function setData(array $data): self public function setData(array $data): self
{ {
@ -89,7 +94,7 @@ class XML {
* Set the xml to parse the data from * Set the xml to parse the data from
* *
* @param string $xml * @param string $xml
* @return $this * @return self
*/ */
public function setXML(string $xml): self public function setXML(string $xml): self
{ {
@ -161,20 +166,28 @@ class XML {
return static::toXML($this->getData()); return static::toXML($this->getData());
} }
/**
* Strip whitespace from raw xml to remove irrelevant text nodes
*
* @param string $xml
* @return string
*/
private static function stripXMLWhitespace(string $xml): string private static function stripXMLWhitespace(string $xml): string
{ {
// Get rid of unimportant text nodes by removing // Get rid of unimportant text nodes by removing
// whitespace characters from between xml tags, // whitespace characters from between xml tags,
// except for the xml declaration tag, Which looks // except for the xml declaration tag, Which looks
// something like: // something like:
/* <?xml version="1.0" encoding="UTF-8"?> */ /* <?xml version="1.0" encoding="UTF-8"?> */
return preg_replace('/([^\?])>\s+</', '$1><', $xml); return preg_replace('/([^\?])>\s+</', '$1><', $xml);
} }
/** /**
* Recursively create array structure based on xml structure * Recursively create array structure based on xml structure
* *
* @param array &$root A reference to the current array location * @param array $root A reference to the current array location
* @param DOMNodeList $nodeList The current NodeList object * @param DOMNodeList $nodeList The current NodeList object
* @return void * @return void
*/ */
@ -187,7 +200,7 @@ class XML {
$current =& $root[$el->nodeName]; $current =& $root[$el->nodeName];
// It's a top level element! // It's a top level element!
if (is_a($el->childNodes->item(0), 'DomText') || ( ! $el->hasChildNodes())) if (is_a($el->childNodes->item(0), 'DomText') OR ( ! $el->hasChildNodes()))
{ {
$current = $el->textContent; $current = $el->textContent;
continue; continue;

View File

@ -1,16 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
@ -28,6 +28,18 @@ const NOT_FOUND_METHOD = 'notFound';
const ERROR_MESSAGE_METHOD = 'errorPage'; const ERROR_MESSAGE_METHOD = 'errorPage';
const SRC_DIR = SRC_DIR; const SRC_DIR = SRC_DIR;
/**
* Joins paths together. Variadic to take an
* arbitrary number of arguments
*
* @param string[] ...$args
* @return string
*/
function _dir(...$args)
{
return implode(DIRECTORY_SEPARATOR, $args);
}
/** /**
* Load configuration options from .toml files * Load configuration options from .toml files
* *

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -72,7 +72,7 @@ class BaseCommand extends Command {
$config = loadToml($CONF_DIR); $config = loadToml($CONF_DIR);
$config_array = array_merge($base_config, $config); $config_array = array_merge($base_config, $config);
$di = function ($config_array) use ($APP_DIR) { $di = function ($config_array) {
$container = new Container(); $container = new Container();
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -21,7 +21,7 @@ namespace Aviat\AnimeClient\Command;
*/ */
class ClearCache extends BaseCommand { class ClearCache extends BaseCommand {
/** /**
* Run the image conversion script * Clear the API cache
* *
* @param array $args * @param array $args
* @param array $options * @param array $options

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -29,7 +29,16 @@ use Aviat\Ion\Json;
*/ */
class SyncKitsuWithMal extends BaseCommand { class SyncKitsuWithMal extends BaseCommand {
/**
* Model for making requests to Kitsu API
* @var \Aviat\AnimeClient\API\Kitsu\Model
*/
protected $kitsuModel; protected $kitsuModel;
/**
* Model for making requests to MAL API
* @var \Aviat\AnimeClient\API\MAL\Model
*/
protected $malModel; protected $malModel;
/** /**
@ -56,12 +65,11 @@ class SyncKitsuWithMal extends BaseCommand {
$data = $this->diffLists(); $data = $this->diffLists();
$this->echoBox("Number of items that need to be added to MAL: " . count($data)); $this->echoBox("Number of items that need to be added to MAL: " . count($data));
if (! empty($data['addToMAL'])) if ( ! empty($data['addToMAL']))
{ {
$this->echoBox("Adding missing list items to MAL"); $this->echoBox("Adding missing list items to MAL");
$this->createMALListItems($data['addToMAL']); $this->createMALListItems($data['addToMAL']);
} }
} }
public function getKitsuList() public function getKitsuList()
@ -80,7 +88,7 @@ class SyncKitsuWithMal extends BaseCommand {
} }
$promiseArray = (new Client())->requestMulti($requests); $promiseArray = (new Client())->requestMulti($requests);
$responses = wait(all($promiseArray)); $responses = wait(all($promiseArray));
$output = []; $output = [];
@ -89,7 +97,7 @@ class SyncKitsuWithMal extends BaseCommand {
$data = Json::decode($response->getBody()); $data = Json::decode($response->getBody());
$output = array_merge_recursive($output, $data); $output = array_merge_recursive($output, $data);
} }
return $output; return $output;
} }
@ -113,8 +121,6 @@ class SyncKitsuWithMal extends BaseCommand {
return $output; return $output;
} }
// 2015-05-20T23:48:47.731Z
public function formatMALList() public function formatMALList()
{ {
$orig = $this->getMALList(); $orig = $this->getMALList();
@ -155,7 +161,7 @@ class SyncKitsuWithMal extends BaseCommand {
{ {
$animeId = $listItem['relationships']['anime']['data']['id']; $animeId = $listItem['relationships']['anime']['data']['id'];
$potentialMappings = $includes['anime'][$animeId]['relationships']['mappings']; $potentialMappings = $includes['anime'][$animeId]['relationships']['mappings'];
$malId = null; $malId = NULL;
foreach ($potentialMappings as $mappingId) foreach ($potentialMappings as $mappingId)
{ {
@ -166,7 +172,7 @@ class SyncKitsuWithMal extends BaseCommand {
} }
// Skip to the next item if there isn't a MAL ID // Skip to the next item if there isn't a MAL ID
if ($malId === null) if (is_null($malId))
{ {
continue; continue;
} }
@ -238,11 +244,11 @@ class SyncKitsuWithMal extends BaseCommand {
$data = $transformer->untransform($item); $data = $transformer->untransform($item);
$requests[] = $this->malModel->createFullListItem($data); $requests[] = $this->malModel->createFullListItem($data);
} }
$promiseArray = (new Client())->requestMulti($requests); $promiseArray = (new Client())->requestMulti($requests);
$responses = wait(all($promiseArray)); $responses = wait(all($promiseArray));
foreach($responses as $key => $response) foreach($responses as $key => $response)
{ {
$id = $itemsToAdd[$key]['mal_id']; $id = $itemsToAdd[$key]['mal_id'];

View File

@ -1,16 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
@ -18,6 +18,8 @@ namespace Aviat\AnimeClient;
use const Aviat\AnimeClient\SESSION_SEGMENT; use const Aviat\AnimeClient\SESSION_SEGMENT;
use function Aviat\AnimeClient\_dir;
use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\View\{HtmlView, HttpView, JsonView}; use Aviat\Ion\View\{HtmlView, HttpView, JsonView};
use InvalidArgumentException; use InvalidArgumentException;
@ -33,13 +35,13 @@ class Controller {
/** /**
* Cache manager * Cache manager
* @var \Aviat\Ion\Cache\CacheInterface * @var \Psr\Cache\CacheItemPoolInterface
*/ */
protected $cache; protected $cache;
/** /**
* The global configuration object * The global configuration object
* @var Aviat\Ion\ConfigInterface $config * @var \Aviat\Ion\ConfigInterface $config
*/ */
protected $config; protected $config;
@ -69,7 +71,7 @@ class Controller {
/** /**
* Session segment * Session segment
* @var [type] * @var \Aura\Session\Segment
*/ */
protected $session; protected $session;
@ -77,7 +79,7 @@ class Controller {
* Common data to be sent to views * Common data to be sent to views
* @var array * @var array
*/ */
protected $base_data = [ protected $baseData = [
'url_type' => 'anime', 'url_type' => 'anime',
'other_type' => 'manga', 'other_type' => 'manga',
'menu_name' => '' 'menu_name' => ''
@ -97,24 +99,28 @@ class Controller {
$this->config = $container->get('config'); $this->config = $container->get('config');
$this->request = $container->get('request'); $this->request = $container->get('request');
$this->response = $container->get('response'); $this->response = $container->get('response');
$this->base_data['url'] = $auraUrlGenerator;
$this->base_data['urlGenerator'] = $urlGenerator; $this->baseData = array_merge((array)$this->baseData, [
$this->base_data['auth'] = $container->get('auth'); 'url' => $auraUrlGenerator,
$this->base_data['config'] = $this->config; 'urlGenerator' => $urlGenerator,
'auth' => $container->get('auth'),
'config' => $this->config
]);
$this->urlGenerator = $urlGenerator; $this->urlGenerator = $urlGenerator;
$session = $container->get('session'); $session = $container->get('session');
$this->session = $session->getSegment(SESSION_SEGMENT); $this->session = $session->getSegment(SESSION_SEGMENT);
// Set a 'previous' flash value for better redirects // Set a 'previous' flash value for better redirects
$server_params = $this->request->getServerParams(); $serverParams = $this->request->getServerParams();
if (array_key_exists('HTTP_REFERER', $server_params)) if (array_key_exists('HTTP_REFERER', $serverParams))
{ {
$this->session->setFlash('previous', $server_params['HTTP_REFERER']); $this->session->setFlash('previous', $serverParams['HTTP_REFERER']);
} }
// Set a message box if available // Set a message box if available
$this->base_data['message'] = $this->session->getFlash('message'); $this->baseData['message'] = $this->session->getFlash('message');
} }
/** /**
@ -124,8 +130,8 @@ class Controller {
*/ */
public function redirectToDefaultRoute() public function redirectToDefaultRoute()
{ {
$default_type = $this->config->get(['routes', 'route_config', 'default_list']); $defaultType = $this->config->get(['routes', 'route_config', 'default_list']);
$this->redirect($this->urlGenerator->default_url($default_type), 303); $this->redirect($this->urlGenerator->defaultUrl($defaultType), 303);
} }
/** /**
@ -133,7 +139,7 @@ class Controller {
* *
* @return void * @return void
*/ */
public function redirect_to_previous() public function redirectToPrevious()
{ {
$previous = $this->session->getFlash('previous'); $previous = $this->session->getFlash('previous');
$this->redirect($previous, 303); $this->redirect($previous, 303);
@ -145,31 +151,31 @@ class Controller {
* @param string|null $url * @param string|null $url
* @return void * @return void
*/ */
public function set_session_redirect($url = NULL) public function setSessionRedirect($url = NULL)
{ {
$server_params = $this->request->getServerParams(); $serverParams = $this->request->getServerParams();
if ( ! array_key_exists('HTTP_REFERER', $server_params)) if ( ! array_key_exists('HTTP_REFERER', $serverParams))
{ {
return; return;
} }
$util = $this->container->get('util'); $util = $this->container->get('util');
$double_form_page = $server_params['HTTP_REFERER'] === $this->request->getUri(); $doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri();
// Don't attempt to set the redirect url if // Don't attempt to set the redirect url if
// the page is one of the form type pages, // the page is one of the form type pages,
// and the previous page is also a form type page_segments // and the previous page is also a form type page_segments
if ($double_form_page) if ($doubleFormPage)
{ {
return; return;
} }
if (is_null($url)) if (is_null($url))
{ {
$url = $util->is_view_page() $url = $util->isViewPage()
? $this->request->url->get() ? $this->request->url->get()
: $server_params['HTTP_REFERER']; : $serverParams['HTTP_REFERER'];
} }
$this->session->set('redirect_url', $url); $this->session->set('redirect_url', $url);
@ -180,7 +186,7 @@ class Controller {
* *
* @return void * @return void
*/ */
public function session_redirect() public function sessionRedirect()
{ {
$target = $this->session->get('redirect_url'); $target = $this->session->get('redirect_url');
if (empty($target)) if (empty($target))
@ -221,27 +227,27 @@ class Controller {
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @return string * @return string
*/ */
protected function load_partial($view, $template, array $data = []) protected function loadPartial($view, $template, array $data = [])
{ {
$router = $this->container->get('dispatcher'); $router = $this->container->get('dispatcher');
if (isset($this->base_data)) if (isset($this->baseData))
{ {
$data = array_merge($this->base_data, $data); $data = array_merge($this->baseData, $data);
} }
$route = $router->getRoute(); $route = $router->getRoute();
$data['route_path'] = $route ? $router->getRoute()->path : ''; $data['route_path'] = $route ? $router->getRoute()->path : '';
$template_path = _dir($this->config->get('view_path'), "{$template}.php"); $templatePath = _dir($this->config->get('view_path'), "{$template}.php");
if ( ! is_file($template_path)) if ( ! is_file($templatePath))
{ {
throw new InvalidArgumentException("Invalid template : {$template}"); throw new InvalidArgumentException("Invalid template : {$template}");
} }
return $view->renderTemplate($template_path, (array)$data); return $view->renderTemplate($templatePath, (array)$data);
} }
/** /**
@ -252,17 +258,17 @@ class Controller {
* @param array $data * @param array $data
* @return void * @return void
*/ */
protected function render_full_page($view, $template, array $data) protected function renderFullPage($view, $template, array $data)
{ {
$view->appendOutput($this->load_partial($view, 'header', $data)); $view->appendOutput($this->loadPartial($view, 'header', $data));
if (array_key_exists('message', $data) && is_array($data['message'])) if (array_key_exists('message', $data) && is_array($data['message']))
{ {
$view->appendOutput($this->load_partial($view, 'message', $data['message'])); $view->appendOutput($this->loadPartial($view, 'message', $data['message']));
} }
$view->appendOutput($this->load_partial($view, $template, $data)); $view->appendOutput($this->loadPartial($view, $template, $data));
$view->appendOutput($this->load_partial($view, 'footer', $data)); $view->appendOutput($this->loadPartial($view, 'footer', $data));
} }
/** /**
@ -280,11 +286,11 @@ class Controller {
if ($status !== '') if ($status !== '')
{ {
$message = $this->show_message($view, 'error', $status); $message = $this->showMessage($view, 'error', $status);
} }
// Set the redirect url // Set the redirect url
$this->set_session_redirect(); $this->setSessionRedirect();
$this->outputHTML('login', [ $this->outputHTML('login', [
'title' => 'Api login', 'title' => 'Api login',
@ -303,10 +309,11 @@ class Controller {
$post = $this->request->getParsedBody(); $post = $this->request->getParsedBody();
if ($auth->authenticate($post['password'])) if ($auth->authenticate($post['password']))
{ {
return $this->session_redirect(); $this->sessionRedirect();
return;
} }
$this->set_flash_message('Invalid username or password.'); $this->setFlashMessage('Invalid username or password.');
$this->redirect($this->urlGenerator->url('login'), 303); $this->redirect($this->urlGenerator->url('login'), 303);
} }
@ -338,19 +345,19 @@ class Controller {
/** /**
* Display a generic error page * Display a generic error page
* *
* @param int $http_code * @param int $httpCode
* @param string $title * @param string $title
* @param string $message * @param string $message
* @param string $long_message * @param string $long_message
* @return void * @return void
*/ */
public function errorPage($http_code, $title, $message, $long_message = "") public function errorPage($httpCode, $title, $message, $long_message = "")
{ {
$this->outputHTML('error', [ $this->outputHTML('error', [
'title' => $title, 'title' => $title,
'message' => $message, 'message' => $message,
'long_message' => $long_message 'long_message' => $long_message
], NULL, $http_code); ], NULL, $httpCode);
} }
/** /**
@ -361,12 +368,21 @@ class Controller {
* @param string $type * @param string $type
* @return void * @return void
*/ */
public function set_flash_message($message, $type = "info") public function setFlashMessage($message, $type = "info")
{ {
$this->session->setFlash('message', [ static $messages;
if ( ! $messages)
{
$messages = [];
}
$messages[] = [
'message_type' => $type, 'message_type' => $type,
'message' => $message 'message' => $message
]); ];
$this->session->setFlash('message', $messages);
} }
/** /**
@ -393,7 +409,7 @@ class Controller {
*/ */
protected function showMessage($view, $type, $message) protected function showMessage($view, $type, $message)
{ {
return $this->load_partial($view, 'message', [ return $this->loadPartial($view, 'message', [
'message_type' => $type, 'message_type' => $type,
'message' => $message 'message' => $message
]); ]);
@ -416,7 +432,7 @@ class Controller {
} }
$view->setStatusCode($code); $view->setStatusCode($code);
$this->render_full_page($view, $template, $data); $this->renderFullPage($view, $template, $data);
} }
/** /**

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -39,13 +39,13 @@ class Anime extends BaseController {
/** /**
* Data to be sent to all routes in this controller * Data to be sent to all routes in this controller
* @var array $base_data * @var array $baseData
*/ */
protected $base_data; protected $baseData;
/** /**
* Data cache * Data cache
* @var Aviat\Ion\Cache\CacheInterface * @var \Psr\Cache\CachePoolInterface
*/ */
protected $cache; protected $cache;
@ -60,7 +60,7 @@ class Anime extends BaseController {
$this->model = $container->get('anime-model'); $this->model = $container->get('anime-model');
$this->base_data = array_merge($this->base_data, [ $this->baseData = array_merge($this->baseData, [
'menu_name' => 'anime_list', 'menu_name' => 'anime_list',
'url_type' => 'anime', 'url_type' => 'anime',
'other_type' => 'manga', 'other_type' => 'manga',
@ -79,16 +79,16 @@ class Anime extends BaseController {
*/ */
public function index($type = AnimeWatchingStatus::WATCHING, string $view = NULL) public function index($type = AnimeWatchingStatus::WATCHING, string $view = NULL)
{ {
$type_title_map = [ $typeTitleMap = [
'all' => 'All', 'all' => 'All',
AnimeWatchingStatus::WATCHING => 'Currently Watching', 'watching' => 'Currently Watching',
AnimeWatchingStatus::PLAN_TO_WATCH => 'Plan to Watch', 'plan_to_watch' => 'Plan to Watch',
AnimeWatchingStatus::ON_HOLD => 'On Hold', 'on_hold' => 'On Hold',
AnimeWatchingStatus::DROPPED => 'Dropped', 'dropped' => 'Dropped',
AnimeWatchingStatus::COMPLETED => 'Completed' 'completed' => 'Completed'
]; ];
$model_map = [ $modelMap = [
'watching' => AnimeWatchingStatus::WATCHING, 'watching' => AnimeWatchingStatus::WATCHING,
'plan_to_watch' => AnimeWatchingStatus::PLAN_TO_WATCH, 'plan_to_watch' => AnimeWatchingStatus::PLAN_TO_WATCH,
'on_hold' => AnimeWatchingStatus::ON_HOLD, 'on_hold' => AnimeWatchingStatus::ON_HOLD,
@ -97,21 +97,21 @@ class Anime extends BaseController {
'completed' => AnimeWatchingStatus::COMPLETED 'completed' => AnimeWatchingStatus::COMPLETED
]; ];
$title = (array_key_exists($type, $type_title_map)) $title = (array_key_exists($type, $typeTitleMap))
? $this->config->get('whose_list') . ? $this->config->get('whose_list') .
"'s Anime List &middot; {$type_title_map[$type]}" "'s Anime List &middot; {$typeTitleMap[$type]}"
: ''; : '';
$view_map = [ $viewMap = [
'' => 'cover', '' => 'cover',
'list' => 'list' 'list' => 'list'
]; ];
$data = ($type !== 'all') $data = ($type !== 'all')
? $this->model->getList($model_map[$type]) ? $this->model->getList($modelMap[$type])
: $this->model->get_all_lists(); : $this->model->get_all_lists();
$this->outputHTML('anime/' . $view_map[$view], [ $this->outputHTML('anime/' . $viewMap[$view], [
'title' => $title, 'title' => $title,
'sections' => $data 'sections' => $data
]); ]);
@ -122,7 +122,7 @@ class Anime extends BaseController {
* *
* @return void * @return void
*/ */
public function add_form() public function addForm()
{ {
$statuses = [ $statuses = [
AnimeWatchingStatus::WATCHING => 'Currently Watching', AnimeWatchingStatus::WATCHING => 'Currently Watching',
@ -132,7 +132,7 @@ class Anime extends BaseController {
AnimeWatchingStatus::COMPLETED => 'Completed' AnimeWatchingStatus::COMPLETED => 'Completed'
]; ];
$this->set_session_redirect(); $this->setSessionRedirect();
$this->outputHTML('anime/add', [ $this->outputHTML('anime/add', [
'title' => $this->config->get('whose_list') . 'title' => $this->config->get('whose_list') .
"'s Anime List &middot; Add", "'s Anime List &middot; Add",
@ -158,15 +158,15 @@ class Anime extends BaseController {
if ($result) if ($result)
{ {
$this->set_flash_message('Added new anime to list', 'success'); $this->setFlashMessage('Added new anime to list', 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to add new anime to list', 'error'); $this->setFlashMessage('Failed to add new anime to list', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -179,19 +179,19 @@ class Anime extends BaseController {
public function edit($id, $status = "all") public function edit($id, $status = "all")
{ {
$item = $this->model->getLibraryItem($id, $status); $item = $this->model->getLibraryItem($id, $status);
$raw_status_list = AnimeWatchingStatus::getConstList(); $rawStatusList = AnimeWatchingStatus::getConstList();
$statuses = []; $statuses = [];
foreach ($raw_status_list as $status_item) foreach ($rawStatusList as $statusItem)
{ {
$statuses[$status_item] = (string) $this->string($status_item) $statuses[$statusItem] = (string) $this->string($statusItem)
->underscored() ->underscored()
->humanize() ->humanize()
->titleize(); ->titleize();
} }
$this->set_session_redirect(); $this->setSessionRedirect();
$this->outputHTML('anime/edit', [ $this->outputHTML('anime/edit', [
'title' => $this->config->get('whose_list') . 'title' => $this->config->get('whose_list') .
@ -220,27 +220,27 @@ class Anime extends BaseController {
* *
* @return void * @return void
*/ */
public function form_update() public function formUpdate()
{ {
$data = $this->request->getParsedBody(); $data = $this->request->getParsedBody();
// Do some minor data manipulation for // Do some minor data manipulation for
// large form-based updates // large form-based updates
$transformer = new AnimeListTransformer(); $transformer = new AnimeListTransformer();
$post_data = $transformer->untransform($data); $postData = $transformer->untransform($data);
$full_result = $this->model->updateLibraryItem($post_data); $fullResult = $this->model->updateLibraryItem($postData);
if ($full_result['statusCode'] === 200) if ($fullResult['statusCode'] === 200)
{ {
$this->set_flash_message("Successfully updated.", 'success'); $this->setFlashMessage("Successfully updated.", 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to update anime.', 'error'); $this->setFlashMessage('Failed to update anime.', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -277,26 +277,26 @@ class Anime extends BaseController {
if ((bool)$response === TRUE) if ((bool)$response === TRUE)
{ {
$this->set_flash_message("Successfully deleted anime.", 'success'); $this->setFlashMessage("Successfully deleted anime.", 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to delete anime.', 'error'); $this->setFlashMessage('Failed to delete anime.', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
* View details of an anime * View details of an anime
* *
* @param string $anime_id * @param string $animeId
* @return void * @return void
*/ */
public function details($anime_id) public function details($animeId)
{ {
$data = $this->model->getAnime($anime_id); $data = $this->model->getAnime($animeId);
$this->outputHTML('anime/details', [ $this->outputHTML('anime/details', [
'title' => 'Anime &middot ' . $data['titles'][0], 'title' => 'Anime &middot ' . $data['titles'][0],

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -17,8 +17,10 @@
namespace Aviat\AnimeClient\Controller; namespace Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\Controller as BaseController; use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Model\Anime as AnimeModel; use Aviat\AnimeClient\Model\{
use Aviat\AnimeClient\Model\AnimeCollection as AnimeCollectionModel; Anime as AnimeModel,
AnimeCollection as AnimeCollectionModel
};
use Aviat\AnimeClient\UrlGenerator; use Aviat\AnimeClient\UrlGenerator;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
@ -29,21 +31,21 @@ class Collection extends BaseController {
/** /**
* The anime collection model * The anime collection model
* @var AnimeCollectionModel $anime_collection_model * @var AnimeCollectionModel $animeCollectionModel
*/ */
private $anime_collection_model; private $animeCollectionModel;
/** /**
* The anime API model * The anime API model
* @var AnimeModel $anime_model * @var AnimeModel $animeModel
*/ */
private $anime_model; private $animeModel;
/** /**
* Data to ve sent to all routes in this controller * Data to be sent to all routes in this controller
* @var array $base_data * @var array $baseData
*/ */
protected $base_data; protected $baseData;
/** /**
* Url Generator class * Url Generator class
@ -61,9 +63,9 @@ class Collection extends BaseController {
parent::__construct($container); parent::__construct($container);
$this->urlGenerator = $container->get('url-generator'); $this->urlGenerator = $container->get('url-generator');
$this->anime_model = $container->get('anime-model'); $this->animeModel = $container->get('anime-model');
$this->anime_collection_model = $container->get('anime-collection-model'); $this->animeCollectionModel = $container->get('anime-collection-model');
$this->base_data = array_merge($this->base_data, [ $this->baseData = array_merge($this->baseData, [
'menu_name' => 'collection', 'menu_name' => 'collection',
'url_type' => 'anime', 'url_type' => 'anime',
'other_type' => 'manga', 'other_type' => 'manga',
@ -80,7 +82,7 @@ class Collection extends BaseController {
{ {
$queryParams = $this->request->getQueryParams(); $queryParams = $this->request->getQueryParams();
$query = $queryParams['query']; $query = $queryParams['query'];
$this->outputJSON($this->anime_model->search($query)); $this->outputJSON($this->animeModel->search($query));
} }
/** /**
@ -91,17 +93,17 @@ class Collection extends BaseController {
*/ */
public function index($view) public function index($view)
{ {
$view_map = [ $viewMap = [
'' => 'cover', '' => 'cover',
'list' => 'list' 'list' => 'list'
]; ];
$data = $this->anime_collection_model->get_collection(); $data = $this->animeCollectionModel->getCollection();
$this->outputHTML('collection/' . $view_map[$view], [ $this->outputHTML('collection/' . $viewMap[$view], [
'title' => $this->config->get('whose_list') . "'s Anime Collection", 'title' => $this->config->get('whose_list') . "'s Anime Collection",
'sections' => $data, 'sections' => $data,
'genres' => $this->anime_collection_model->get_genre_list() 'genres' => $this->animeCollectionModel->getGenreList()
]); ]);
} }
@ -113,16 +115,16 @@ class Collection extends BaseController {
*/ */
public function form($id = NULL) public function form($id = NULL)
{ {
$this->set_session_redirect(); $this->setSessionRedirect();
$action = (is_null($id)) ? "Add" : "Edit"; $action = (is_null($id)) ? "Add" : "Edit";
$this->outputHTML('collection/' . strtolower($action), [ $this->outputHTML('collection/' . strtolower($action), [
'action' => $action, 'action' => $action,
'action_url' => $this->urlGenerator->full_url('collection/' . strtolower($action)), 'action_url' => $this->urlGenerator->fullUrl('collection/' . strtolower($action)),
'title' => $this->config->get('whose_list') . " Anime Collection &middot; {$action}", 'title' => $this->config->get('whose_list') . " Anime Collection &middot; {$action}",
'media_items' => $this->anime_collection_model->get_media_type_list(), 'media_items' => $this->animeCollectionModel->getMediaTypeList(),
'item' => ($action === "Edit") ? $this->anime_collection_model->get($id) : [] 'item' => ($action === "Edit") ? $this->animeCollectionModel->get($id) : []
]); ]);
} }
@ -136,15 +138,15 @@ class Collection extends BaseController {
$data = $this->request->getParsedBody(); $data = $this->request->getParsedBody();
if (array_key_exists('hummingbird_id', $data)) if (array_key_exists('hummingbird_id', $data))
{ {
$this->anime_collection_model->update($data); $this->animeCollectionModel->update($data);
$this->set_flash_message('Successfully updated collection item.', 'success'); $this->setFlashMessage('Successfully updated collection item.', 'success');
} }
else else
{ {
$this->set_flash_message('Failed to update collection item', 'error'); $this->setFlashMessage('Failed to update collection item', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -157,15 +159,15 @@ class Collection extends BaseController {
$data = $this->request->getParsedBody(); $data = $this->request->getParsedBody();
if (array_key_exists('id', $data)) if (array_key_exists('id', $data))
{ {
$this->anime_collection_model->add($data); $this->animeCollectionModel->add($data);
$this->set_flash_message('Successfully added collection item', 'success'); $this->setFlashMessage('Successfully added collection item', 'success');
} }
else else
{ {
$this->set_flash_message('Failed to add collection item.', 'error'); $this->setFlashMessage('Failed to add collection item.', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -181,8 +183,8 @@ class Collection extends BaseController {
$this->redirect("/collection/view", 303); $this->redirect("/collection/view", 303);
} }
$this->anime_collection_model->delete($data); $this->animeCollectionModel->delete($data);
$this->set_flash_message("Successfully removed anime from collection.", 'success'); $this->setFlashMessage("Successfully removed anime from collection.", 'success');
$this->redirect("/collection/view", 303); $this->redirect("/collection/view", 303);
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -39,9 +39,9 @@ class Manga extends Controller {
/** /**
* Data to ve sent to all routes in this controller * Data to ve sent to all routes in this controller
* @var array $base_data * @var array $baseData
*/ */
protected $base_data; protected $baseData;
/** /**
* Constructor * Constructor
@ -53,7 +53,7 @@ class Manga extends Controller {
parent::__construct($container); parent::__construct($container);
$this->model = $container->get('manga-model'); $this->model = $container->get('manga-model');
$this->base_data = array_merge($this->base_data, [ $this->baseData = array_merge($this->baseData, [
'menu_name' => 'manga_list', 'menu_name' => 'manga_list',
'config' => $this->config, 'config' => $this->config,
'url_type' => 'manga', 'url_type' => 'manga',
@ -101,7 +101,7 @@ class Manga extends Controller {
* *
* @return void * @return void
*/ */
public function add_form() public function addForm()
{ {
$raw_status_list = MangaReadingStatus::getConstList(); $raw_status_list = MangaReadingStatus::getConstList();
@ -115,7 +115,7 @@ class Manga extends Controller {
->titleize(); ->titleize();
} }
$this->set_session_redirect(); $this->setSessionRedirect();
$this->outputHTML('manga/add', [ $this->outputHTML('manga/add', [
'title' => $this->config->get('whose_list') . 'title' => $this->config->get('whose_list') .
"'s Manga List &middot; Add", "'s Manga List &middot; Add",
@ -141,15 +141,15 @@ class Manga extends Controller {
if ($result) if ($result)
{ {
$this->set_flash_message('Added new manga to list', 'success'); $this->setFlashMessage('Added new manga to list', 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to add new manga to list' . $result['body'], 'error'); $this->setFlashMessage('Failed to add new manga to list' . $result['body'], 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -161,7 +161,7 @@ class Manga extends Controller {
*/ */
public function edit($id, $status = "All") public function edit($id, $status = "All")
{ {
$this->set_session_redirect(); $this->setSessionRedirect();
$item = $this->model->getLibraryItem($id); $item = $this->model->getLibraryItem($id);
$title = $this->config->get('whose_list') . "'s Manga List &middot; Edit"; $title = $this->config->get('whose_list') . "'s Manga List &middot; Edit";
@ -190,7 +190,7 @@ class Manga extends Controller {
* *
* @return void * @return void
*/ */
public function form_update() public function formUpdate()
{ {
$data = $this->request->getParsedBody(); $data = $this->request->getParsedBody();
@ -202,16 +202,16 @@ class Manga extends Controller {
if ($full_result['statusCode'] === 200) if ($full_result['statusCode'] === 200)
{ {
$this->set_flash_message("Successfully updated manga.", 'success'); $this->setFlashMessage("Successfully updated manga.", 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to update manga.', 'error'); $this->setFlashMessage('Failed to update manga.', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**
@ -249,15 +249,15 @@ class Manga extends Controller {
if ($response) if ($response)
{ {
$this->set_flash_message("Successfully deleted manga.", 'success'); $this->setFlashMessage("Successfully deleted manga.", 'success');
$this->cache->clear(); $this->cache->clear();
} }
else else
{ {
$this->set_flash_message('Failed to delete manga.', 'error'); $this->setFlashMessage('Failed to delete manga.', 'error');
} }
$this->session_redirect(); $this->sessionRedirect();
} }
/** /**

View File

@ -1,16 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
@ -24,6 +24,8 @@ use const Aviat\AnimeClient\{
SRC_DIR SRC_DIR
}; };
use function Aviat\AnimeClient\_dir;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Friend; use Aviat\Ion\Friend;
@ -46,15 +48,15 @@ class Dispatcher extends RoutingBase {
/** /**
* Class wrapper for input superglobals * Class wrapper for input superglobals
* @var Psr\Http\Message\ServerRequestInterface * @var \Psr\Http\Message\ServerRequestInterface
*/ */
protected $request; protected $request;
/** /**
* Routes added to router * Routes added to router
* @var array $output_routes * @var array $outputRoutes
*/ */
protected $output_routes; protected $outputRoutes;
/** /**
* Constructor * Constructor
@ -68,7 +70,7 @@ class Dispatcher extends RoutingBase {
$this->matcher = $container->get('aura-router')->getMatcher(); $this->matcher = $container->get('aura-router')->getMatcher();
$this->request = $container->get('request'); $this->request = $container->get('request');
$this->output_routes = $this->_setupRoutes(); $this->outputRoutes = $this->setupRoutes();
} }
/** /**
@ -80,12 +82,12 @@ class Dispatcher extends RoutingBase {
{ {
$logger = $this->container->getLogger('default'); $logger = $this->container->getLogger('default');
$raw_route = $this->request->getUri()->getPath(); $rawRoute = $this->request->getUri()->getPath();
$route_path = "/" . trim($raw_route, '/'); $routePath = "/" . trim($rawRoute, '/');
$logger->info('Dispatcher - Routing data from get_route method'); $logger->info('Dispatcher - Routing data from get_route method');
$logger->info(print_r([ $logger->info(print_r([
'route_path' => $route_path 'route_path' => $routePath
], TRUE)); ], TRUE));
return $this->matcher->match($this->request); return $this->matcher->match($this->request);
@ -98,7 +100,7 @@ class Dispatcher extends RoutingBase {
*/ */
public function getOutputRoutes() public function getOutputRoutes()
{ {
return $this->output_routes; return $this->outputRoutes;
} }
/** /**
@ -131,10 +133,10 @@ class Dispatcher extends RoutingBase {
{ {
// If not route was matched, return an appropriate http // If not route was matched, return an appropriate http
// error message // error message
$error_route = $this->getErrorParams(); $errorRoute = $this->getErrorParams();
$controllerName = DEFAULT_CONTROLLER; $controllerName = DEFAULT_CONTROLLER;
$actionMethod = $error_route['action_method']; $actionMethod = $errorRoute['action_method'];
$params = $error_route['params']; $params = $errorRoute['params'];
} }
$this->call($controllerName, $actionMethod, $params); $this->call($controllerName, $actionMethod, $params);
@ -152,7 +154,7 @@ class Dispatcher extends RoutingBase {
{ {
if (array_key_exists('controller', $route->attributes)) if (array_key_exists('controller', $route->attributes))
{ {
$controller_name = $route->attributes['controller']; $controllerName = $route->attributes['controller'];
} }
else else
{ {
@ -160,13 +162,13 @@ class Dispatcher extends RoutingBase {
} }
// Get the full namespace for a controller if a short name is given // Get the full namespace for a controller if a short name is given
if (strpos($controller_name, '\\') === FALSE) if (strpos($controllerName, '\\') === FALSE)
{ {
$map = $this->getControllerList(); $map = $this->getControllerList();
$controller_name = $map[$controller_name]; $controllerName = $map[$controllerName];
} }
$action_method = (array_key_exists('action', $route->attributes)) $actionMethod = (array_key_exists('action', $route->attributes))
? $route->attributes['action'] ? $route->attributes['action']
: NOT_FOUND_METHOD; : NOT_FOUND_METHOD;
@ -186,8 +188,8 @@ class Dispatcher extends RoutingBase {
$logger->info(json_encode($params)); $logger->info(json_encode($params));
return [ return [
'controller_name' => $controller_name, 'controller_name' => $controllerName,
'action_method' => $action_method, 'action_method' => $actionMethod,
'params' => $params 'params' => $params
]; ];
} }
@ -199,16 +201,16 @@ class Dispatcher extends RoutingBase {
*/ */
public function getController() public function getController()
{ {
$route_type = $this->__get('default_list'); $routeType = $this->__get('default_list');
$request_uri = $this->request->getUri()->getPath(); $requestUri = $this->request->getUri()->getPath();
$path = trim($request_uri, '/'); $path = trim($requestUri, '/');
$segments = explode('/', $path); $segments = explode('/', $path);
$controller = reset($segments); $controller = reset($segments);
if (empty($controller)) if (empty($controller))
{ {
$controller = $route_type; $controller = $routeType;
} }
return $controller; return $controller;
@ -221,22 +223,22 @@ class Dispatcher extends RoutingBase {
*/ */
public function getControllerList() public function getControllerList()
{ {
$default_namespace = DEFAULT_CONTROLLER_NAMESPACE; $defaultNamespace = DEFAULT_CONTROLLER_NAMESPACE;
$path = str_replace('\\', '/', $default_namespace); $path = str_replace('\\', '/', $defaultNamespace);
$path = str_replace('Aviat/AnimeClient/', '', $path); $path = str_replace('Aviat/AnimeClient/', '', $path);
$path = trim($path, '/'); $path = trim($path, '/');
$actual_path = realpath(_dir(SRC_DIR, $path)); $actualPath = realpath(_dir(SRC_DIR, $path));
$class_files = glob("{$actual_path}/*.php"); $classFiles = glob("{$actualPath}/*.php");
$controllers = []; $controllers = [];
foreach ($class_files as $file) foreach ($classFiles as $file)
{ {
$raw_class_name = basename(str_replace(".php", "", $file)); $rawClassName = basename(str_replace(".php", "", $file));
$path = strtolower(basename($raw_class_name)); $path = strtolower(basename($rawClassName));
$class_name = trim($default_namespace . '\\' . $raw_class_name, '\\'); $className = trim($defaultNamespace . '\\' . $rawClassName, '\\');
$controllers[$path] = $class_name; $controllers[$path] = $className;
} }
return $controllers; return $controllers;
@ -260,6 +262,7 @@ class Dispatcher extends RoutingBase {
// Run the appropriate controller method // Run the appropriate controller method
$logger->debug('Dispatcher - controller arguments'); $logger->debug('Dispatcher - controller arguments');
$logger->debug(print_r($params, TRUE)); $logger->debug(print_r($params, TRUE));
call_user_func_array([$controller, $method], $params); call_user_func_array([$controller, $method], $params);
} }
@ -277,7 +280,7 @@ class Dispatcher extends RoutingBase {
$logger->info('Dispatcher - failed route'); $logger->info('Dispatcher - failed route');
$logger->info(print_r($failure, TRUE)); $logger->info(print_r($failure, TRUE));
$action_method = ERROR_MESSAGE_METHOD; $actionMethod = ERROR_MESSAGE_METHOD;
$params = []; $params = [];
@ -300,13 +303,13 @@ class Dispatcher extends RoutingBase {
default: default:
// Fall back to a 404 message // Fall back to a 404 message
$action_method = NOT_FOUND_METHOD; $actionMethod = NOT_FOUND_METHOD;
break; break;
} }
return [ return [
'params' => $params, 'params' => $params,
'action_method' => $action_method 'action_method' => $actionMethod
]; ];
} }
@ -315,9 +318,9 @@ class Dispatcher extends RoutingBase {
* *
* @return array * @return array
*/ */
protected function _setupRoutes() protected function setupRoutes()
{ {
$route_type = $this->getController(); $routeType = $this->getController();
// Add routes // Add routes
$routes = []; $routes = [];
@ -326,18 +329,18 @@ class Dispatcher extends RoutingBase {
$path = $route['path']; $path = $route['path'];
unset($route['path']); unset($route['path']);
$controller_map = $this->getControllerList(); $controllerMap = $this->getControllerList();
$controller_class = (array_key_exists($route_type, $controller_map)) $controllerClass = (array_key_exists($routeType, $controllerMap))
? $controller_map[$route_type] ? $controllerMap[$routeType]
: DEFAULT_CONTROLLER; : DEFAULT_CONTROLLER;
if (array_key_exists($route_type, $controller_map)) if (array_key_exists($routeType, $controllerMap))
{ {
$controller_class = $controller_map[$route_type]; $controllerClass = $controllerMap[$routeType];
} }
// Prepend the controller to the route parameters // Prepend the controller to the route parameters
$route['controller'] = $controller_class; $route['controller'] = $controllerClass;
// Select the appropriate router method based on the http verb // Select the appropriate router method based on the http verb
$add = (array_key_exists('verb', $route)) $add = (array_key_exists('verb', $route))

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -28,13 +28,13 @@ class Menu {
/** /**
* Create the html for the selected menu * Create the html for the selected menu
* *
* @param string $menu_name * @param string $menuName
* @return string * @return string
*/ */
public function __invoke($menu_name) public function __invoke($menuName)
{ {
$generator = new MenuGenerator($this->container); $generator = new MenuGenerator($this->container);
return $generator->generate($menu_name); return $generator->generate($menuName);
} }
} }

View File

@ -1,16 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
@ -33,14 +33,14 @@ class MenuGenerator extends UrlGenerator {
/** /**
* Html generation helper * Html generation helper
* *
* @var Aura\Html\HelperLocator * @var \Aura\Html\HelperLocator
*/ */
protected $helper; protected $helper;
/** /**
* Request object * Request object
* *
* @var Aura\Web\Request * @var \Psr\Http\Message\RequestInterface
*/ */
protected $request; protected $request;
@ -62,7 +62,7 @@ class MenuGenerator extends UrlGenerator {
* @param array $menus * @param array $menus
* @return array * @return array
*/ */
protected function parse_config(array $menus) protected function parseConfig(array $menus)
{ {
$parsed = []; $parsed = [];
@ -88,17 +88,17 @@ class MenuGenerator extends UrlGenerator {
public function generate($menu) public function generate($menu)
{ {
$menus = $this->config->get('menus'); $menus = $this->config->get('menus');
$parsed_config = $this->parse_config($menus); $parsedConfig = $this->parseConfig($menus);
// Bail out early on invalid menu // Bail out early on invalid menu
if ( ! $this->arr($parsed_config)->hasKey($menu)) if ( ! $this->arr($parsedConfig)->hasKey($menu))
{ {
return ''; return '';
} }
$menu_config = $parsed_config[$menu]; $menuConfig = $parsedConfig[$menu];
foreach ($menu_config as $title => $path) foreach ($menuConfig as $title => $path)
{ {
$has = $this->string($this->path())->contains($path); $has = $this->string($this->path())->contains($path);
$selected = ($has && strlen($this->path()) >= strlen($path)); $selected = ($has && strlen($this->path()) >= strlen($path));

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -16,54 +16,26 @@
namespace Aviat\AnimeClient\Model; namespace Aviat\AnimeClient\Model;
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Model;
/** /**
* Base model for api interaction * Base model for api interaction
*/ */
class API extends Model { class API extends AbstractModel {
use ContainerAware;
/**
* Config manager
* @var ConfigInterface
*/
protected $config;
/**
* Cache manager
* @var \Psr\Cache\CacheItemPoolInterface
*/
protected $cache;
/**
* Constructor
*
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->config = $container->get('config');
}
/** /**
* Sort the list entries by their title * Sort the list entries by their title
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @param array $array * @param array $array
* @param string $sort_key * @param string $sortKey
* @return void * @return void
*/ */
protected function sortByName(array &$array, string $sort_key) protected function sortByName(array &$array, string $sortKey)
{ {
$sort = []; $sort = [];
foreach ($array as $key => $item) foreach ($array as $key => $item)
{ {
$sort[$key] = $item[$sort_key]['titles'][0]; $sort[$key] = $item[$sortKey]['titles'][0];
} }
array_multisort($sort, SORT_ASC, $array); array_multisort($sort, SORT_ASC, $array);

View File

@ -0,0 +1,26 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Model;
use Aviat\Ion\StringWrapper;
/**
* Base class for Models
*/
abstract class AbstractModel {
use StringWrapper;
}

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -18,7 +18,9 @@ namespace Aviat\AnimeClient\Model;
use function Amp\some; use function Amp\some;
use function Amp\wait; use function Amp\wait;
use Amp\Artax\Client; use Amp\Artax\Client;
use Aviat\AnimeClient\API\ParallelAPIRequest;
use Aviat\AnimeClient\API\Kitsu\Enum\AnimeWatchingStatus; use Aviat\AnimeClient\API\Kitsu\Enum\AnimeWatchingStatus;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Json; use Aviat\Ion\Json;
@ -47,19 +49,34 @@ class Anime extends API {
AnimeWatchingStatus::COMPLETED => self::COMPLETED, AnimeWatchingStatus::COMPLETED => self::COMPLETED,
]; ];
/**
* Model for making requests to Kitsu API
*
* @var \Aviat\AnimeClient\API\Kitsu\Model
*/
protected $kitsuModel; protected $kitsuModel;
/**
* Model for making requests to MAL API
*
* @var \Aviat\AnimeClient\API\MAL\Model
*/
protected $malModel; protected $malModel;
/**
* Whether to use the MAL api
*
* @var boolean
*/
protected $useMALAPI; protected $useMALAPI;
/** /**
* Anime constructor. * Anime constructor.
*
* @param ContainerInterface $container * @param ContainerInterface $container
*/ */
public function __construct(ContainerInterface $container) { public function __construct(ContainerInterface $container)
parent::__construct($container); {
$config = $container->get('config'); $config = $container->get('config');
$this->kitsuModel = $container->get('kitsu-model'); $this->kitsuModel = $container->get('kitsu-model');
$this->malModel = $container->get('mal-model'); $this->malModel = $container->get('mal-model');
@ -137,7 +154,7 @@ class Anime extends API {
*/ */
public function createLibraryItem(array $data): bool public function createLibraryItem(array $data): bool
{ {
$requests = []; $requester = new ParallelAPIRequest();
if ($this->useMALAPI) if ($this->useMALAPI)
{ {
@ -147,15 +164,13 @@ class Anime extends API {
if ( ! is_null($malId)) if ( ! is_null($malId))
{ {
$malData['id'] = $malId; $malData['id'] = $malId;
$requests['mal'] = $this->malModel->createListItem($malData); $requester->addRequest($this->malModel->createListItem($malData), 'mal');
} }
} }
$requester->addRequest($this->kitsuModel->createListItem($data), 'kitsu');
$requests['kitsu'] = $this->kitsuModel->createListItem($data); $results = $requester->makeRequests(TRUE);
$promises = (new Client)->requestMulti($requests);
$results = wait(some($promises));
return count($results[1]) > 0; return count($results[1]) > 0;
} }
@ -168,18 +183,16 @@ class Anime extends API {
*/ */
public function updateLibraryItem(array $data): array public function updateLibraryItem(array $data): array
{ {
$requests = []; $requester = new ParallelAPIRequest();
if ($this->useMALAPI) if ($this->useMALAPI)
{ {
$requests['mal'] = $this->malModel->updateListItem($data); $requester->addRequest($this->malModel->updateListItem($data), 'mal');
} }
$requests['kitsu'] = $this->kitsuModel->updateListItem($data); $requester->addRequest($this->kitsuModel->updateListItem($data), 'kitsu');
$promises = (new Client)->requestMulti($requests);
$results = wait(some($promises)); $results = $requester->makeRequests(TRUE);
return [ return [
'body' => Json::decode($results[1]['kitsu']->getBody()), 'body' => Json::decode($results[1]['kitsu']->getBody()),
@ -194,18 +207,18 @@ class Anime extends API {
* @param string|null $malId * @param string|null $malId
* @return bool * @return bool
*/ */
public function deleteLibraryItem(string $id, string $malId = null): bool public function deleteLibraryItem(string $id, string $malId = NULL): bool
{ {
$requests = []; $requester = new ParallelAPIRequest();
if ($this->useMALAPI && ! is_null($malId)) if ($this->useMALAPI && ! is_null($malId))
{ {
$requests['mal'] = $this->malModel->deleteListItem($malId); $requester->addRequest($this->malModel->deleteListItem($malId), 'MAL');
} }
$requests['kitsu'] = $this->kitsuModel->deleteListItem($id); $requester->addRequest($this->kitsuModel->deleteListItem($id), 'kitsu');
$results = wait(some((new Client)->requestMulti($requests))); $results = $requester->makeRequests(TRUE);
return count($results[1]) > 0; return count($results[1]) > 0;
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -31,13 +31,13 @@ class AnimeCollection extends Collection {
* *
* @return array * @return array
*/ */
public function get_collection() public function getCollection()
{ {
$raw_collection = $this->_get_collection(); $rawCollection = $this->getCollectionFromDatabase();
$collection = []; $collection = [];
foreach ($raw_collection as $row) foreach ($rawCollection as $row)
{ {
if (array_key_exists($row['media'], $collection)) if (array_key_exists($row['media'], $collection))
{ {
@ -57,7 +57,7 @@ class AnimeCollection extends Collection {
* *
* @return array * @return array
*/ */
public function get_media_type_list() public function getMediaTypeList()
{ {
$output = []; $output = [];
@ -79,7 +79,7 @@ class AnimeCollection extends Collection {
* @param int $id * @param int $id
* @return array * @return array
*/ */
public function get_collection_entry($id) public function getCollectionEntry($id)
{ {
$query = $this->db->from('anime_set') $query = $this->db->from('anime_set')
->where('hummingbird_id', (int)$id) ->where('hummingbird_id', (int)$id)
@ -93,9 +93,9 @@ class AnimeCollection extends Collection {
* *
* @return array * @return array
*/ */
private function _get_collection() private function getCollectionFromDatabase()
{ {
if ( ! $this->valid_database) if ( ! $this->validDatabase)
{ {
return []; return [];
} }
@ -119,9 +119,7 @@ class AnimeCollection extends Collection {
*/ */
public function add($data) public function add($data)
{ {
$anime = (object)$this->anime_model->getAnimeById($data['id']); $anime = (object)$this->animeModel->getAnimeById($data['id']);
$util = $this->container->get('util');
$this->db->set([ $this->db->set([
'hummingbird_id' => $data['id'], 'hummingbird_id' => $data['id'],
'slug' => $anime->slug, 'slug' => $anime->slug,
@ -136,7 +134,7 @@ class AnimeCollection extends Collection {
'notes' => $data['notes'] 'notes' => $data['notes']
])->insert('anime_set'); ])->insert('anime_set');
$this->update_genre($data['id']); $this->updateGenre($data['id']);
} }
/** /**
@ -185,13 +183,13 @@ class AnimeCollection extends Collection {
/** /**
* Get the details of a collection item * Get the details of a collection item
* *
* @param int $hummingbird_id * @param int $kitsuId
* @return array * @return array
*/ */
public function get($hummingbird_id) public function get($kitsuId)
{ {
$query = $this->db->from('anime_set') $query = $this->db->from('anime_set')
->where('hummingbird_id', $hummingbird_id) ->where('hummingbird_id', $kitsuId)
->get(); ->get();
return $query->fetch(PDO::FETCH_ASSOC); return $query->fetch(PDO::FETCH_ASSOC);
@ -200,16 +198,16 @@ class AnimeCollection extends Collection {
/** /**
* Update genre information for selected anime * Update genre information for selected anime
* *
* @param int $anime_id The current anime * @param int $animeId The current anime
* @return void * @return void
*/ */
private function update_genre($anime_id) private function updateGenre($animeId)
{ {
$genre_info = $this->get_genre_data(); $genreInfo = $this->getGenreData();
extract($genre_info); extract($genreInfo);
// Get api information // Get api information
$anime = $this->anime_model->getAnimeById($anime_id); $anime = $this->animeModel->getAnimeById($animeId);
foreach ($anime['genres'] as $genre) foreach ($anime['genres'] as $genre)
{ {
@ -224,23 +222,23 @@ class AnimeCollection extends Collection {
// Update link table // Update link table
// Get id of genre to put in link table // Get id of genre to put in link table
$flipped_genres = array_flip($genres); $flippedGenres = array_flip($genres);
$insert_array = [ $insertArray = [
'hummingbird_id' => $anime_id, 'hummingbird_id' => $animeId,
'genre_id' => $flipped_genres[$genre] 'genre_id' => $flippedGenres[$genre]
]; ];
if (array_key_exists($anime_id, $links)) if (array_key_exists($animeId, $links))
{ {
if ( ! in_array($flipped_genres[$genre], $links[$anime_id])) if ( ! in_array($flippedGenres[$genre], $links[$animeId]))
{ {
$this->db->set($insert_array)->insert('genre_anime_set_link'); $this->db->set($insertArray)->insert('genre_anime_set_link');
} }
} }
else else
{ {
$this->db->set($insert_array)->insert('genre_anime_set_link'); $this->db->set($insertArray)->insert('genre_anime_set_link');
} }
} }
} }
@ -250,7 +248,7 @@ class AnimeCollection extends Collection {
* *
* @return array * @return array
*/ */
private function get_genre_data() private function getGenreData()
{ {
$genres = []; $genres = [];
$links = []; $links = [];
@ -285,21 +283,5 @@ class AnimeCollection extends Collection {
'links' => $links 'links' => $links
]; ];
} }
/**
* Update genre information for the entire collection
*
* @return void
*/
private function update_genres()
{
// Get the anime collection
$collection = $this->_get_collection();
foreach ($collection as $anime)
{
// Get api information
$this->update_genre($anime['hummingbird_id']);
}
}
} }
// End of AnimeCollectionModel.php // End of AnimeCollectionModel.php

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -16,10 +16,8 @@
namespace Aviat\AnimeClient\Model; namespace Aviat\AnimeClient\Model;
use Aviat\AnimeClient\Model\DB;
use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Model\DB;
use PDO; use PDO;
use PDOException; use PDOException;
@ -32,15 +30,15 @@ class Collection extends DB {
/** /**
* Anime API Model * Anime API Model
* @var object $anime_model * @var object $animeModel
*/ */
protected $anime_model; protected $animeModel;
/** /**
* Whether the database is valid for querying * Whether the database is valid for querying
* @var boolean * @var boolean
*/ */
protected $valid_database = FALSE; protected $validDatabase = FALSE;
/** /**
* Create a new collection object * Create a new collection object
@ -48,41 +46,39 @@ class Collection extends DB {
* @param ContainerInterface $container * @param ContainerInterface $container
*/ */
public function __construct(ContainerInterface $container) public function __construct(ContainerInterface $container)
{ {
$this->container = $container; parent::__construct($container);
parent::__construct($container->get('config'));
try try
{ {
$this->db = \Query($this->db_config['collection']); $this->db = \Query($this->dbConfig['collection']);
} }
catch (PDOException $e) catch (PDOException $e)
{ {
//$this->valid_database = FALSE; //$this->validDatabase = FALSE;
//return FALSE; //return FALSE;
} }
$this->anime_model = $container->get('anime-model'); $this->animeModel = $container->get('anime-model');
// Is database valid? If not, set a flag so the // Is database valid? If not, set a flag so the
// app can be run without a valid database // app can be run without a valid database
if ($this->db_config['collection']['type'] === 'sqlite') if ($this->dbConfig['collection']['type'] === 'sqlite')
{ {
$db_file_name = $this->db_config['collection']['file']; $dbFileName = $this->dbConfig['collection']['file'];
if ($db_file_name !== ':memory:' && file_exists($db_file_name)) if ($dbFileName !== ':memory:' && file_exists($dbFileName))
{ {
$db_file = file_get_contents($db_file_name); $dbFile = file_get_contents($dbFileName);
$this->valid_database = (strpos($db_file, 'SQLite format 3') === 0); $this->validDatabase = (strpos($dbFile, 'SQLite format 3') === 0);
} }
else else
{ {
$this->valid_database = FALSE; $this->validDatabase = FALSE;
} }
} }
else else
{ {
$this->valid_database = TRUE; $this->validDatabase = TRUE;
} }
} }
@ -92,7 +88,7 @@ class Collection extends DB {
* @param array $filter * @param array $filter
* @return array * @return array
*/ */
public function get_genre_list($filter = []) public function getGenreList($filter = [])
{ {
$this->db->select('hummingbird_id, genre') $this->db->select('hummingbird_id, genre')
->from('genre_anime_set_link gl') ->from('genre_anime_set_link gl')

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -16,14 +16,13 @@
namespace Aviat\AnimeClient\Model; namespace Aviat\AnimeClient\Model;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Model;
/** /**
* Base model for database interaction * Base model for database interaction
*/ */
class DB extends Model { class DB extends AbstractModel {
use \Aviat\Ion\Di\ContainerAware; use ContainerAware;
/** /**
* The query builder object * The query builder object
@ -33,9 +32,9 @@ class DB extends Model {
/** /**
* The database connection information array * The database connection information array
* @var array $db_config * @var array $dbConfig
*/ */
protected $db_config; protected $dbConfig = [];
/** /**
* Constructor * Constructor
@ -44,7 +43,7 @@ class DB extends Model {
*/ */
public function __construct(ContainerInterface $container) public function __construct(ContainerInterface $container)
{ {
$this->db_config = $container->get('config')->get('database'); $this->dbConfig = $container->get('config')->get('database');
$this->setContainer($container); $this->setContainer($container);
} }
} }

View File

@ -1,12 +1,12 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Anime List Client * Hummingbird Anime List Client
* *
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package AnimeListClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2017 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -36,7 +36,7 @@ class Manga extends API
* Map API constants to display constants * Map API constants to display constants
* @var array * @var array
*/ */
protected $const_map = [ protected $constMap = [
MangaReadingStatus::READING => self::READING, MangaReadingStatus::READING => self::READING,
MangaReadingStatus::PLAN_TO_READ => self::PLAN_TO_READ, MangaReadingStatus::PLAN_TO_READ => self::PLAN_TO_READ,
MangaReadingStatus::ON_HOLD => self::ON_HOLD, MangaReadingStatus::ON_HOLD => self::ON_HOLD,
@ -44,7 +44,11 @@ class Manga extends API
MangaReadingStatus::COMPLETED => self::COMPLETED MangaReadingStatus::COMPLETED => self::COMPLETED
]; ];
protected $status_map = [ /**
* Maps url segments to their title equivalents
* @var array
*/
protected $statusMap = [
'current' => self::READING, 'current' => self::READING,
'planned' => self::PLAN_TO_READ, 'planned' => self::PLAN_TO_READ,
'completed' => self::COMPLETED, 'completed' => self::COMPLETED,
@ -53,15 +57,26 @@ class Manga extends API
]; ];
/** /**
* @var Aviat\AnimeClient\API\Kitsu\KitsuModel * Model for making requests to Kitsu API
* @var \Aviat\AnimeClient\API\Kitsu\Model
*/ */
protected $kitsuModel; protected $kitsuModel;
/**
* Model for making requests to MAL API
* @var \Aviat\AnimeClient\API\MAL\Model
*/
protected $malModel;
/**
* Constructor
*
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container) public function __construct(ContainerInterface $container)
{ {
parent::__construct($container);
$this->kitsuModel = $container->get('kitsu-model'); $this->kitsuModel = $container->get('kitsu-model');
$this->malModel = $container->get('mal-model');
} }
/** /**
@ -72,7 +87,7 @@ class Manga extends API
*/ */
public function getList($status) public function getList($status)
{ {
$APIstatus = array_flip($this->const_map)[$status]; $APIstatus = array_flip($this->constMap)[$status];
$data = $this->kitsuModel->getMangaList($APIstatus); $data = $this->kitsuModel->getMangaList($APIstatus);
return $this->mapByStatus($data)[$status]; return $this->mapByStatus($data)[$status];
} }
@ -161,7 +176,7 @@ class Manga extends API
]; ];
foreach ($data as &$entry) { foreach ($data as &$entry) {
$key = $this->status_map[$entry['reading_status']]; $key = $this->statusMap[$entry['reading_status']];
$output[$key][] = $entry; $output[$key][] = $entry;
} }

View File

@ -1,29 +1,30 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
namespace Aviat\AnimeClient; namespace Aviat\AnimeClient;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\StringWrapper;
/** /**
* Base for routing/url classes * Base for routing/url classes
*/ */
class RoutingBase { class RoutingBase {
use \Aviat\Ion\StringWrapper; use StringWrapper;
/** /**
* Injection Container * Injection Container
@ -33,7 +34,7 @@ class RoutingBase {
/** /**
* Config Object * Config Object
* @var Config * @var \Aviat\Ion\Config
*/ */
protected $config; protected $config;
@ -47,7 +48,7 @@ class RoutingBase {
* Route configuration options * Route configuration options
* @var array * @var array
*/ */
protected $route_config; protected $routeConfig;
/** /**
* Constructor * Constructor
@ -58,9 +59,9 @@ class RoutingBase {
{ {
$this->container = $container; $this->container = $container;
$this->config = $container->get('config'); $this->config = $container->get('config');
$base_routes = $this->config->get('routes'); $baseRoutes = $this->config->get('routes');
$this->routes = $base_routes['routes']; $this->routes = $baseRoutes['routes'];
$this->route_config = $base_routes['route_config']; $this->routeConfig = $baseRoutes['route_config'];
} }
/** /**
@ -71,11 +72,11 @@ class RoutingBase {
*/ */
public function __get($key) public function __get($key)
{ {
$routing_config =& $this->route_config; $routingConfig =& $this->routeConfig;
if (array_key_exists($key, $routing_config)) if (array_key_exists($key, $routingConfig))
{ {
return $routing_config[$key]; return $routingConfig[$key];
} }
} }
@ -88,13 +89,13 @@ class RoutingBase {
{ {
$request = $this->container->get('request'); $request = $this->container->get('request');
$path = $request->getUri()->getPath(); $path = $request->getUri()->getPath();
$cleaned_path = $this->string($path) $cleanedPath = $this->string($path)
->replace('%20', '') ->replace('%20', '')
->trim() ->trim()
->trimRight('/') ->trimRight('/')
->ensureLeft('/'); ->ensureLeft('/');
return (string)$cleaned_path; return (string)$cleanedPath;
} }
/** /**
@ -114,7 +115,7 @@ class RoutingBase {
* @param int $num * @param int $num
* @return string|null * @return string|null
*/ */
public function get_segment($num) public function getSegment($num)
{ {
$segments = $this->segments(); $segments = $this->segments();
return (array_key_exists($num, $segments)) ? $segments[$num] : NULL; return (array_key_exists($num, $segments)) ? $segments[$num] : NULL;
@ -125,7 +126,7 @@ class RoutingBase {
* *
* @return string * @return string
*/ */
public function last_segment() public function lastSegment()
{ {
$segments = $this->segments(); $segments = $this->segments();
return end($segments); return end($segments);

View File

@ -1,22 +1,23 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
/** /**
* Hummingbird Anime Client * Hummingbird Anime List Client
* *
* An API client for Hummingbird to manage anime and manga watch lists * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
* *
* PHP version 7 * PHP version 7
* *
* @package HummingbirdAnimeClient * @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net> * @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren * @copyright 2015 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.1 * @version 4.0
* @link https://github.com/timw4mail/HummingBirdAnimeClient * @link https://github.com/timw4mail/HummingBirdAnimeClient
*/ */
namespace Aviat\AnimeClient; namespace Aviat\AnimeClient;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
use InvalidArgumentException;
/** /**
* UrlGenerator class. * UrlGenerator class.
@ -43,42 +44,26 @@ class UrlGenerator extends RoutingBase {
/** /**
* Get the base url for css/js/images * Get the base url for css/js/images
* *
* @param string ...$args url segments to apend to the base asset url
* @return string * @return string
*/ */
public function asset_url() public function assetUrl(...$args): string
{ {
$args = func_get_args(); $baseUrl = rtrim($this->url(""), '/');
$base_url = rtrim($this->url(""), '/'); $baseUrl = "{$baseUrl}" . $this->__get("asset_path");
$base_url = "{$base_url}" . $this->__get("asset_path"); array_unshift($args, $baseUrl);
array_unshift($args, $base_url);
return implode("/", $args); return implode("/", $args);
} }
/**
* Get the base url from the config
*
* @param string $type - (optional) The controller
* @return string
*/
public function base_url($type = "anime")
{
$config_path = trim($this->__get("{$type}_path"), "/");
$path = ($config_path !== '') ? $config_path : "";
return implode("/", ['/', $this->host, $path]);
}
/** /**
* Generate a proper url from the path * Generate a proper url from the path
* *
* @param string $path * @param string $path
* @return string * @return string
*/ */
public function url($path) public function url(string $path): string
{ {
$path = trim($path, '/'); $path = trim($path, '/');
@ -108,20 +93,20 @@ class UrlGenerator extends RoutingBase {
* Full default path for the list pages * Full default path for the list pages
* *
* @param string $type * @param string $type
* @throws \InvalidArgumentException * @throws InvalidArgumentException
* @return string * @return string
*/ */
public function default_url($type) public function defaultUrl(string $type): string
{ {
$type = trim($type); $type = trim($type);
$default_path = $this->__get("default_{$type}_list_path"); $defaultPath = $this->__get("default_{$type}_list_path");
if ( ! is_null($default_path)) if ( ! is_null($defaultPath))
{ {
return $this->url("{$type}/{$default_path}"); return $this->url("{$type}/{$defaultPath}");
} }
throw new \InvalidArgumentException("Invalid default type: '{$type}'"); throw new InvalidArgumentException("Invalid default type: '{$type}'");
} }
/** /**
@ -131,9 +116,9 @@ class UrlGenerator extends RoutingBase {
* @param string $type - (optional) The controller (anime or manga), defaults to anime * @param string $type - (optional) The controller (anime or manga), defaults to anime
* @return string * @return string
*/ */
public function full_url($path = "", $type = "anime") public function fullUrl(string $path = "", string $type = "anime"): string
{ {
$config_default_route = $this->__get("default_{$type}_path"); $configDefaultRoute = $this->__get("default_{$type}_path");
// Remove beginning/trailing slashes // Remove beginning/trailing slashes
$path = trim($path, '/'); $path = trim($path, '/');
@ -141,7 +126,7 @@ class UrlGenerator extends RoutingBase {
// Set the default view // Set the default view
if ($path === '') if ($path === '')
{ {
$path .= trim($config_default_route, '/'); $path .= trim($configDefaultRoute, '/');
if ($this->__get('default_to_list_view')) if ($this->__get('default_to_list_view'))
{ {
$path .= '/list'; $path .= '/list';

Some files were not shown because too many files have changed in this diff Show More