Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
43 changed files with 230 additions and 297 deletions
Showing only changes of commit f3c85da8cc - Show all commits

View File

@ -20,5 +20,3 @@ host = "127.0.0.1"
# Database number
database = 2
[options]

View File

@ -2,7 +2,7 @@
<main>
<h2>Edit Anime Collection Item</h2>
<form action="<?= $action_url ?>" method="post">
<table class="invisible form borderless">
<table class="invisible form">
<tbody>
<tr>
<td rowspan="6" class="align-center">

View File

@ -315,7 +315,7 @@ class APIRequestBuilder {
* @param string $type
* @return void
*/
private function resetState($url, $type = 'GET')
private function resetState($url, $type = 'GET'): void
{
$requestUrl = $url ?: $this->baseUrl;

View File

@ -65,7 +65,7 @@ final class Anilist {
MangaReadingStatus::PLAN_TO_READ => KMRS::PLAN_TO_READ,
];
public static function getIdToWatchingStatusMap()
public static function getIdToWatchingStatusMap(): array
{
return [
'CURRENT' => AnimeWatchingStatus::WATCHING,
@ -77,7 +77,7 @@ final class Anilist {
];
}
public static function getIdToReadingStatusMap()
public static function getIdToReadingStatusMap(): array
{
return [
'CURRENT' => MangaReadingStatus::READING,

View File

@ -100,7 +100,7 @@ final class Model
$config = $this->container->get('config');
$anilistUser = $config->get(['anilist', 'username']);
if ( ! is_string($anilistUser))
if ( ! \is_string($anilistUser))
{
throw new InvalidArgumentException('Anilist username is not defined in config');
}
@ -151,10 +151,9 @@ final class Model
* Create a list item with all the relevant data
*
* @param array $data
* @param string $type
* @return Request
*/
public function createFullListItem(array $data, string $type = 'anime'): Request
public function createFullListItem(array $data): Request
{
$createData = $data['data'];
$mediaId = $this->getMediaIdFromMalId($data['mal_id']);
@ -168,6 +167,7 @@ final class Model
* Get the data for a specific list item, generally for editing
*
* @param string $malId - The unique identifier of that list item
* @param string $type - Them media type (anime/manga)
* @return mixed
*/
public function getListItem(string $malId, string $type): array
@ -185,6 +185,7 @@ final class Model
* Increase the watch count for the current list item
*
* @param FormItem $data
* @param string $type - Them media type (anime/manga)
* @return Request
*/
public function incrementListItem(FormItem $data, string $type): Request
@ -198,7 +199,7 @@ final class Model
* Modify a list item
*
* @param FormItem $data
* @param int [$id]
* @param string $type - Them media type (anime/manga)
* @return Request
*/
public function updateListItem(FormItem $data, string $type): Request
@ -225,6 +226,7 @@ final class Model
* Get the id of the specific list entry from the malId
*
* @param string $malId
* @param string $type - The media type (anime/manga)
* @return string
*/
public function getListIdFromMalId(string $malId, string $type): ?string
@ -234,7 +236,7 @@ final class Model
}
/**
* Get the Anilist media id from its MAL id
* Get the Anilist list item id from the media id from its MAL id
* this way is more accurate than getting the list item id
* directly from the MAL id
*/
@ -248,13 +250,6 @@ final class Model
'userName' => $anilistUser,
]);
/* dump([
'media_id' => $mediaId,
'userName' => $anilistUser,
'response' => $info,
]);
die(); */
return (string)$info['data']['MediaList']['id'];
}
@ -272,12 +267,6 @@ final class Model
'type' => mb_strtoupper($type),
]);
/* dump([
'mal_id' => $malId,
'response' => $info,
]);
die(); */
return (string)$info['data']['Media']['id'];
}
}

View File

@ -56,16 +56,4 @@ class AnimeListTransformer extends AbstractTransformer {
],
]);
}
/**
* Transform a set of structures
*
* @param array|object $collection
* @return array
*/
public function untransformCollection($collection): array
{
$list = (array)$collection;
return array_map([$this, 'untransform'], $list);
}
}

View File

@ -18,6 +18,7 @@ namespace Aviat\AnimeClient\API\Anilist\Transformer;
use Aviat\AnimeClient\API\Enum\MangaReadingStatus\Anilist as AnilistStatus;
use Aviat\AnimeClient\API\Mapping\MangaReadingStatus;
use Aviat\AnimeClient\Types\MangaListItem;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Transformer\AbstractTransformer;
@ -28,7 +29,7 @@ class MangaListTransformer extends AbstractTransformer {
public function transform($item)
{
return new MangaListItem([]);
}
/**
@ -56,16 +57,4 @@ class MangaListTransformer extends AbstractTransformer {
]
]);
}
/**
* Transform a set of structures
*
* @param array|object $collection
* @return array
*/
public function untransformCollection($collection): array
{
$list = (array)$collection;
return array_map([$this, 'untransform'], $list);
}
}

