Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
57 changed files with 429 additions and 149 deletions
Showing only changes of commit f04cc7d1d5 - Show all commits

View File

@ -24,7 +24,7 @@
<img src="<?= $urlGenerator->assetUrl("images/anime/{$item['anime']['id']}.jpg") ?>" alt="" />
<div class="name">
<a href="<?= $url->generate('anime.details', ['id' => $item['anime']['slug']]); ?>">
<?= array_shift($item['anime']['titles']) ?>
<?= $item['anime']['title'] ?>
<?php foreach ($item['anime']['titles'] as $title): ?>
<br /><small><?= $title ?></small>
<?php endforeach ?>
@ -85,7 +85,7 @@
</div>
</div>
<div class="row">
<div class="media_type"><?= $escape->html($item['anime']['type']) ?></div>
<div class="media_type"><?= $escape->html($item['anime']['show_type']) ?></div>
<div class="airing_status"><?= $escape->html($item['airing']['status']) ?></div>
<div class="age_rating"><?= $escape->html($item['anime']['age_rating']) ?></div>
</div>

View File

@ -38,7 +38,7 @@
</table>
</div>
<div>
<h2><a rel="external" href="<?= $show_data['url'] ?>"><?= array_shift($show_data['titles']) ?></a></h2>
<h2><a rel="external" href="<?= $show_data['url'] ?>"><?= $show_data['title'] ?></a></h2>
<?php foreach ($show_data['titles'] as $title): ?>
<h3><?= $title ?></h3>
<?php endforeach ?>

View File

@ -6,7 +6,7 @@
<thead>
<tr>
<th>
<h3><?= $escape->html(array_shift($item['anime']['titles'])) ?></h3>
<h3><?= $escape->html($item['anime']['title']) ?></h3>
<?php foreach($item['anime']['titles'] as $title): ?>
<h4><?= $escape->html($title) ?></h4>
<?php endforeach ?>

View File

@ -42,15 +42,15 @@
<?php endif ?>
<td class="justify">
<a href="<?= $url->generate('anime.details', ['id' => $item['anime']['slug']]) ?>">
<?= array_shift($item['anime']['titles']) ?>
<?= $item['anime']['title'] ?>
</a>
<?php foreach($item['anime']['titles'] as $title): ?>
<br /><?= $title ?>
<?php foreach ($item['anime']['titles'] as $title): ?>
<br/><?= $title ?>
<?php endforeach ?>
</td>
<td><?= $item['airing']['status'] ?></td>
<td><?= $item['user_rating'] ?> / 10 </td>
<td><?= $item['anime']['type'] ?></td>
<td><?= $item['anime']['show_type'] ?></td>
<td id="<?= $item['anime']['slug'] ?>">
Episodes: <br />
<span class="completed_number"><?= $item['episodes']['watched'] ?></span>&nbsp;/&nbsp;<span class="total_number"><?= $item['episodes']['total'] ?></span>
@ -83,8 +83,8 @@
<p><?= $escape->html($item['notes']) ?></p>
</td>
<td class="align_left">
<?php sort($item['anime']['genres']) ?>
<?= implode(', ', $item['anime']['genres']) ?>
<?php sort($item['anime']->genres) ?>
<?= implode(', ', $item['anime']->genres) ?>
</td>
</tr>
<?php endforeach ?>

View File