View File

@ -22,10 +22,10 @@ use Aviat\Ion\Enum;
* Possible values for watching status for the current anime
*/
final class Anilist extends Enum {
const WATCHING = 'CURRENT';
const COMPLETED = 'COMPLETED';
const ON_HOLD = 'PAUSED';
const DROPPED = 'DROPPED';
const PLAN_TO_WATCH = 'PLANNING';
const REPEATING = 'REPEATING';
public const WATCHING = 'CURRENT';
public const COMPLETED = 'COMPLETED';
public const ON_HOLD = 'PAUSED';
public const DROPPED = 'DROPPED';
public const PLAN_TO_WATCH = 'PLANNING';
public const REPEATING = 'REPEATING';
}

View File

@ -22,9 +22,9 @@ use Aviat\Ion\Enum;
* Possible values for watching status for the current anime
*/
final class Kitsu extends Enum {
const WATCHING = 'current';
const PLAN_TO_WATCH = 'planned';
const ON_HOLD = 'on_hold';
const DROPPED = 'dropped';
const COMPLETED = 'completed';
public const WATCHING = 'current';
public const PLAN_TO_WATCH = 'planned';
public const ON_HOLD = 'on_hold';
public const DROPPED = 'dropped';
public const COMPLETED = 'completed';
}

View File

@ -16,16 +16,16 @@
namespace Aviat\AnimeClient\API\Enum\AnimeWatchingStatus;
use Aviat\Ion\Enum as Enum;
use Aviat\Ion\Enum;
/**
* Possible values for current watching status of anime
*/
final class Route extends Enum {
const ALL = 'all';
const WATCHING = 'watching';
const PLAN_TO_WATCH = 'plan_to_watch';
const DROPPED = 'dropped';
const ON_HOLD = 'on_hold';
const COMPLETED = 'completed';
public const ALL = 'all';
public const WATCHING = 'watching';
public const PLAN_TO_WATCH = 'plan_to_watch';
public const DROPPED = 'dropped';
public const ON_HOLD = 'on_hold';
public const COMPLETED = 'completed';
}

View File

@ -16,16 +16,16 @@
namespace Aviat\AnimeClient\API\Enum\AnimeWatchingStatus;
use Aviat\Ion\Enum as Enum;
use Aviat\Ion\Enum;
/**
* Possible values for current watching status of anime
*/
final class Title extends Enum {
const ALL = 'All';
const WATCHING = 'Currently Watching';
const PLAN_TO_WATCH = 'Plan to Watch';
const DROPPED = 'Dropped';
const ON_HOLD = 'On Hold';
const COMPLETED = 'Completed';
public const ALL = 'All';
public const WATCHING = 'Currently Watching';
public const PLAN_TO_WATCH = 'Plan to Watch';
public const DROPPED = 'Dropped';
public const ON_HOLD = 'On Hold';
public const COMPLETED = 'Completed';
}

View File

@ -22,10 +22,10 @@ use Aviat\Ion\Enum;
* Possible values for watching status for the current anime
*/
final class Anilist extends Enum {
const READING = 'CURRENT';
const COMPLETED = 'COMPLETED';
const ON_HOLD = 'PAUSED';
const DROPPED = 'DROPPED';
const PLAN_TO_READ = 'PLANNING';
const REPEATING = 'REPEATING';
public const READING = 'CURRENT';
public const COMPLETED = 'COMPLETED';
public const ON_HOLD = 'PAUSED';
public const DROPPED = 'DROPPED';
public const PLAN_TO_READ = 'PLANNING';
public const REPEATING = 'REPEATING';
}

View File

@ -22,9 +22,9 @@ use Aviat\Ion\Enum;
* Possible values for current reading status of manga
*/
final class Kitsu extends Enum {
const READING = 'current';
const PLAN_TO_READ = 'planned';
const DROPPED = 'dropped';
const ON_HOLD = 'on_hold';
const COMPLETED = 'completed';
public const READING = 'current';
public const PLAN_TO_READ = 'planned';
public const DROPPED = 'dropped';
public const ON_HOLD = 'on_hold';
public const COMPLETED = 'completed';
}

View File

@ -22,10 +22,10 @@ use Aviat\Ion\Enum;
* Possible values for current reading status of manga
*/
final class Route extends Enum {
const ALL = 'all';
const READING = 'reading';
const PLAN_TO_READ = 'plan_to_read';
const DROPPED = 'dropped';
const ON_HOLD = 'on_hold';
const COMPLETED = 'completed';
public const ALL = 'all';
public const READING = 'reading';
public const PLAN_TO_READ = 'plan_to_read';
public const DROPPED = 'dropped';
public const ON_HOLD = 'on_hold';
public const COMPLETED = 'completed';
}

View File

@ -22,10 +22,10 @@ use Aviat\Ion\Enum;
* Possible values for current reading status of manga
*/
final class Title extends Enum {
const ALL = 'All';
const READING = 'Currently Reading';
const PLAN_TO_READ = 'Plan to Read';
const DROPPED = 'Dropped';
const ON_HOLD = 'On Hold';
const COMPLETED = 'Completed';
public const ALL = 'All';
public const READING = 'Currently Reading';
public const PLAN_TO_READ = 'Plan to Read';
public const DROPPED = 'Dropped';
public const ON_HOLD = 'On Hold';
public const COMPLETED = 'Completed';
}

View File

@ -21,9 +21,7 @@ namespace Aviat\AnimeClient\API;
*/
final class JsonAPI {
/**
* The full data array
*
/*
* Basic structure is generally like so:
* [
* 'id' => '12016665',
@ -35,10 +33,7 @@ final class JsonAPI {
*
* ]
* ]
*
* @var array
*/
protected $data = [];
/**
* Inline all included data
@ -214,8 +209,7 @@ final class JsonAPI {
$dataType = $props['data']['type'];
$relationship =& $organized[$type][$id]['relationships'][$relType];
unset($relationship['links']);
unset($relationship['data']);
unset($relationship['links'], $relationship['data']);
if ($relType === $dataType)
{

View File

@ -23,11 +23,11 @@ use DateTimeImmutable;
* Data massaging helpers for the Kitsu API
*/
final class Kitsu {
const AUTH_URL = 'https://kitsu.io/api/oauth/token';
const AUTH_USER_ID_KEY = 'kitsu-auth-userid';
const AUTH_TOKEN_CACHE_KEY = 'kitsu-auth-token';
const AUTH_TOKEN_EXP_CACHE_KEY = 'kitsu-auth-token-expires';
const AUTH_TOKEN_REFRESH_CACHE_KEY = 'kitsu-auth-token-refresh';
public const AUTH_URL = 'https://kitsu.io/api/oauth/token';
public const AUTH_USER_ID_KEY = 'kitsu-auth-userid';
public const AUTH_TOKEN_CACHE_KEY = 'kitsu-auth-token';
public const AUTH_TOKEN_EXP_CACHE_KEY = 'kitsu-auth-token-expires';
public const AUTH_TOKEN_REFRESH_CACHE_KEY = 'kitsu-auth-token-refresh';
/**
* Determine whether an anime is airing, finished airing, or has not yet aired
@ -163,7 +163,7 @@ final class Kitsu {
'dubs' => $streamingLink['dubs']
];
}
usort($links, function ($a, $b) {
return $a['meta']['name'] <=> $b['meta']['name'];
});

View File

@ -22,8 +22,8 @@ use Aviat\Ion\Enum as BaseEnum;
* Status of when anime is being/was/will be aired
*/
final class AnimeAiringStatus extends BaseEnum {
const NOT_YET_AIRED = 'Not Yet Aired';
const AIRING = 'Currently Airing';
const FINISHED_AIRING = 'Finished Airing';
public const NOT_YET_AIRED = 'Not Yet Aired';
public const AIRING = 'Currently Airing';
public const FINISHED_AIRING = 'Finished Airing';
}
// End of AnimeAiringStatus.php

View File

@ -16,6 +16,7 @@
namespace Aviat\AnimeClient\API\Kitsu;
use const Aviat\AnimeClient\USER_AGENT;
use Aviat\AnimeClient\API\APIRequestBuilder;
final class KitsuRequestBuilder extends APIRequestBuilder {
@ -32,7 +33,7 @@ final class KitsuRequestBuilder extends APIRequestBuilder {
* @var array
*/
protected $defaultHeaders = [
'User-Agent' => "Tim's Anime Client/4.0",
'User-Agent' => USER_AGENT,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'CLIENT_ID' => 'dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd',

View File

@ -16,6 +16,7 @@
namespace Aviat\AnimeClient\API\Kitsu;
use Amp\Artax\Response;
use const Aviat\AnimeClient\SESSION_SEGMENT;
use function Amp\Promise\wait;
@ -121,7 +122,7 @@ trait KitsuTrait {
* @param array $options
* @return Response
*/
private function getResponse(string $type, string $url, array $options = [])
private function getResponse(string $type, string $url, array $options = []): Response
{
$logger = NULL;
if ($this->getContainer())

View File

@ -37,7 +37,7 @@ final class ListItem implements ListItemInterface {
use KitsuTrait;
public function create(array $data): Request
{
{
$body = [
'data' => [
'type' => 'libraryEntries',
@ -61,7 +61,7 @@ final class ListItem implements ListItemInterface {
]
]
];
if (array_key_exists('notes', $data))
{
$body['data']['attributes']['notes'] = $data['notes'];
@ -78,8 +78,6 @@ final class ListItem implements ListItemInterface {
return $request->setJsonBody($body)
->getFullRequest();
// return ($response->getStatus() === 201);
}
public function delete(string $id): Request
@ -93,8 +91,6 @@ final class ListItem implements ListItemInterface {
}
return $request->getFullRequest();
// return ($response->getStatus() === 204);
}
public function get(string $id): array

View File

@ -91,9 +91,10 @@ final class Model {
{
$this->animeTransformer = new AnimeTransformer();
$this->animeListTransformer = new AnimeListTransformer();
$this->listItem = $listItem;
$this->mangaTransformer = new MangaTransformer();
$this->mangaListTransformer = new MangaListTransformer();
$this->listItem = $listItem;
}
/**
@ -265,7 +266,7 @@ final class Model {
public function getUserData(string $username): array
{
// $userId = $this->getUserIdByUsername($username);
$data = $this->getRequest("users", [
$data = $this->getRequest('users', [
'query' => [
'filter' => [
'name' => $username,
@ -334,7 +335,7 @@ final class Model {
* @param string $type "anime" or "manga"
* @return string|NULL
*/
public function getKitsuIdFromMALId(string $malId, string $type="anime")
public function getKitsuIdFromMALId(string $malId, string $type='anime'): ?string
{
$options = [
'query' => [
@ -369,7 +370,7 @@ final class Model {
* @param string $slug
* @return Anime
*/
public function getAnime(string $slug)
public function getAnime(string $slug): Anime
{
$baseData = $this->getRawMediaData('anime', $slug);
@ -523,7 +524,7 @@ final class Model {
* @param string $kitsuAnimeId The id of the anime on Kitsu
* @return string|null Returns the mal id if it exists, otherwise null
*/
public function getMalIdForAnime(string $kitsuAnimeId)
public function getMalIdForAnime(string $kitsuAnimeId): ?string
{
$options = [
'query' => [
@ -625,7 +626,7 @@ final class Model {
* Get information about a particular manga
*
* @param string $mangaId
* @return array
* @return MangaPage
*/
public function getMangaById(string $mangaId): MangaPage
{
@ -808,7 +809,7 @@ final class Model {
* @param string $kitsuMangaId The id of the manga on Kitsu
* @return string|null Returns the mal id if it exists, otherwise null
*/
public function getMalIdForManga(string $kitsuMangaId)
public function getMalIdForManga(string $kitsuMangaId): ?string
{
$options = [
'query' => [
@ -920,7 +921,7 @@ final class Model {
}
/**
* Get the raw data for the anime id
* Get the raw data for the anime/manga id
*
* @param string $type
* @param string $id

View File

@ -24,7 +24,7 @@ use Aviat\Ion\Enum;
* and url route segments
*/
final class AnimeWatchingStatus extends Enum {
const ANILIST_TO_KITSU = [
public const ANILIST_TO_KITSU = [
Anilist::WATCHING => Kitsu::WATCHING,
Anilist::PLAN_TO_WATCH => Kitsu::PLAN_TO_WATCH,
Anilist::COMPLETED => Kitsu::COMPLETED,
@ -32,7 +32,7 @@ final class AnimeWatchingStatus extends Enum {
Anilist::DROPPED => Kitsu::DROPPED
];
const KITSU_TO_ANILIST = [
public const KITSU_TO_ANILIST = [
Kitsu::WATCHING => Anilist::WATCHING,
Kitsu::PLAN_TO_WATCH => Anilist::PLAN_TO_WATCH,
Kitsu::COMPLETED => Anilist::COMPLETED,
@ -40,7 +40,7 @@ final class AnimeWatchingStatus extends Enum {
Kitsu::DROPPED => Anilist::DROPPED
];
const KITSU_TO_TITLE = [
public const KITSU_TO_TITLE = [
Kitsu::WATCHING => Title::WATCHING,
Kitsu::PLAN_TO_WATCH => Title::PLAN_TO_WATCH,
Kitsu::ON_HOLD => Title::ON_HOLD,
@ -48,7 +48,7 @@ final class AnimeWatchingStatus extends Enum {
Kitsu::COMPLETED => Title::COMPLETED
];
const ROUTE_TO_KITSU = [
public const ROUTE_TO_KITSU = [
Route::WATCHING => Kitsu::WATCHING,
Route::PLAN_TO_WATCH => Kitsu::PLAN_TO_WATCH,
Route::ON_HOLD => Kitsu::ON_HOLD,
@ -56,7 +56,7 @@ final class AnimeWatchingStatus extends Enum {
Route::COMPLETED => Kitsu::COMPLETED
];
const ROUTE_TO_TITLE = [
public const ROUTE_TO_TITLE = [
Route::ALL => Title::ALL,
Route::WATCHING => Title::WATCHING,
Route::PLAN_TO_WATCH => Title::PLAN_TO_WATCH,
@ -65,7 +65,7 @@ final class AnimeWatchingStatus extends Enum {
Route::COMPLETED => Title::COMPLETED
];
const TITLE_TO_ROUTE = [
public const TITLE_TO_ROUTE = [
Title::ALL => Route::ALL,
Title::WATCHING => Route::WATCHING,
Title::PLAN_TO_WATCH => Route::PLAN_TO_WATCH,

View File

@ -24,7 +24,7 @@ use Aviat\Ion\Enum;
* and url route segments
*/
final class MangaReadingStatus extends Enum {
const ANILIST_TO_KITSU = [
public const ANILIST_TO_KITSU = [
Anilist::READING => Kitsu::READING,
Anilist::PLAN_TO_READ => Kitsu::PLAN_TO_READ,
Anilist::COMPLETED => Kitsu::COMPLETED,
@ -32,7 +32,7 @@ final class MangaReadingStatus extends Enum {
Anilist::DROPPED => Kitsu::DROPPED
];
const KITSU_TO_ANILIST = [
public const KITSU_TO_ANILIST = [
Kitsu::READING => Anilist::READING,
Kitsu::PLAN_TO_READ => Anilist::PLAN_TO_READ,
Kitsu::COMPLETED => Anilist::COMPLETED,
@ -40,7 +40,7 @@ final class MangaReadingStatus extends Enum {
Kitsu::DROPPED => Anilist::DROPPED
];
const KITSU_TO_TITLE = [
public const KITSU_TO_TITLE = [
Kitsu::READING => Title::READING,
Kitsu::PLAN_TO_READ => Title::PLAN_TO_READ,
Kitsu::COMPLETED => Title::COMPLETED,
@ -48,7 +48,7 @@ final class MangaReadingStatus extends Enum {
Kitsu::DROPPED => Title::DROPPED,
];
const ROUTE_TO_KITSU = [
public const ROUTE_TO_KITSU = [
Route::PLAN_TO_READ => Kitsu::PLAN_TO_READ,
Route::READING => Kitsu::READING,
Route::COMPLETED => Kitsu::COMPLETED,
@ -56,7 +56,7 @@ final class MangaReadingStatus extends Enum {
Route::ON_HOLD => Kitsu::ON_HOLD,
];
const ROUTE_TO_TITLE = [
public const ROUTE_TO_TITLE = [
Route::ALL => Title::ALL,
Route::PLAN_TO_READ => Title::PLAN_TO_READ,
Route::READING => Title::READING,
@ -65,7 +65,7 @@ final class MangaReadingStatus extends Enum {
Route::ON_HOLD => Title::ON_HOLD,
];
const TITLE_TO_KITSU = [
public const TITLE_TO_KITSU = [
Title::PLAN_TO_READ => Kitsu::PLAN_TO_READ,
Title::READING => Kitsu::READING,
Title::COMPLETED => Kitsu::COMPLETED,

View File

@ -246,7 +246,7 @@ function getLocalImg ($kitsuUrl, $webp = TRUE): string
* @param int $height
* @param string $text
*/
function createPlaceholderImage ($path, $width, $height, $text = 'Image Unavailable')
function createPlaceholderImage ($path, $width, $height, $text = 'Image Unavailable'): void
{
$width = $width ?? 200;
$height = $height ?? 200;
@ -268,7 +268,7 @@ function createPlaceholderImage ($path, $width, $height, $text = 'Image Unavaila
$fontSize = 10;
$fontWidth = imagefontwidth($fontSize);
$fontHeight = imagefontheight($fontSize);
$length = strlen($text);
$length = \strlen($text);
$textWidth = $length * $fontWidth;
$fxPos = (int) ceil((imagesx($img) - $textWidth) / 2);
$fyPos = (int) ceil((imagesy($img) - $fontHeight) / 2);

View File

@ -21,13 +21,9 @@ use function Aviat\AnimeClient\loadTomlFile;
use Aura\Router\RouterContainer;
use Aura\Session\SessionFactory;
use Aviat\AnimeClient\UrlGenerator;
use Aviat\AnimeClient\Util;
use Aviat\AnimeClient\API\CacheTrait;
use Aviat\AnimeClient\API\Anilist;
use Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\{Model, UrlGenerator, Util};
use Aviat\AnimeClient\API\{Anilist, CacheTrait, Kitsu};
use Aviat\AnimeClient\API\Kitsu\KitsuRequestBuilder;
use Aviat\AnimeClient\Model;
use Aviat\Banker\Pool;
use Aviat\Ion\Config;
use Aviat\Ion\Di\{Container, ContainerAware};

View File

@ -1,59 +1,59 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Command;
/**
* Clears out image cache directories
*/
class ClearThumbnails extends BaseCommand {
public function execute(array $args, array $options = []): void
{
$this->clearThumbs();
$this->echoBox('All cached images have been removed');
}
public function clearThumbs()
{
$imgDir = realpath(__DIR__ . '/../../public/images');
$paths = [
'avatars/*.gif',
'avatars/*.jpg',
'avatars/*.png',
'avatars/*.webp',
'anime/*.jpg',
'anime/*.png',
'anime/*.webp',
'manga/*.jpg',
'manga/*.png',
'manga/*.webp',
'characters/*.jpg',
'characters/*.png',
'characters/*.webp',
'people/*.jpg',
'people/*.png',
'people/*.webp',
];
foreach($paths as $path)
{
$cmd = "rm -rf {$imgDir}/{$path}";
exec($cmd);
}
}
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Command;
/**
* Clears out image cache directories
*/
class ClearThumbnails extends BaseCommand {
public function execute(array $args, array $options = []): void
{
$this->clearThumbs();
$this->echoBox('All cached images have been removed');
}
private function clearThumbs(): void
{
$imgDir = realpath(__DIR__ . '/../../public/images');
$paths = [
'avatars/*.gif',
'avatars/*.jpg',
'avatars/*.png',
'avatars/*.webp',
'anime/*.jpg',
'anime/*.png',
'anime/*.webp',
'manga/*.jpg',
'manga/*.png',
'manga/*.webp',
'characters/*.jpg',
'characters/*.png',
'characters/*.webp',
'people/*.jpg',
'people/*.png',
'people/*.webp',
];
foreach($paths as $path)
{
$cmd = "rm -rf {$imgDir}/{$path}";
exec($cmd);
}
}
}

View File

@ -183,7 +183,7 @@ class Controller {
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @return void
*/
public function sessionRedirect()
public function sessionRedirect(): void
{
$target = $this->session->get('redirect_url');
if (empty($target))
@ -208,7 +208,7 @@ class Controller {
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @return string
*/
protected function loadPartial($view, string $template, array $data = [])
protected function loadPartial($view, string $template, array $data = []): string
{
$router = $this->container->get('dispatcher');
@ -242,7 +242,7 @@ class Controller {
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @return void
*/
protected function renderFullPage($view, string $template, array $data)
protected function renderFullPage($view, string $template, array $data): void
{
$csp = [
"default-src 'self'",
@ -275,7 +275,7 @@ class Controller {
public function notFound(
string $title = 'Sorry, page not found',
string $message = 'Page Not Found'
)
): void
{
$this->outputHTML('404', [
'title' => $title,
@ -383,7 +383,7 @@ class Controller {
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @return void
*/
protected function outputHTML(string $template, array $data = [], $view = NULL, int $code = 200)
protected function outputHTML(string $template, array $data = [], $view = NULL, int $code = 200): void
{
if (null === $view)
{

View File

@ -68,7 +68,7 @@ final class AnimeCollection extends BaseController {
* @throws \Aviat\Ion\Exception\DoubleRenderException
* @return void
*/
public function search()
public function search(): void
{
$queryParams = $this->request->getQueryParams();
$query = $queryParams['query'];
@ -84,7 +84,7 @@ final class AnimeCollection extends BaseController {
* @throws \InvalidArgumentException
* @return void
*/
public function index($view)
public function index($view): void
{
$viewMap = [
'' => 'cover',
@ -110,7 +110,7 @@ final class AnimeCollection extends BaseController {
* @throws \InvalidArgumentException
* @return void
*/
public function form($id = NULL)
public function form($id = NULL): void
{
$this->setSessionRedirect();
@ -161,7 +161,7 @@ final class AnimeCollection extends BaseController {
* @throws \InvalidArgumentException
* @return void
*/
public function add()
public function add(): void
{
$data = $this->request->getParsedBody();
if (array_key_exists('id', $data))
@ -182,7 +182,7 @@ final class AnimeCollection extends BaseController {
*
* @return void
*/
public function delete()
public function delete(): void
{
$data = $this->request->getParsedBody();
if ( ! array_key_exists('hummingbird_id', $data))

View File

@ -138,7 +138,7 @@ final class MangaCollection extends BaseController {
* @throws \InvalidArgumentException
* @return void
*/
public function edit()
public function edit(): void
{
$data = $this->request->getParsedBody();
if (array_key_exists('hummingbird_id', $data))
@ -162,7 +162,7 @@ final class MangaCollection extends BaseController {
* @throws \InvalidArgumentException
* @return void
*/
public function add()
public function add(): void
{
$data = $this->request->getParsedBody();
if (array_key_exists('id', $data))
@ -183,7 +183,7 @@ final class MangaCollection extends BaseController {
*
* @return void
*/
public function delete()
public function delete(): void
{
$data = $this->request->getParsedBody();
if ( ! array_key_exists('hummingbird_id', $data))

View File

@ -17,7 +17,6 @@
namespace Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\View\HtmlView;
/**
@ -29,7 +28,7 @@ final class Misc extends BaseController {
*
* @return void
*/
public function clearCache()
public function clearCache(): void
{
$this->cache->clear();
$this->outputHTML('blank', [
@ -43,7 +42,7 @@ final class Misc extends BaseController {
* @param string $status
* @return void
*/
public function login(string $status = '')
public function login(string $status = ''): void
{
$message = '';
@ -68,7 +67,7 @@ final class Misc extends BaseController {
*
* @return void
*/
public function loginAction()
public function loginAction(): void
{
$auth = $this->container->get('auth');
$post = $this->request->getParsedBody();
@ -88,7 +87,7 @@ final class Misc extends BaseController {
*
* @return void
*/
public function logout()
public function logout(): void
{
$auth = $this->container->get('auth');
$auth->logout();

View File

@ -64,8 +64,9 @@ final class Dispatcher extends RoutingBase {
public function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->router = $container->get('aura-router')->getMap();
$this->matcher = $container->get('aura-router')->getMatcher();
$router = $this->container->get('aura-router');
$this->router = $router->getMap();
$this->matcher = $router->getMatcher();
$this->request = $container->get('request');
$this->outputRoutes = $this->setupRoutes();
@ -99,7 +100,7 @@ final class Dispatcher extends RoutingBase {
*
* @return array
*/
public function getOutputRoutes()
public function getOutputRoutes(): array
{
return $this->outputRoutes;
}
@ -171,7 +172,7 @@ final class Dispatcher extends RoutingBase {
$controllerName = $map[$controllerName];
}
$actionMethod = (array_key_exists('action', $route->attributes))
$actionMethod = array_key_exists('action', $route->attributes)
? $route->attributes['action']
: NOT_FOUND_METHOD;
@ -205,9 +206,9 @@ final class Dispatcher extends RoutingBase {
*
* @return string
*/
public function getController()
public function getController(): string
{
$routeType = $this->__get('default_list');
$routeType = $this->config->get('default_list');
$requestUri = $this->request->getUri()->getPath();
$path = trim($requestUri, '/');
@ -225,7 +226,7 @@ final class Dispatcher extends RoutingBase {
$controller = $routeType;
}
return $controller;
return $controller ?? '';
}
/**
@ -233,11 +234,13 @@ final class Dispatcher extends RoutingBase {
*
* @return array
*/
public function getControllerList()
public function getControllerList(): array
{
$defaultNamespace = DEFAULT_CONTROLLER_NAMESPACE;
$path = str_replace('\\', '/', $defaultNamespace);
$path = str_replace('Aviat/AnimeClient/', '', $path);
$find = ['\\', 'Aviat/AnimeClient/'];
$replace = ['/', ''];
$path = str_replace($find, $replace, $defaultNamespace);
$path = trim($path, '/');
$actualPath = realpath(_dir(SRC_DIR, $path));
$classFiles = glob("{$actualPath}/*.php");
@ -265,7 +268,7 @@ final class Dispatcher extends RoutingBase {
* @param array $params
* @return void
*/
protected function call($controllerName, $method, array $params)
protected function call($controllerName, $method, array $params): void
{
$logger = $this->container->getLogger('default');
@ -347,7 +350,7 @@ final class Dispatcher extends RoutingBase {
*
* @return array
*/
protected function setupRoutes()
protected function setupRoutes(): array
{
$routeType = $this->getController();
@ -359,7 +362,7 @@ final class Dispatcher extends RoutingBase {
unset($route['path']);
$controllerMap = $this->getControllerList();
$controllerClass = (array_key_exists($routeType, $controllerMap))
$controllerClass = array_key_exists($routeType, $controllerMap)
? $controllerMap[$routeType]
: DEFAULT_CONTROLLER;

View File

@ -16,35 +16,28 @@
namespace Aviat\AnimeClient;
use Aviat\Ion\
{
ArrayWrapper, StringWrapper
};
use Aviat\Ion\Di\ContainerInterface;
/**
* Helper object to manage form generation, especially for config editing
*/
final class FormGenerator {
use ArrayWrapper;
use StringWrapper;
/**
* Injection Container
* @var ContainerInterface $container
*/
protected $container;
/**
* Html generation helper
*
* @var \Aura\Html\HelperLocator
*/
protected $helper;
private $helper;
/**
* FormGenerator constructor.
*
* @param ContainerInterface $container
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->helper = $container->get('html-helper');
}
@ -55,7 +48,7 @@ final class FormGenerator {
* @param array $form
* @return string
*/
public function generate(string $name, array $form)
public function generate(string $name, array $form): string
{
$type = $form['type'];
@ -105,6 +98,6 @@ final class FormGenerator {
}
}
return $this->helper->input($params);
return (string)$this->helper->input($params);
}
}

View File

@ -45,9 +45,11 @@ final class MenuGenerator extends UrlGenerator {
protected $request;
/**
* Create menu generator
* MenuGenerator constructor.
*
* @param ContainerInterface $container
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
*/
public function __construct(ContainerInterface $container)
{
@ -106,7 +108,7 @@ final class MenuGenerator extends UrlGenerator {
$link = $this->helper->a($this->url($path), $title);
$attrs = ($selected)
$attrs = $selected
? ['class' => 'selected']
: [];

View File

@ -16,14 +16,10 @@
namespace Aviat\AnimeClient\Model;
use Aviat\Ion\StringWrapper;
/**
* Base model for api interaction
*/
class API {
use StringWrapper;
/**
* Sort the list entries by their title
*
@ -31,7 +27,7 @@ class API {
* @param string $sortKey
* @return void
*/
protected function sortByName(array &$array, string $sortKey)
protected function sortByName(array &$array, string $sortKey): void
{
$sort = [];

View File

@ -108,7 +108,7 @@ class Anime extends API {
* @param string $slug
* @return AnimeType
*/
public function getAnime(string $slug)
public function getAnime(string $slug): AnimeType
{
return $this->kitsuModel->getAnime($slug);
}
@ -147,7 +147,7 @@ class Anime extends API {
$item = $this->kitsuModel->getListItem($itemId);
$array = $item->toArray();
if (is_array($array['notes']))
if (\is_array($array['notes']))
{
$array['notes'] = '';
}

View File

@ -226,6 +226,11 @@ final class AnimeCollection extends Collection {
return $query->fetch(PDO::FETCH_ASSOC);
}
/**
* Get the list of genres from the database
*
* @return array
*/
private function getGenresForList(): array
{
$query = $this->db->select('hummingbird_id, genre')

View File

@ -83,11 +83,11 @@ class Collection extends DB {
if ( ! empty($filter))
{
$this->db->where_in('hummingbird_id', $filter);
$this->db->whereIn('hummingbird_id', $filter);
}
$query = $this->db->order_by('hummingbird_id')
->order_by('genre')
$query = $this->db->orderBy('hummingbird_id')
->orderBy('genre')
->get();
$output = [];

View File

@ -17,15 +17,12 @@
namespace Aviat\AnimeClient\Model;
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\{ArrayWrapper, StringWrapper};
/**
* Base model for database interaction
*/
class DB {
use ArrayWrapper;
use ContainerAware;
use StringWrapper;
/**
* The query builder object

View File

@ -41,7 +41,7 @@ final class Settings {
$this->config = $config;
}
public function getSettings()
public function getSettings(): array
{
$settings = [
'config' => [],
@ -66,7 +66,7 @@ final class Settings {
return $settings;
}
public function getSettingsForm()
public function getSettingsForm(): array
{
$output = [];
@ -124,7 +124,7 @@ final class Settings {
return $output;
}
public function validateSettings(array $settings)
public function validateSettings(array $settings): array
{
$config = (new Config($settings))->toArray();
@ -150,7 +150,7 @@ final class Settings {
$looseConfig[$key] = $val;
}
}
elseif (is_array($val) && ! empty($val))
elseif (\is_array($val) && ! empty($val))
{
foreach($val as $k => $v)
{
@ -204,7 +204,6 @@ final class Settings {
{
dump($e);
dump($settings);
die();
return FALSE;
}

View File

@ -59,20 +59,6 @@ class RoutingBase {
$this->routes = $this->config->get('routes');
}
/**
* Retrieve the appropriate value for the routing key
*
* @param string|int|array $key
* @return mixed
*/
public function __get($key)
{
if ($this->config->has($key))
{
return $this->config->get($key);
}
}
/**
* Get the current url path
* @throws \Aviat\Ion\Di\ContainerException

View File

@ -47,13 +47,13 @@ class UrlGenerator extends RoutingBase {
/**
* Get the base url for css/js/images
*
* @param string ...$args
* @param string[] $args
* @return string
*/
public function assetUrl(string ...$args): string
{
$baseUrl = rtrim($this->url(''), '/')
. $this->__get('asset_path');
. $this->config->get('asset_path');
array_unshift($args, $baseUrl);
@ -82,7 +82,7 @@ class UrlGenerator extends RoutingBase {
{
if ( ! array_key_exists($i + 1, $segments))
{
$segments[$i + 1] = "";
$segments[$i + 1] = '';
}
$path_segments[$i] = preg_replace('`{.*?}`', $segments[$i + 1], $path_segments[$i]);
@ -104,7 +104,7 @@ class UrlGenerator extends RoutingBase {
public function defaultUrl(string $type): string
{
$type = trim($type);
$defaultPath = $this->__get("default_{$type}_list_path");
$defaultPath = $this->config->get("default_{$type}_list_path");
if ($defaultPath !== NULL)
{

View File

@ -60,7 +60,7 @@ class Util {
* @param string $b - Second item to compare
* @return string
*/
public static function isSelected($a, $b)
public static function isSelected(string $a, string $b): string
{
return ($a === $b) ? 'selected' : '';
}
@ -72,7 +72,7 @@ class Util {
* @param string $b - Second item to compare
* @return string
*/
public static function isNotSelected($a, $b)
public static function isNotSelected(string $a, string $b): string
{
return ($a !== $b) ? 'selected' : '';
}
@ -100,7 +100,7 @@ class Util {
*
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @return boolean
* @return bool
*/
public function isFormPage(): bool
{