@ -39,6 +39,7 @@
"phpmd/phpmd": "^2.4",
"phpstan/phpstan": "^0.9.1",
"phpunit/phpunit": "^6.0",
"roave/security-advisories": "dev-master",
"robmorgan/phinx": "^0.9.1",
"sebastian/phpcpd": "^3.0",
"spatie/phpunit-snapshot-assertions": "^1.2.0",

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum;
/**
* Possible values for watching status for the current anime
*/
class Kitsu extends Enum {
final class Kitsu extends Enum {
const WATCHING = 'current';
const PLAN_TO_WATCH = 'planned';
const ON_HOLD = 'on_hold';

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum;
/**
* Possible values for watching status for the current anime
*/
class MAL extends Enum {
final class MAL extends Enum {
const WATCHING = 1;
const COMPLETED = 2;
const ON_HOLD = 3;

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum as Enum;
/**
* Possible values for current watching status of anime
*/
class Route extends Enum {
final class Route extends Enum {
const ALL = 'all';
const WATCHING = 'watching';
const PLAN_TO_WATCH = 'plan_to_watch';

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum as Enum;
/**
* Possible values for current watching status of anime
*/
class Title extends Enum {
final class Title extends Enum {
const ALL = 'All';
const WATCHING = 'Currently Watching';
const PLAN_TO_WATCH = 'Plan to Watch';

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum;
/**
* Possible values for current reading status of manga
*/
class Kitsu extends Enum {
final class Kitsu extends Enum {
const READING = 'current';
const PLAN_TO_READ = 'planned';
const DROPPED = 'dropped';

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Enum;
/**
* Possible values for watching status for the current anime
*/
class MAL extends Enum {
final class MAL extends Enum {
const READING = 'reading';
const COMPLETED = 'completed';
const ON_HOLD = 'onhold';

View File

@ -16,12 +16,12 @@
namespace Aviat\AnimeClient\API\Enum\MangaReadingStatus;
use Aviat\Ion\Enum as Enum;
use Aviat\Ion\Enum;
/**
* Possible values for current reading status of manga
*/
class Route extends Enum {
final class Route extends Enum {
const ALL = 'all';
const READING = 'reading';
const PLAN_TO_READ = 'plan_to_read';

View File

@ -16,12 +16,12 @@
namespace Aviat\AnimeClient\API\Enum\MangaReadingStatus;
use Aviat\Ion\Enum as Enum;
use Aviat\Ion\Enum;
/**
* Possible values for current reading status of manga
*/
class Title extends Enum {
final class Title extends Enum {
const ALL = 'All';
const READING = 'Currently Reading';
const PLAN_TO_READ = 'Plan to Read';

View File

@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\API;
/**
* Class encapsulating Json API data structure for a request or response
*/
class JsonAPI {
final class JsonAPI {
/**
* The full data array

View File

@ -22,7 +22,7 @@ use DateTimeImmutable;
/**
* Data massaging helpers for the Kitsu API
*/
class Kitsu {
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';

View File

@ -28,7 +28,7 @@ use Exception;
/**
* Kitsu API Authentication
*/
class Auth {
final class Auth {
use CacheTrait;
use ContainerAware;
@ -37,14 +37,14 @@ class Auth {
*
* @var Model
*/
protected $model;
private $model;
/**
* Session object
*
* @var \Aura\Session\Segment
*/
protected $segment;
private $segment;
/**
* Constructor

View File

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

View File

@ -18,7 +18,7 @@ namespace Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\API\APIRequestBuilder;
class KitsuRequestBuilder extends APIRequestBuilder {
final class KitsuRequestBuilder extends APIRequestBuilder {
/**
* The base url for api requests

View File

@ -25,39 +25,17 @@ use Aviat\AnimeClient\API\{
HummingbirdClient,
ListItemInterface
};
use Aviat\AnimeClient\Types\AbstractType;
use Aviat\Ion\Di\ContainerAware;
use Aviat\Ion\Json;
/**
* CRUD operations for Kitsu list items
*/
class ListItem implements ListItemInterface {
final class ListItem implements ListItemInterface {
use ContainerAware;
use KitsuTrait;
private function getAuthHeader()
{
$cache = $this->getContainer()->get('cache');
$cacheItem = $cache->getItem('kitsu-auth-token');
$sessionSegment = $this->getContainer()
->get('session')
->getSegment(SESSION_SEGMENT);
if ($sessionSegment->get('auth_token') !== NULL)
{
$token = $sessionSegment->get('auth_token');
return "bearer {$token}";
}
if ($cacheItem->isHit())
{
$token = $cacheItem->get();
return "bearer {$token}";
}
return FALSE;
}
public function create(array $data): Request
{
$body = [
@ -134,7 +112,7 @@ class ListItem implements ListItemInterface {
return Json::decode(wait($response->getBody()));
}
public function update(string $id, array $data): Request
public function update(string $id, AbstractType $data): Request
{
$authHeader = $this->getAuthHeader();
$requestData = [
@ -155,4 +133,25 @@ class ListItem implements ListItemInterface {
return $request->getFullRequest();
}
private function getAuthHeader()
{
$cache = $this->getContainer()->get('cache');
$cacheItem = $cache->getItem('kitsu-auth-token');
$sessionSegment = $this->getContainer()
->get('session')
->getSegment(SESSION_SEGMENT);
if ($sessionSegment->get('auth_token') !== NULL) {
$token = $sessionSegment->get('auth_token');
return "bearer {$token}";
}
if ($cacheItem->isHit()) {
$token = $cacheItem->get();
return "bearer {$token}";
}
return FALSE;
}
}

View File

@ -36,17 +36,22 @@ use Aviat\AnimeClient\API\Kitsu\Transformer\{
MangaTransformer,
MangaListTransformer
};
use Aviat\AnimeClient\Types\{
Anime,
AnimeFormItem,
AnimeListItem
};
use Aviat\Ion\{Di\ContainerAware, Json};
/**
* Kitsu API Model
*/
class Model {
final class Model {
use CacheTrait;
use ContainerAware;
use KitsuTrait;
protected const LIST_PAGE_SIZE = 100;
private const LIST_PAGE_SIZE = 100;
/**
* Class to map anime list items
@ -55,27 +60,27 @@ class Model {
*
* @var AnimeListTransformer
*/
protected $animeListTransformer;
private $animeListTransformer;
/**
* @var AnimeTransformer
*/
protected $animeTransformer;
private $animeTransformer;
/**
* @var ListItem
*/
protected $listItem;
private $listItem;
/**
* @var MangaTransformer
*/
protected $mangaTransformer;
private $mangaTransformer;
/**
* @var MangaListTransformer
*/
protected $mangaListTransformer;
private $mangaListTransformer;
/**
* Constructor
@ -313,15 +318,15 @@ class Model {
* Get information about a particular anime
*
* @param string $slug
* @return array
* @return Anime
*/
public function getAnime(string $slug): array
public function getAnime(string $slug): Anime
{
$baseData = $this->getRawMediaData('anime', $slug);
if (empty($baseData))
{
return [];
return new Anime();
}
$transformed = $this->animeTransformer->transform($baseData);
@ -803,9 +808,9 @@ class Model {
* Get the data for a specific list item, generally for editing
*
* @param string $listId - The unique identifier of that list item
* @return array
* @return mixed
*/
public function getListItem(string $listId): array
public function getListItem(string $listId)
{
$baseData = $this->listItem->get($listId);
$included = JsonAPI::organizeIncludes($baseData['included']);
@ -813,12 +818,12 @@ class Model {
switch (TRUE)
{
case in_array('anime', array_keys($included)):
case array_key_exists('anime', $included): // in_array('anime', array_keys($included)):
$included = JsonAPI::inlineIncludedRelationships($included, 'anime');
$baseData['data']['included'] = $included;
return $this->animeListTransformer->transform($baseData['data']);
case in_array('manga', array_keys($included)):
case array_key_exists('manga', $included): // in_array('manga', array_keys($included)):
$included = JsonAPI::inlineIncludedRelationships($included, 'manga');
$baseData['data']['included'] = $included;
$baseData['data']['manga'] = $baseData['included'][0];
@ -832,10 +837,10 @@ class Model {
/**
* Modify a list item
*
* @param array $data
* @param AnimeFormItem $data
* @return Request
*/
public function updateListItem(array $data): Request
public function updateListItem(AnimeFormItem $data): Request
{
return $this->listItem->update($data['id'], $data['data']);
}

View File

@ -17,21 +17,27 @@
namespace Aviat\AnimeClient\API\Kitsu\Transformer;
use Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\Types\{
Anime,
AnimeFormItem,
AnimeFormItemData,
AnimeListItem
};
use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Transformer for anime list
*/
class AnimeListTransformer extends AbstractTransformer {
final class AnimeListTransformer extends AbstractTransformer {
/**
* Convert raw api response to a more
* logical and workable structure
*
* @param array $item API library item
* @return array
* @return AnimeListItem
*/
public function transform($item): array
public function transform($item): AnimeListItem
{
$included = $item['included'];
$animeId = $item['relationships']['media']['data']['id'];
@ -66,7 +72,10 @@ class AnimeListTransformer extends AbstractTransformer {
? Kitsu::parseListItemStreamingLinks($included, $animeId)
: [];
return [
$titles = Kitsu::filterTitles($anime);
$title = array_shift($titles);
return new AnimeListItem([
'id' => $item['id'],
'mal_id' => $MALid,
'episodes' => [
@ -81,24 +90,24 @@ class AnimeListTransformer extends AbstractTransformer {
'started' => $anime['startDate'],
'ended' => $anime['endDate']
],
'anime' => [
'anime' => new Anime([
'id' => $animeId,
'age_rating' => $anime['ageRating'],
'title' => $anime['canonicalTitle'],
'titles' => Kitsu::filterTitles($anime),
'title' => $title,
'titles' => $titles,
'slug' => $anime['slug'],
'type' => $this->string($anime['showType'])->upperCaseFirst()->__toString(),
'image' => $anime['posterImage']['small'],
'show_type' => $this->string($anime['showType'])->upperCaseFirst()->__toString(),
'cover_image' => $anime['posterImage']['small'],
'genres' => $genres,
'streaming_links' => $streamingLinks,
],
]),
'watching_status' => $item['attributes']['status'],
'notes' => $item['attributes']['notes'],
'rewatching' => (bool) $item['attributes']['reconsuming'],
'rewatched' => (int) $item['attributes']['reconsumeCount'],
'user_rating' => $rating,
'private' => $item['attributes']['private'] ?? FALSE,
];
]);
}
/**
@ -106,24 +115,24 @@ class AnimeListTransformer extends AbstractTransformer {
* api response format
*
* @param array $item Transformed library item
* @return array API library item
* @return AnimeFormItem API library item
*/
public function untransform($item): array
public function untransform($item): AnimeFormItem
{
$privacy = (array_key_exists('private', $item) && $item['private']);
$rewatching = (array_key_exists('rewatching', $item) && $item['rewatching']);
$untransformed = [
$untransformed = new AnimeFormItem([
'id' => $item['id'],
'mal_id' => $item['mal_id'] ?? NULL,
'data' => [
'data' => new AnimeFormItemData([
'status' => $item['watching_status'],
'reconsuming' => $rewatching,
'reconsumeCount' => $item['rewatched'],
'notes' => $item['notes'],
'private' => $privacy
]
];
])
]);
if (is_numeric($item['episodes_watched']) && $item['episodes_watched'] > 0)
{

View File

@ -17,31 +17,32 @@
namespace Aviat\AnimeClient\API\Kitsu\Transformer;
use Aviat\AnimeClient\API\{JsonAPI, Kitsu};
use Aviat\AnimeClient\Types\Anime;
use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Transformer for anime description page
*/
class AnimeTransformer extends AbstractTransformer {
final class AnimeTransformer extends AbstractTransformer {
/**
* Convert raw api response to a more
* logical and workable structure
*
* @param array $item API library item
* @return array
* @return Anime
*/
public function transform($item): array
public function transform($item): Anime
{
$item['included'] = JsonAPI::organizeIncludes($item['included']);
$genres = $item['included']['categories'] ?? [];
$item['genres'] = array_column($genres, 'title') ?? [];
sort($item['genres']);
$titles = Kitsu::filterTitles($item);
$title = array_shift($titles);
return [
return new Anime([
'age_rating' => $item['ageRating'],
'age_rating_guide' => $item['ageRatingGuide'],
'cover_image' => $item['posterImage']['small'],
@ -54,10 +55,10 @@ class AnimeTransformer extends AbstractTransformer {
'status' => Kitsu::getAiringStatus($item['startDate'], $item['endDate']),
'streaming_links' => Kitsu::parseStreamingLinks($item['included']),
'synopsis' => $item['synopsis'],
'title' => $titles[0],
'title' => $title,
'titles' => $titles,
'trailer_id' => $item['youtubeVideoId'],
'url' => "https://kitsu.io/anime/{$item['slug']}",
];
]);
}
}

View File

@ -23,7 +23,7 @@ use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Data transformation class for zippered Hummingbird manga
*/
class MangaListTransformer extends AbstractTransformer {
final class MangaListTransformer extends AbstractTransformer {
use StringWrapper;

View File

@ -21,7 +21,7 @@ use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Transformer for anime description page
*/
class MangaTransformer extends AbstractTransformer {
final class MangaTransformer extends AbstractTransformer {
/**
* Convert raw api response to a more

View File

@ -17,6 +17,7 @@
namespace Aviat\AnimeClient\API;
use Amp\Artax\Request;
use Aviat\AnimeClient\Types\AbstractType;
/**
* Common interface for anime and manga list item CRUD
@ -43,10 +44,10 @@ interface ListItemInterface {
* Update a list item
*
* @param string $id - The id of the list item to update
* @param array $data - The data with which to update the list item
* @param AbstractType $data - The data with which to update the list item
* @return Request
*/
public function update(string $id, array $data): Request;
public function update(string $id, AbstractType $data): Request;
/**
* Delete a list item

View File

@ -28,7 +28,7 @@ use Aviat\AnimeClient\API\Enum\{
/**
* Constants and mappings for the My Anime List API
*/
class MAL {
final class MAL {
const AUTH_URL = 'https://myanimelist.net/api/account/verify_credentials.xml';
const BASE_URL = 'https://myanimelist.net/api/';

View File

@ -20,12 +20,13 @@ use Amp\Artax\{FormBody, Request};
use Aviat\AnimeClient\API\{
XML
};
use Aviat\AnimeClient\Types\AbstractType;
use Aviat\Ion\Di\ContainerAware;
/**
* CRUD operations for MAL list items
*/
class ListItem {
final class ListItem {
use ContainerAware;
use MALTrait;
@ -84,11 +85,11 @@ class ListItem {
* Update a list item
*
* @param string $id
* @param array $data
* @param AbstractType $data
* @param string $type
* @return Request
*/
public function update(string $id, array $data, string $type = 'anime'): Request
public function update(string $id, AbstractType $data, string $type = 'anime'): Request
{
$config = $this->container->get('config');

View File

@ -21,7 +21,7 @@ use Aviat\AnimeClient\API\{
MAL as M
};
class MALRequestBuilder extends APIRequestBuilder {
final class MALRequestBuilder extends APIRequestBuilder {
/**
* The base url for api requests

View File

@ -24,12 +24,13 @@ use Aviat\AnimeClient\API\MAL\{
};
use Aviat\AnimeClient\API\XML;
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
use Aviat\AnimeClient\Types\{Anime, AnimeFormItem};
use Aviat\Ion\Di\ContainerAware;
/**
* MyAnimeList API Model
*/
class Model {
final class Model {
use ContainerAware;
use MALTrait;
@ -147,11 +148,11 @@ class Model {
/**
* Update a list item
*
* @param array $data
* @param AnimeFormItem $data
* @param string $type "anime" or "manga"
* @return Request
*/
public function updateListItem(array $data, string $type = 'anime'): Request
public function updateListItem(AnimeFormItem $data, string $type = 'anime'): Request
{
$updateData = [];

View File

@ -17,12 +17,13 @@
namespace Aviat\AnimeClient\API\MAL\Transformer;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\{AnimeFormItem, AnimeFormItemData};
use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Transformer for updating MAL List
*/
class AnimeListTransformer extends AbstractTransformer {
final class AnimeListTransformer extends AbstractTransformer {
/**
* Identity transformation
*
@ -38,16 +39,14 @@ class AnimeListTransformer extends AbstractTransformer {
* Transform Kitsu episode data to MAL episode data
*
* @param array $item
* @return array
* @return AnimeFormItem
*/
public function untransform(array $item): array
public function untransform(array $item): AnimeFormItem
{
$map = [
$map = new AnimeFormItem([
'id' => $item['mal_id'],
'data' => []
];
$data =& $item['data'];
'data' => new AnimeFormItemData([]),
]);
foreach($item['data'] as $key => $value)
{

View File

@ -22,7 +22,7 @@ use Aviat\Ion\Transformer\AbstractTransformer;
/**
* Transformer for updating MAL List
*/
class MangaListTransformer extends AbstractTransformer {
final class MangaListTransformer extends AbstractTransformer {
/**
* Identity transformation
*

View File

@ -23,7 +23,7 @@ use Aviat\Ion\Enum;
* Anime watching status mappings, among Kitsu, MAL, Page titles
* and url route segments
*/
class AnimeWatchingStatus extends Enum {
final class AnimeWatchingStatus extends Enum {
const KITSU_TO_MAL = [
Kitsu::WATCHING => MAL::WATCHING,
Kitsu::PLAN_TO_WATCH => MAL::PLAN_TO_WATCH,

View File

@ -23,7 +23,7 @@ use Aviat\Ion\Enum;
* Manga reading status mappings, among Kitsu, MAL, Page titles
* and url route segments
*/
class MangaReadingStatus extends Enum {
final class MangaReadingStatus extends Enum {
const KITSU_TO_MAL = [
Kitsu::READING => MAL::READING,
Kitsu::PLAN_TO_READ => MAL::PLAN_TO_READ,

View File

@ -22,14 +22,14 @@ use function Amp\Promise\{all, wait};
/**
* Class to simplify making and validating simultaneous requests
*/
class ParallelAPIRequest {
final class ParallelAPIRequest {
/**
* Set of requests to make in parallel
*
* @var array
*/
protected $requests = [];
private $requests = [];
/**
* Add a request
@ -76,9 +76,7 @@ class ParallelAPIRequest {
{
$promises[$key] = call(function () use ($client, $url) {
$response = yield $client->request($url);
$body = yield $response->getBody();
return $body;
return yield $response->getBody();
});
}

View File

@ -21,7 +21,7 @@ use DOMDocument, DOMNode, DOMNodeList, InvalidArgumentException;
/**
* XML <=> PHP Array codec
*/
class XML {
final class XML {
/**
* XML representation of the data

View File

@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\Command;
/**
* Clears the API Cache
*/
class CacheClear extends BaseCommand {
final class CacheClear extends BaseCommand {
/**
* Clear the API cache
*

View File

@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\Command;
/**
* Clears the API Cache
*/
class CachePrime extends BaseCommand {
final class CachePrime extends BaseCommand {
/**
* Clear, then prime the API cache
*

View File

@ -32,7 +32,7 @@ use DateTime;
/**
* Clears the API Cache
*/
class SyncLists extends BaseCommand {
final class SyncLists extends BaseCommand {
/**
* Model for making requests to Kitsu API

View File

@ -27,7 +27,7 @@ use Aviat\Ion\StringWrapper;
/**
* Controller for Anime-related pages
*/
class Anime extends BaseController {
final class Anime extends BaseController {
use StringWrapper;
@ -277,7 +277,7 @@ class Anime extends BaseController {
$show_data = $this->model->getAnime($animeId);
$characters = [];
if (empty($show_data))
if ($show_data->title === '')
{
$this->notFound(
$this->config->get('whose_list') .
@ -301,7 +301,7 @@ class Anime extends BaseController {
'title' => $this->formatTitle(
$this->config->get('whose_list') . "'s Anime List",
'Anime',
$show_data['titles'][0]
$show_data->title
),
'characters' => $characters,
'show_data' => $show_data,

View File

@ -26,7 +26,7 @@ use Aviat\Ion\Di\ContainerInterface;
/**
* Controller for Anime collection pages
*/
class AnimeCollection extends BaseController {
final class AnimeCollection extends BaseController {
/**
* The anime collection model

View File

@ -23,7 +23,7 @@ use Aviat\Ion\ArrayWrapper;
/**
* Controller for character description pages
*/
class Character extends BaseController {
final class Character extends BaseController {
use ArrayWrapper;

View File

@ -25,7 +25,7 @@ use Aviat\Ion\View\HtmlView;
/**
* Controller for handling routes that don't fit elsewhere
*/
class Index extends BaseController {
final class Index extends BaseController {
/**
* Purges the API cache

View File

@ -26,7 +26,7 @@ use Aviat\Ion\{Json, StringWrapper};
/**
* Controller for manga list
*/
class Manga extends Controller {
final class Manga extends Controller {
use StringWrapper;

View File

@ -26,7 +26,7 @@ use Aviat\Ion\Di\ContainerInterface;
/**
* Controller for manga collection pages
*/
class MangaCollection extends BaseController {
final class MangaCollection extends BaseController {
/**
* The manga collection model

View File

@ -28,7 +28,7 @@ use Aviat\Ion\StringWrapper;
/**
* Basic routing/ dispatch
*/
class Dispatcher extends RoutingBase {
final class Dispatcher extends RoutingBase {
use StringWrapper;

View File

@ -17,13 +17,14 @@
namespace Aviat\AnimeClient\Helper;
use Aviat\AnimeClient\MenuGenerator;
use Aviat\Ion\Di\ContainerAware;
/**
* MenuGenerator helper wrapper
*/
class Menu {
final class Menu {
use \Aviat\Ion\Di\ContainerAware;
use ContainerAware;
/**
* Create the html for the selected menu

View File

@ -25,7 +25,7 @@ use Aviat\Ion\Exception\ConfigException;
/**
* Helper object to manage menu creation and selection
*/
class MenuGenerator extends UrlGenerator {
final class MenuGenerator extends UrlGenerator {
use ArrayWrapper;
use StringWrapper;

View File

@ -44,7 +44,7 @@ class API {
foreach ($array as $key => $item)
{
$sort[$key] = $item[$sortKey]['titles'][0];
$sort[$key] = $item[$sortKey]['title'];
}
array_multisort($sort, SORT_ASC, $array);

View File

@ -18,13 +18,18 @@ namespace Aviat\AnimeClient\Model;
use Aviat\AnimeClient\API\ParallelAPIRequest;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\{
Anime as AnimeType,
AnimeFormItem,
AnimeListItem,
};
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Json;
/**
* Model for handling requests dealing with the anime list
*/
class Anime extends API {
final class Anime extends API {
/**
* Model for making requests to Kitsu API
*
@ -93,9 +98,9 @@ class Anime extends API {
* Get information about an anime from its slug
*
* @param string $slug
* @return array
* @return AnimeType
*/
public function getAnime(string $slug): array
public function getAnime(string $slug): AnimeType
{
return $this->kitsuModel->getAnime($slug);
}
@ -127,9 +132,9 @@ class Anime extends API {
* for editing/updating that item
*
* @param string $itemId
* @return array
* @return AnimeListItem
*/
public function getLibraryItem(string $itemId): array
public function getLibraryItem(string $itemId): AnimeListItem
{
return $this->kitsuModel->getListItem($itemId);
}
@ -166,10 +171,10 @@ class Anime extends API {
/**
* Update a list entry
*
* @param array $data
* @param AnimeFormItem $data
* @return array
*/
public function updateLibraryItem(array $data): array
public function updateLibraryItem(AnimeFormItem $data): array
{
$requester = new ParallelAPIRequest();

View File

@ -22,7 +22,7 @@ use PDO;
/**
* Model for getting anime collection data
*/
class AnimeCollection extends Collection {
final class AnimeCollection extends Collection {
/**
* Anime API Model

View File

@ -27,7 +27,7 @@ use Aviat\Ion\Json;
/**
* Model for handling requests dealing with the manga list
*/
class Manga extends API
final class Manga extends API
{
/**
* Model for making requests to Kitsu API

View File

@ -22,7 +22,7 @@ use PDO;
/**
* Model for getting anime collection data
*/
class MangaCollection extends Collection {
final class MangaCollection extends Collection {
/**
* Manga API Model

121
src/Types/AbstractType.php Normal file
View File

@ -0,0 +1,121 @@
<?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 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
use ArrayAccess;
use LogicException;
abstract class AbstractType implements ArrayAccess {
/**
* Sets the properties by using the constructor
*
* @param array $data
*/
public function __construct(array $data = [])
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
/**
* See if a property is set
*
* @param $name
* @return bool
*/
public function __isset($name): bool
{
return property_exists($this, $name);
}
/**
* Set a property on the type object
*
* @param string $name
* @param mixed $value
* @return void
*/
public function __set($name, $value): void
{
if (!property_exists($this, $name)) {
$existing = json_encode($this);
throw new LogicException("Trying to set non-existent property: '$name'. Existing properties: $existing");
}
$this->$name = $value;
}
/**
* Get a property from the type object
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
if (property_exists($this, $name)) {
return $this->$name;
}
throw new LogicException("Trying to get non-existent property: '$name'");
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @return bool
*/
public function offsetExists($offset): bool
{
return $this->__isset($offset);
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->__get($offset);
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @param $value
*/
public function offsetSet($offset, $value): void
{
$this->__set($offset, $value);
}
/**
* Implementing ArrayAccess
*
* @param $offset
*/
public function offsetUnset($offset): void
{
// Do nothing!
}
}

40
src/Types/Anime.php Normal file
View File

@ -0,0 +1,40 @@
<?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 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class Anime extends AbstractType {
public $age_rating;
public $age_rating_guide;
public $cover_image;
public $episode_count;
public $episode_length;
public $genres;
public $id;
public $included;
public $show_type;
public $slug;
public $status;
public $streaming_links;
public $synopsis;
public $title;
public $titles;
public $trailer_id;
public $url;
}

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 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class AnimeFormItem extends AbstractType {
public $data;
public $id;
public $mal_id;
}

View File

@ -0,0 +1,30 @@
<?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 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class AnimeFormItemData extends AbstractType {
public $notes;
public $private;
public $progress;
public $rating;
public $reconsumeCount;
public $reconsuming;
public $status;
}

View File

@ -0,0 +1,42 @@
<?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 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class AnimeListItem extends AbstractType {
public $id;
public $mal_id;
public $episodes = [
'length' => 0,
'total' => 0,
'watched' => '',
];
public $airing = [
'status' => '',
'started' => '',
'ended' => '',
];
public $anime;
public $watching_status;
public $notes;
public $rewatching;
public $rewatched;
public $user_rating;
public $private;
}