Move data transformation out of controllers, and into transformers
All checks were successful
timw4mail/HummingBirdAnimeClient/develop This commit looks good
All checks were successful
timw4mail/HummingBirdAnimeClient/develop This commit looks good
This commit is contained in:
parent
11475187fc
commit
27977a0c8a
@ -2,52 +2,52 @@
|
|||||||
<main class="details fixed">
|
<main class="details fixed">
|
||||||
<section class="flex">
|
<section class="flex">
|
||||||
<aside class="info">
|
<aside class="info">
|
||||||
<?= $helper->picture("images/anime/{$show_data['id']}-original.webp") ?>
|
<?= $helper->picture("images/anime/{$data['id']}-original.webp") ?>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<table class="media-details">
|
<table class="media-details">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="align-right">Airing Status</td>
|
<td class="align-right">Airing Status</td>
|
||||||
<td><?= $show_data['status'] ?></td>
|
<td><?= $data['status'] ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Show Type</td>
|
<td>Show Type</td>
|
||||||
<td><?= $show_data['show_type'] ?></td>
|
<td><?= $data['show_type'] ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Episode Count</td>
|
<td>Episode Count</td>
|
||||||
<td><?= $show_data['episode_count'] ?? '-' ?></td>
|
<td><?= $data['episode_count'] ?? '-' ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php if ( ! empty($show_data['episode_length'])): ?>
|
<?php if ( ! empty($data['episode_length'])): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Episode Length</td>
|
<td>Episode Length</td>
|
||||||
<td><?= $show_data['episode_length'] ?> minutes</td>
|
<td><?= $data['episode_length'] ?> minutes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if ( ! empty($show_data['age_rating'])): ?>
|
<?php if ( ! empty($data['age_rating'])): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Age Rating</td>
|
<td>Age Rating</td>
|
||||||
<td><abbr title="<?= $show_data['age_rating_guide'] ?>"><?= $show_data['age_rating'] ?></abbr>
|
<td><abbr title="<?= $data['age_rating_guide'] ?>"><?= $data['age_rating'] ?></abbr>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Genres</td>
|
<td>Genres</td>
|
||||||
<td>
|
<td>
|
||||||
<?= implode(', ', $show_data['genres']) ?>
|
<?= implode(', ', $data['genres']) ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</aside>
|
</aside>
|
||||||
<article class="text">
|
<article class="text">
|
||||||
<h2 class="toph"><a rel="external" href="<?= $show_data['url'] ?>"><?= $show_data['title'] ?></a></h2>
|
<h2 class="toph"><a rel="external" href="<?= $data['url'] ?>"><?= $data['title'] ?></a></h2>
|
||||||
<?php foreach ($show_data['titles'] as $title): ?>
|
<?php foreach ($data['titles'] as $title): ?>
|
||||||
<h3><?= $title ?></h3>
|
<h3><?= $title ?></h3>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
<br />
|
<br />
|
||||||
<p class="description"><?= nl2br($show_data['synopsis']) ?></p>
|
<p class="description"><?= nl2br($data['synopsis']) ?></p>
|
||||||
<?php if (count($show_data['streaming_links']) > 0): ?>
|
<?php if (count($data['streaming_links']) > 0): ?>
|
||||||
<hr />
|
<hr />
|
||||||
<h4>Streaming on:</h4>
|
<h4>Streaming on:</h4>
|
||||||
<table class="full-width invisible streaming-links">
|
<table class="full-width invisible streaming-links">
|
||||||
@ -59,13 +59,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($show_data['streaming_links'] as $link): ?>
|
<?php foreach ($data['streaming_links'] as $link): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="align-left">
|
<td class="align-left">
|
||||||
<?php if ($link['meta']['link'] !== FALSE): ?>
|
<?php if ($link['meta']['link'] !== FALSE): ?>
|
||||||
<a
|
<a
|
||||||
href="<?= $link['link'] ?>"
|
href="<?= $link['link'] ?>"
|
||||||
title="Stream '<?= $show_data['title'] ?>' on <?= $link['meta']['name'] ?>"
|
title="Stream '<?= $data['title'] ?>' on <?= $link['meta']['name'] ?>"
|
||||||
>
|
>
|
||||||
<?= $helper->picture("images/{$link['meta']['image']}", 'svg', [
|
<?= $helper->picture("images/{$link['meta']['image']}", 'svg', [
|
||||||
'class' => 'streaming-logo',
|
'class' => 'streaming-logo',
|
||||||
@ -92,13 +92,13 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if ( ! empty($show_data['trailer_id'])): ?>
|
<?php if ( ! empty($data['trailer_id'])): ?>
|
||||||
<div class="responsive-iframe">
|
<div class="responsive-iframe">
|
||||||
<h4>Trailer</h4>
|
<h4>Trailer</h4>
|
||||||
<iframe
|
<iframe
|
||||||
width="560"
|
width="560"
|
||||||
height="315"
|
height="315"
|
||||||
src="https://www.youtube.com/embed/<?= $show_data['trailer_id'] ?>"
|
src="https://www.youtube.com/embed/<?= $data['trailer_id'] ?>"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
allow="autoplay; encrypted-media"
|
allow="autoplay; encrypted-media"
|
||||||
allowfullscreen
|
allowfullscreen
|
||||||
@ -108,13 +108,13 @@
|
|||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php if (count($characters) > 0): ?>
|
<?php if (count($data['characters']) > 0): ?>
|
||||||
<section>
|
<section>
|
||||||
<h2>Characters</h2>
|
<h2>Characters</h2>
|
||||||
|
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<?php $i = 0 ?>
|
<?php $i = 0 ?>
|
||||||
<?php foreach ($characters as $role => $list): ?>
|
<?php foreach ($data['characters'] as $role => $list): ?>
|
||||||
<input
|
<input
|
||||||
type="radio" name="character-types"
|
type="radio" name="character-types"
|
||||||
id="character-types-<?= $i ?>" <?= ($i === 0) ? 'checked' : '' ?> />
|
id="character-types-<?= $i ?>" <?= ($i === 0) ? 'checked' : '' ?> />
|
||||||
@ -140,14 +140,14 @@
|
|||||||
</section>
|
</section>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (count($staff) > 0): ?>
|
<?php if (count($data['staff']) > 0): ?>
|
||||||
<?php //dump($staff); ?>
|
<?php //dump($data['staff']); ?>
|
||||||
<section>
|
<section>
|
||||||
<h2>Staff</h2>
|
<h2>Staff</h2>
|
||||||
|
|
||||||
<div class="vertical-tabs">
|
<div class="vertical-tabs">
|
||||||
<?php $i = 0; ?>
|
<?php $i = 0; ?>
|
||||||
<?php foreach ($staff as $role => $people): ?>
|
<?php foreach ($data['staff'] as $role => $people): ?>
|
||||||
<div class="tab">
|
<div class="tab">
|
||||||
<input type="radio" name="staff-roles" id="staff-role<?= $i ?>" <?= $i === 0 ? 'checked' : '' ?> />
|
<input type="radio" name="staff-roles" id="staff-role<?= $i ?>" <?= $i === 0 ? 'checked' : '' ?> />
|
||||||
<label for="staff-role<?= $i ?>"><?= $role ?></label>
|
<label for="staff-role<?= $i ?>"><?= $role ?></label>
|
||||||
|
@ -7,10 +7,10 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
<main class="details fixed">
|
<main class="details fixed">
|
||||||
<section class="flex flex-no-wrap">
|
<section class="flex flex-no-wrap">
|
||||||
<div>
|
<div>
|
||||||
<?= $helper->picture("images/characters/{$data[0]['id']}-original.webp") ?>
|
<?= $helper->picture("images/characters/{$data['id']}-original.webp") ?>
|
||||||
<?php if ( ! empty($data[0]['attributes']['otherNames'])): ?>
|
<?php if ( ! empty($data['otherNames'])): ?>
|
||||||
<h3>Nicknames / Other names</h3>
|
<h3>Nicknames / Other names</h3>
|
||||||
<?php foreach ($data[0]['attributes']['otherNames'] as $name): ?>
|
<?php foreach ($data['otherNames'] as $name): ?>
|
||||||
<h4><?= $name ?></h4>
|
<h4><?= $name ?></h4>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
@ -23,19 +23,19 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<p class="description"><?= $data[0]['attributes']['description'] ?></p>
|
<p class="description"><?= $data['description'] ?></p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php if (array_key_exists('anime', $data['included']) || array_key_exists('manga', $data['included'])): ?>
|
<?php if (array_key_exists('anime', $data['media']) || array_key_exists('manga', $data['media'])): ?>
|
||||||
<h3>Media</h3>
|
<h3>Media</h3>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<?php if (array_key_exists('anime', $data['included'])): ?>
|
<?php if (array_key_exists('anime', $data['media'])): ?>
|
||||||
<input checked="checked" type="radio" id="media-anime" name="media-tabs" />
|
<input checked="checked" type="radio" id="media-anime" name="media-tabs" />
|
||||||
<label for="media-anime">Anime</label>
|
<label for="media-anime">Anime</label>
|
||||||
|
|
||||||
<section class="media-wrap content">
|
<section class="media-wrap content">
|
||||||
<?php foreach ($data['included']['anime'] as $id => $anime): ?>
|
<?php foreach ($data['media']['anime'] as $id => $anime): ?>
|
||||||
<article class="media">
|
<article class="media">
|
||||||
<?php
|
<?php
|
||||||
$link = $url->generate('anime.details', ['id' => $anime['attributes']['slug']]);
|
$link = $url->generate('anime.details', ['id' => $anime['attributes']['slug']]);
|
||||||
@ -58,12 +58,12 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
</section>
|
</section>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (array_key_exists('manga', $data['included'])): ?>
|
<?php if (array_key_exists('manga', $data['media'])): ?>
|
||||||
<input type="radio" id="media-manga" name="media-tabs" />
|
<input type="radio" id="media-manga" name="media-tabs" />
|
||||||
<label for="media-manga">Manga</label>
|
<label for="media-manga">Manga</label>
|
||||||
|
|
||||||
<section class="media-wrap content">
|
<section class="media-wrap content">
|
||||||
<?php foreach ($data['included']['manga'] as $id => $manga): ?>
|
<?php foreach ($data['media']['manga'] as $id => $manga): ?>
|
||||||
<article class="media">
|
<article class="media">
|
||||||
<?php
|
<?php
|
||||||
$link = $url->generate('manga.details', ['id' => $manga['attributes']['slug']]);
|
$link = $url->generate('manga.details', ['id' => $manga['attributes']['slug']]);
|
||||||
@ -89,14 +89,68 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<?php if ($castCount > 0): ?>
|
<?php if (count($data['castings']) > 0): ?>
|
||||||
<h3>Castings</h3>
|
<h3>Castings</h3>
|
||||||
<?php
|
<?php
|
||||||
$vas = $castings['Voice Actor'];
|
$vas = $data['castings']['Voice Actor'];
|
||||||
unset($castings['Voice Actor']);
|
unset($data['castings']['Voice Actor']);
|
||||||
ksort($vas)
|
ksort($vas)
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php foreach ($data['castings'] as $role => $entries): ?>
|
||||||
|
<h4><?= $role ?></h4>
|
||||||
|
<?php foreach ($entries as $language => $casting): ?>
|
||||||
|
<h5><?= $language ?></h5>
|
||||||
|
<table class="min-table">
|
||||||
|
<tr>
|
||||||
|
<th>Cast Member</th>
|
||||||
|
<th>Series</th>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($casting as $cid => $c): ?>
|
||||||
|
<tr>
|
||||||
|
<td style="width:229px">
|
||||||
|
<article class="character">
|
||||||
|
<?php
|
||||||
|
$link = $url->generate('person', ['id' => $c['person']['id']]);
|
||||||
|
?>
|
||||||
|
<a href="<?= $link ?>">
|
||||||
|
<?= $helper->picture(getLocalImg($c['person']['image'], TRUE)) ?>
|
||||||
|
<div class="name">
|
||||||
|
<?= $c['person']['name'] ?>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</article>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<section class="align-left media-wrap">
|
||||||
|
<?php foreach ($c['series'] as $series): ?>
|
||||||
|
<article class="media">
|
||||||
|
<?php
|
||||||
|
$link = $url->generate('anime.details', ['id' => $series['attributes']['slug']]);
|
||||||
|
$titles = Kitsu::filterTitles($series['attributes']);
|
||||||
|
?>
|
||||||
|
<a href="<?= $link ?>">
|
||||||
|
<?= $helper->picture(getLocalImg($series['attributes']['posterImage']['small'], TRUE)) ?>
|
||||||
|
</a>
|
||||||
|
<div class="name">
|
||||||
|
<a href="<?= $link ?>">
|
||||||
|
<?= array_shift($titles) ?>
|
||||||
|
<?php foreach ($titles as $title): ?>
|
||||||
|
<br />
|
||||||
|
<small><?= $title ?></small>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</section>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</table>
|
||||||
|
<?php endforeach ?>
|
||||||
|
<?php endforeach ?>
|
||||||
|
|
||||||
<?php if ( ! empty($vas)): ?>
|
<?php if ( ! empty($vas)): ?>
|
||||||
<h4>Voice Actors</h4>
|
<h4>Voice Actors</h4>
|
||||||
|
|
||||||
@ -161,61 +215,6 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
|
||||||
<?php foreach ($castings as $role => $entries): ?>
|
|
||||||
<h4><?= $role ?></h4>
|
|
||||||
<?php foreach ($entries as $language => $casting): ?>
|
|
||||||
<h5><?= $language ?></h5>
|
|
||||||
<table class="min-table">
|
|
||||||
<tr>
|
|
||||||
<th>Cast Member</th>
|
|
||||||
<th>Series</th>
|
|
||||||
</tr>
|
|
||||||
<?php foreach ($casting as $cid => $c): ?>
|
|
||||||
<tr>
|
|
||||||
<td style="width:229px">
|
|
||||||
<article class="character">
|
|
||||||
<?php
|
|
||||||
$link = $url->generate('person', ['id' => $c['person']['id']]);
|
|
||||||
?>
|
|
||||||
<a href="<?= $link ?>">
|
|
||||||
<?= $helper->picture(getLocalImg($c['person']['image'], TRUE)) ?>
|
|
||||||
<div class="name">
|
|
||||||
<?= $c['person']['name'] ?>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</article>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<section class="align-left media-wrap">
|
|
||||||
<?php foreach ($c['series'] as $series): ?>
|
|
||||||
<article class="media">
|
|
||||||
<?php
|
|
||||||
$link = $url->generate('anime.details', ['id' => $series['attributes']['slug']]);
|
|
||||||
$titles = Kitsu::filterTitles($series['attributes']);
|
|
||||||
?>
|
|
||||||
<a href="<?= $link ?>">
|
|
||||||
<?= $helper->picture(getLocalImg($series['attributes']['posterImage']['small'], TRUE)) ?>
|
|
||||||
</a>
|
|
||||||
<div class="name">
|
|
||||||
<a href="<?= $link ?>">
|
|
||||||
<?= array_shift($titles) ?>
|
|
||||||
<?php foreach ($titles as $title): ?>
|
|
||||||
<br />
|
|
||||||
<small><?= $title ?></small>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</section>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</table>
|
|
||||||
<?php endforeach ?>
|
|
||||||
<?php endforeach ?>
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
@ -5,7 +5,7 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
<h3>Voice Acting Roles</h3>
|
<h3>Voice Acting Roles</h3>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<?php $i = 0; ?>
|
<?php $i = 0; ?>
|
||||||
<?php foreach($characters as $role => $characterList): ?>
|
<?php foreach($data['characters'] as $role => $characterList): ?>
|
||||||
<input <?= $i === 0 ? 'checked="checked"' : '' ?> type="radio" name="character-type-tabs" id="character-type-<?= $i ?>" />
|
<input <?= $i === 0 ? 'checked="checked"' : '' ?> type="radio" name="character-type-tabs" id="character-type-<?= $i ?>" />
|
||||||
<label for="character-type-<?= $i ?>"><h5><?= ucfirst($role) ?></h5></label>
|
<label for="character-type-<?= $i ?>"><h5><?= ucfirst($role) ?></h5></label>
|
||||||
<section class="content">
|
<section class="content">
|
||||||
|
@ -9,16 +9,16 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
<?= $helper->picture("images/people/{$data['id']}-original.webp", 'jpg', ['class' => 'cover' ]) ?>
|
<?= $helper->picture("images/people/{$data['id']}-original.webp", 'jpg', ['class' => 'cover' ]) ?>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="toph"><?= $data['attributes']['name'] ?></h2>
|
<h2 class="toph"><?= $data['name'] ?></h2>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php if ( ! empty($staff)): ?>
|
<?php if ( ! empty($data['staff'])): ?>
|
||||||
<section>
|
<section>
|
||||||
<h3>Castings</h3>
|
<h3>Castings</h3>
|
||||||
<div class="vertical-tabs">
|
<div class="vertical-tabs">
|
||||||
<?php $i = 0 ?>
|
<?php $i = 0 ?>
|
||||||
<?php foreach ($staff as $role => $entries): ?>
|
<?php foreach ($data['staff'] as $role => $entries): ?>
|
||||||
<div class="tab">
|
<div class="tab">
|
||||||
<input
|
<input
|
||||||
type="radio" name="staff-roles" id="staff-role<?= $i ?>" <?= $i === 0 ? 'checked' : '' ?> />
|
type="radio" name="staff-roles" id="staff-role<?= $i ?>" <?= $i === 0 ? 'checked' : '' ?> />
|
||||||
@ -59,7 +59,7 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
</section>
|
</section>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if ( ! (empty($characters['main']) || empty($characters['supporting']))): ?>
|
<?php if ( ! (empty($data['characters']['main']) || empty($data['characters']['supporting']))): ?>
|
||||||
<section>
|
<section>
|
||||||
<?php include 'character-mapping.php' ?>
|
<?php include 'character-mapping.php' ?>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,45 +1,39 @@
|
|||||||
<?php
|
<?php
|
||||||
use function Aviat\AnimeClient\getLocalImg;
|
|
||||||
use Aviat\AnimeClient\API\Kitsu;
|
use Aviat\AnimeClient\API\Kitsu;
|
||||||
?>
|
?>
|
||||||
<main class="user-page details">
|
<main class="user-page details">
|
||||||
<h2 class="toph">
|
<h2 class="toph">
|
||||||
<?= $helper->a(
|
<?= $helper->a(
|
||||||
"https://kitsu.io/users/{$attributes['slug']}",
|
"https://kitsu.io/users/{$data['slug']}",
|
||||||
$attributes['name'], [
|
$data['name'], [
|
||||||
'title' => 'View profile on Kitsu'
|
'title' => 'View profile on Kitsu'
|
||||||
])
|
])
|
||||||
?>
|
?>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p><?= $escape->html($attributes['about']) ?></p>
|
<p><?= $escape->html($data['about']) ?></p>
|
||||||
|
|
||||||
<section class="flex flex-no-wrap">
|
<section class="flex flex-no-wrap">
|
||||||
<aside class="info">
|
<aside class="info">
|
||||||
<center>
|
<center>
|
||||||
<?php
|
<?= $helper->img($urlGenerator->assetUrl($data['avatar']), ['alt' => '']); ?>
|
||||||
$avatar = $urlGenerator->assetUrl(
|
|
||||||
getLocalImg($attributes['avatar']['original'], FALSE)
|
|
||||||
);
|
|
||||||
echo $helper->img($avatar, ['alt' => '']);
|
|
||||||
?>
|
|
||||||
</center>
|
</center>
|
||||||
<br />
|
<br />
|
||||||
<table class="media-details">
|
<table class="media-details">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Location</td>
|
<td>Location</td>
|
||||||
<td><?= $attributes['location'] ?></td>
|
<td><?= $data['location'] ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Website</td>
|
<td>Website</td>
|
||||||
<td><?= $helper->a($attributes['website'], $attributes['website']) ?></td>
|
<td><?= $helper->a($data['website'], $data['website']) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php if (array_key_exists('waifu', $relationships)): ?>
|
<?php if ( ! empty($data['waifu'])): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?= $escape->html($attributes['waifuOrHusbando']) ?></td>
|
<td><?= $escape->html($data['waifu']['label']) ?></td>
|
||||||
<td>
|
<td>
|
||||||
<?php
|
<?php
|
||||||
$character = $relationships['waifu']['attributes'];
|
$character = $data['waifu']['character'];
|
||||||
echo $helper->a(
|
echo $helper->a(
|
||||||
$url->generate('character', ['slug' => $character['slug']]),
|
$url->generate('character', ['slug' => $character['slug']]),
|
||||||
$character['canonicalName']
|
$character['canonicalName']
|
||||||
@ -52,42 +46,24 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
|
|
||||||
<h3>User Stats</h3><br />
|
<h3>User Stats</h3><br />
|
||||||
<table class="media-details">
|
<table class="media-details">
|
||||||
|
<?php foreach($data['stats'] as $label => $stat): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Time spent watching anime:</td>
|
<td><?= $label ?></td>
|
||||||
<td><?= $timeOnAnime ?></td>
|
<td><?= $stat ?></td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td># of Anime episodes watched</td>
|
|
||||||
<td><?= number_format($stats['anime-amount-consumed']['units']) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td># of Manga chapters read</td>
|
|
||||||
<td><?= number_format($stats['manga-amount-consumed']['units']) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td># of Posts</td>
|
|
||||||
<td><?= number_format($attributes['postsCount']) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td># of Comments</td>
|
|
||||||
<td><?= number_format($attributes['commentsCount']) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td># of Media Rated</td>
|
|
||||||
<td><?= number_format($attributes['ratingsCount']) ?></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
</table>
|
</table>
|
||||||
</aside>
|
</aside>
|
||||||
<article>
|
<article>
|
||||||
<?php if ( ! empty($favorites)): ?>
|
<?php if ( ! empty($data['favorites'])): ?>
|
||||||
<h3>Favorites</h3>
|
<h3>Favorites</h3>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<?php $i = 0 ?>
|
<?php $i = 0 ?>
|
||||||
<?php if ( ! empty($favorites['characters'])): ?>
|
<?php if ( ! empty($data['favorites']['characters'])): ?>
|
||||||
<input type="radio" name="user-favorites" id="user-fav-chars" <?= $i === 0 ? 'checked' : '' ?> />
|
<input type="radio" name="user-favorites" id="user-fav-chars" <?= $i === 0 ? 'checked' : '' ?> />
|
||||||
<label for="user-fav-chars">Characters</label>
|
<label for="user-fav-chars">Characters</label>
|
||||||
<section class="content full-width media-wrap">
|
<section class="content full-width media-wrap">
|
||||||
<?php foreach($favorites['characters'] as $id => $char): ?>
|
<?php foreach($data['favorites']['characters'] as $id => $char): ?>
|
||||||
<?php if ( ! empty($char['image']['original'])): ?>
|
<?php if ( ! empty($char['image']['original'])): ?>
|
||||||
<article class="character">
|
<article class="character">
|
||||||
<?php $link = $url->generate('character', ['slug' => $char['slug']]) ?>
|
<?php $link = $url->generate('character', ['slug' => $char['slug']]) ?>
|
||||||
@ -101,11 +77,11 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
</section>
|
</section>
|
||||||
<?php $i++; ?>
|
<?php $i++; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if ( ! empty($favorites['anime'])): ?>
|
<?php if ( ! empty($data['favorites']['anime'])): ?>
|
||||||
<input type="radio" name="user-favorites" id="user-fav-anime" <?= $i === 0 ? 'checked' : '' ?> />
|
<input type="radio" name="user-favorites" id="user-fav-anime" <?= $i === 0 ? 'checked' : '' ?> />
|
||||||
<label for="user-fav-anime">Anime</label>
|
<label for="user-fav-anime">Anime</label>
|
||||||
<section class="content full-width media-wrap">
|
<section class="content full-width media-wrap">
|
||||||
<?php foreach($favorites['anime'] as $anime): ?>
|
<?php foreach($data['favorites']['anime'] as $anime): ?>
|
||||||
<article class="media">
|
<article class="media">
|
||||||
<?php
|
<?php
|
||||||
$link = $url->generate('anime.details', ['id' => $anime['slug']]);
|
$link = $url->generate('anime.details', ['id' => $anime['slug']]);
|
||||||
@ -127,11 +103,11 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
</section>
|
</section>
|
||||||
<?php $i++; ?>
|
<?php $i++; ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if ( ! empty($favorites['manga'])): ?>
|
<?php if ( ! empty($data['favorites']['manga'])): ?>
|
||||||
<input type="radio" name="user-favorites" id="user-fav-manga" <?= $i === 0 ? 'checked' : '' ?> />
|
<input type="radio" name="user-favorites" id="user-fav-manga" <?= $i === 0 ? 'checked' : '' ?> />
|
||||||
<label for="user-fav-manga">Manga</label>
|
<label for="user-fav-manga">Manga</label>
|
||||||
<section class="content full-width media-wrap">
|
<section class="content full-width media-wrap">
|
||||||
<?php foreach($favorites['manga'] as $manga): ?>
|
<?php foreach($data['favorites']['manga'] as $manga): ?>
|
||||||
<article class="media">
|
<article class="media">
|
||||||
<?php
|
<?php
|
||||||
$link = $url->generate('manga.details', ['id' => $manga['slug']]);
|
$link = $url->generate('manga.details', ['id' => $manga['slug']]);
|
||||||
|
@ -18,7 +18,6 @@ namespace Aviat\AnimeClient\API\Kitsu\Transformer;
|
|||||||
|
|
||||||
use Aviat\AnimeClient\API\Kitsu;
|
use Aviat\AnimeClient\API\Kitsu;
|
||||||
use Aviat\AnimeClient\Types\{
|
use Aviat\AnimeClient\Types\{
|
||||||
Anime,
|
|
||||||
FormItem,
|
FormItem,
|
||||||
AnimeListItem
|
AnimeListItem
|
||||||
};
|
};
|
||||||
@ -95,7 +94,7 @@ final class AnimeListTransformer extends AbstractTransformer {
|
|||||||
'started' => $anime['startDate'],
|
'started' => $anime['startDate'],
|
||||||
'ended' => $anime['endDate']
|
'ended' => $anime['endDate']
|
||||||
],
|
],
|
||||||
'anime' => new Anime([
|
'anime' => [
|
||||||
'id' => $animeId,
|
'id' => $animeId,
|
||||||
'age_rating' => $anime['ageRating'],
|
'age_rating' => $anime['ageRating'],
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
@ -105,7 +104,7 @@ final class AnimeListTransformer extends AbstractTransformer {
|
|||||||
'cover_image' => $anime['posterImage']['small'],
|
'cover_image' => $anime['posterImage']['small'],
|
||||||
'genres' => $genres,
|
'genres' => $genres,
|
||||||
'streaming_links' => $streamingLinks,
|
'streaming_links' => $streamingLinks,
|
||||||
]),
|
],
|
||||||
'watching_status' => $item['attributes']['status'],
|
'watching_status' => $item['attributes']['status'],
|
||||||
'notes' => $item['attributes']['notes'],
|
'notes' => $item['attributes']['notes'],
|
||||||
'rewatching' => (bool) $item['attributes']['reconsuming'],
|
'rewatching' => (bool) $item['attributes']['reconsuming'],
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
namespace Aviat\AnimeClient\API\Kitsu\Transformer;
|
namespace Aviat\AnimeClient\API\Kitsu\Transformer;
|
||||||
|
|
||||||
use Aviat\AnimeClient\API\{JsonAPI, Kitsu};
|
use Aviat\AnimeClient\API\{JsonAPI, Kitsu};
|
||||||
use Aviat\AnimeClient\Types\Anime;
|
use Aviat\AnimeClient\Types\AnimePage;
|
||||||
use Aviat\Ion\Transformer\AbstractTransformer;
|
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,9 +30,9 @@ final class AnimeTransformer extends AbstractTransformer {
|
|||||||
* logical and workable structure
|
* logical and workable structure
|
||||||
*
|
*
|
||||||
* @param array $item API library item
|
* @param array $item API library item
|
||||||
* @return Anime
|
* @return AnimePage
|
||||||
*/
|
*/
|
||||||
public function transform($item): Anime
|
public function transform($item): AnimePage
|
||||||
{
|
{
|
||||||
$item['included'] = JsonAPI::organizeIncludes($item['included']);
|
$item['included'] = JsonAPI::organizeIncludes($item['included']);
|
||||||
$genres = $item['included']['categories'] ?? [];
|
$genres = $item['included']['categories'] ?? [];
|
||||||
@ -40,13 +40,74 @@ final class AnimeTransformer extends AbstractTransformer {
|
|||||||
sort($item['genres']);
|
sort($item['genres']);
|
||||||
|
|
||||||
$title = $item['canonicalTitle'];
|
$title = $item['canonicalTitle'];
|
||||||
|
|
||||||
$titles = Kitsu::filterTitles($item);
|
$titles = Kitsu::filterTitles($item);
|
||||||
// $titles = array_unique(array_diff($item['titles'], [$title]));
|
|
||||||
|
|
||||||
return new Anime([
|
$characters = [];
|
||||||
|
$staff = [];
|
||||||
|
|
||||||
|
if (array_key_exists('animeCharacters', $item['included']))
|
||||||
|
{
|
||||||
|
$animeCharacters = $item['included']['animeCharacters'];
|
||||||
|
|
||||||
|
foreach ($animeCharacters as $rel)
|
||||||
|
{
|
||||||
|
$charId = $rel['relationships']['character']['data']['id'];
|
||||||
|
$role = $rel['role'];
|
||||||
|
|
||||||
|
if (array_key_exists($charId, $item['included']['characters']))
|
||||||
|
{
|
||||||
|
$characters[$role][$charId] = $item['included']['characters'][$charId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('mediaStaff', $item['included']))
|
||||||
|
{
|
||||||
|
foreach ($item['included']['mediaStaff'] as $id => $staffing)
|
||||||
|
{
|
||||||
|
$personId = $staffing['relationships']['person']['data']['id'];
|
||||||
|
$personDetails = $item['included']['people'][$personId];
|
||||||
|
|
||||||
|
$role = $staffing['role'];
|
||||||
|
|
||||||
|
if ( ! array_key_exists($role, $staff))
|
||||||
|
{
|
||||||
|
$staff[$role] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$staff[$role][$personId] = [
|
||||||
|
'id' => $personId,
|
||||||
|
'name' => $personDetails['name'] ?? '??',
|
||||||
|
'image' => $personDetails['image'],
|
||||||
|
];
|
||||||
|
|
||||||
|
usort($staff[$role], function ($a, $b) {
|
||||||
|
return $a['name'] <=> $b['name'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($characters['main']))
|
||||||
|
{
|
||||||
|
uasort($characters['main'], function ($a, $b) {
|
||||||
|
return $a['name'] <=> $b['name'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($characters['supporting']))
|
||||||
|
{
|
||||||
|
uasort($characters['supporting'], function ($a, $b) {
|
||||||
|
return $a['name'] <=> $b['name'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($characters);
|
||||||
|
ksort($staff);
|
||||||
|
|
||||||
|
return new AnimePage([
|
||||||
'age_rating' => $item['ageRating'],
|
'age_rating' => $item['ageRating'],
|
||||||
'age_rating_guide' => $item['ageRatingGuide'],
|
'age_rating_guide' => $item['ageRatingGuide'],
|
||||||
|
'characters' => $characters,
|
||||||
'cover_image' => $item['posterImage']['small'],
|
'cover_image' => $item['posterImage']['small'],
|
||||||
'episode_count' => $item['episodeCount'],
|
'episode_count' => $item['episodeCount'],
|
||||||
'episode_length' => $item['episodeLength'],
|
'episode_length' => $item['episodeLength'],
|
||||||
@ -55,6 +116,7 @@ final class AnimeTransformer extends AbstractTransformer {
|
|||||||
'included' => $item['included'],
|
'included' => $item['included'],
|
||||||
'show_type' => $this->string($item['showType'])->upperCaseFirst()->__toString(),
|
'show_type' => $this->string($item['showType'])->upperCaseFirst()->__toString(),
|
||||||
'slug' => $item['slug'],
|
'slug' => $item['slug'],
|
||||||
|
'staff' => $staff,
|
||||||
'status' => Kitsu::getAiringStatus($item['startDate'], $item['endDate']),
|
'status' => Kitsu::getAiringStatus($item['startDate'], $item['endDate']),
|
||||||
'streaming_links' => Kitsu::parseStreamingLinks($item['included']),
|
'streaming_links' => Kitsu::parseStreamingLinks($item['included']),
|
||||||
'synopsis' => $item['synopsis'],
|
'synopsis' => $item['synopsis'],
|
||||||
|
173
src/API/Kitsu/Transformer/CharacterTransformer.php
Normal file
173
src/API/Kitsu/Transformer/CharacterTransformer.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?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\API\Kitsu\Transformer;
|
||||||
|
|
||||||
|
use Aviat\AnimeClient\API\JsonAPI;
|
||||||
|
use Aviat\AnimeClient\Types\Character;
|
||||||
|
|
||||||
|
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data transformation class for zippered Hummingbird manga
|
||||||
|
*/
|
||||||
|
final class CharacterTransformer extends AbstractTransformer {
|
||||||
|
|
||||||
|
public function transform($characterData): Character
|
||||||
|
{
|
||||||
|
$data = JsonAPI::organizeData($characterData);
|
||||||
|
$attributes = $data[0]['attributes'];
|
||||||
|
$castings = [];
|
||||||
|
|
||||||
|
$names = array_unique(
|
||||||
|
array_merge(
|
||||||
|
[$attributes['canonicalName']],
|
||||||
|
$attributes['names']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$name = array_shift($names);
|
||||||
|
|
||||||
|
if (array_key_exists('included', $data))
|
||||||
|
{
|
||||||
|
if (array_key_exists('anime', $data['included']))
|
||||||
|
{
|
||||||
|
uasort($data['included']['anime'], function ($a, $b) {
|
||||||
|
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('manga', $data['included']))
|
||||||
|
{
|
||||||
|
uasort($data['included']['manga'], function ($a, $b) {
|
||||||
|
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('castings', $data['included']))
|
||||||
|
{
|
||||||
|
$castings = $this->organizeCast($data['included']['castings']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Character([
|
||||||
|
'castings' => $castings,
|
||||||
|
'description' => $attributes['description'],
|
||||||
|
'id' => $data[0]['id'],
|
||||||
|
'media' => [
|
||||||
|
'anime' => $data['included']['anime'] ?? [],
|
||||||
|
'manga' => $data['included']['manga'] ?? [],
|
||||||
|
],
|
||||||
|
'name' => $name,
|
||||||
|
'names' => $names,
|
||||||
|
'otherNames' => $attributes['otherNames'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Organize VA => anime relationships
|
||||||
|
*
|
||||||
|
* @param array $cast
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function dedupeCast(array $cast): array
|
||||||
|
{
|
||||||
|
$output = [];
|
||||||
|
$people = [];
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
foreach ($cast as &$role)
|
||||||
|
{
|
||||||
|
if (empty($role['attributes']['role']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$person = current($role['relationships']['person']['people'])['attributes'];
|
||||||
|
$hasName = array_key_exists($person['name'], $people);
|
||||||
|
|
||||||
|
if ( ! $hasName)
|
||||||
|
{
|
||||||
|
$people[$person['name']] = $i;
|
||||||
|
$role['relationships']['media']['anime'] = [current($role['relationships']['media']['anime'])];
|
||||||
|
$output[$i] = $role;
|
||||||
|
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('anime', $role['relationships']['media']))
|
||||||
|
{
|
||||||
|
$key = $people[$person['name']];
|
||||||
|
$output[$key]['relationships']['media']['anime'][] = current($role['relationships']['media']['anime']);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function organizeCast(array $cast): array
|
||||||
|
{
|
||||||
|
$cast = $this->dedupeCast($cast);
|
||||||
|
$output = [];
|
||||||
|
|
||||||
|
foreach ($cast as $id => $role)
|
||||||
|
{
|
||||||
|
if (empty($role['attributes']['role']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$language = $role['attributes']['language'];
|
||||||
|
$roleName = $role['attributes']['role'];
|
||||||
|
$isVA = $role['attributes']['voiceActor'];
|
||||||
|
|
||||||
|
if ($isVA)
|
||||||
|
{
|
||||||
|
foreach ($role['relationships']['person']['people'] as $pid => $peoples)
|
||||||
|
{
|
||||||
|
$p = $peoples;
|
||||||
|
}
|
||||||
|
|
||||||
|
$person = $p['attributes'];
|
||||||
|
$person['id'] = $pid;
|
||||||
|
$person['image'] = $person['image']['original'];
|
||||||
|
|
||||||
|
uasort($role['relationships']['media']['anime'], function ($a, $b) {
|
||||||
|
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$item = [
|
||||||
|
'person' => $person,
|
||||||
|
'series' => $role['relationships']['media']['anime']
|
||||||
|
];
|
||||||
|
|
||||||
|
$output[$roleName][$language][] = $item;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
foreach ($role['relationships']['person']['people'] as $pid => $person)
|
||||||
|
{
|
||||||
|
$person['id'] = $pid;
|
||||||
|
$output[$roleName][$pid] = $person;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
132
src/API/Kitsu/Transformer/PersonTransformer.php
Normal file
132
src/API/Kitsu/Transformer/PersonTransformer.php
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<?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\API\Kitsu\Transformer;
|
||||||
|
|
||||||
|
use Aviat\AnimeClient\API\JsonAPI;
|
||||||
|
use Aviat\AnimeClient\Types\Person;
|
||||||
|
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data transformation class for zippered Hummingbird manga
|
||||||
|
*/
|
||||||
|
final class PersonTransformer extends AbstractTransformer {
|
||||||
|
|
||||||
|
public function transform($personData): Person
|
||||||
|
{
|
||||||
|
$data = JsonAPI::organizeData($personData);
|
||||||
|
$included = JsonAPI::organizeIncludes($personData['included']);
|
||||||
|
|
||||||
|
$orgData = $this->organizeData($included);
|
||||||
|
|
||||||
|
return new Person([
|
||||||
|
'id' => $data['id'],
|
||||||
|
'name' => $data['attributes']['name'],
|
||||||
|
'characters' => $orgData['characters'],
|
||||||
|
'staff' => $orgData['staff'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function organizeData(array $data): array
|
||||||
|
{
|
||||||
|
$output = [
|
||||||
|
'characters' => [
|
||||||
|
'main' => [],
|
||||||
|
'supporting' => [],
|
||||||
|
],
|
||||||
|
'staff' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (array_key_exists('characterVoices', $data))
|
||||||
|
{
|
||||||
|
foreach ($data['characterVoices'] as $cv)
|
||||||
|
{
|
||||||
|
$mcId = $cv['relationships']['mediaCharacter']['data']['id'];
|
||||||
|
|
||||||
|
if ( ! array_key_exists($mcId, $data['mediaCharacters']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mc = $data['mediaCharacters'][$mcId];
|
||||||
|
|
||||||
|
$role = $mc['role'];
|
||||||
|
|
||||||
|
$charId = $mc['relationships']['character']['data']['id'];
|
||||||
|
$mediaId = $mc['relationships']['media']['data']['id'];
|
||||||
|
|
||||||
|
$existingMedia = array_key_exists($charId, $output['characters'][$role])
|
||||||
|
? $output['characters'][$role][$charId]['media']
|
||||||
|
: [];
|
||||||
|
|
||||||
|
$relatedMedia = [
|
||||||
|
$mediaId => $data['anime'][$mediaId],
|
||||||
|
];
|
||||||
|
|
||||||
|
$includedMedia = array_replace_recursive($existingMedia, $relatedMedia);
|
||||||
|
|
||||||
|
uasort($includedMedia, function ($a, $b) {
|
||||||
|
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$character = $data['characters'][$charId];
|
||||||
|
|
||||||
|
$output['characters'][$role][$charId] = [
|
||||||
|
'character' => $character,
|
||||||
|
'media' => $includedMedia,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('mediaStaff', $data))
|
||||||
|
{
|
||||||
|
foreach ($data['mediaStaff'] as $rid => $role)
|
||||||
|
{
|
||||||
|
$roleName = $role['role'];
|
||||||
|
$mediaType = $role['relationships']['media']['data']['type'];
|
||||||
|
$mediaId = $role['relationships']['media']['data']['id'];
|
||||||
|
$media = $data[$mediaType][$mediaId];
|
||||||
|
$output['staff'][$roleName][$mediaType][$mediaId] = $media;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uasort($output['characters']['main'], function ($a, $b) {
|
||||||
|
return $a['character']['canonicalName'] <=> $b['character']['canonicalName'];
|
||||||
|
});
|
||||||
|
uasort($output['characters']['supporting'], function ($a, $b) {
|
||||||
|
return $a['character']['canonicalName'] <=> $b['character']['canonicalName'];
|
||||||
|
});
|
||||||
|
ksort($output['staff']);
|
||||||
|
foreach ($output['staff'] as $role => &$media)
|
||||||
|
{
|
||||||
|
if (array_key_exists('anime', $media))
|
||||||
|
{
|
||||||
|
uasort($media['anime'], function ($a, $b) {
|
||||||
|
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('manga', $media))
|
||||||
|
{
|
||||||
|
uasort($media['manga'], function ($a, $b) {
|
||||||
|
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
147
src/API/Kitsu/Transformer/UserTransformer.php
Normal file
147
src/API/Kitsu/Transformer/UserTransformer.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?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\API\Kitsu\Transformer;
|
||||||
|
|
||||||
|
use function Aviat\AnimeClient\getLocalImg;
|
||||||
|
|
||||||
|
use Aviat\AnimeClient\API\JsonAPI;
|
||||||
|
use Aviat\AnimeClient\Types\User;
|
||||||
|
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform user profile data for display
|
||||||
|
*/
|
||||||
|
final class UserTransformer extends AbstractTransformer {
|
||||||
|
public function transform($profileData): User
|
||||||
|
{
|
||||||
|
$orgData = JsonAPI::organizeData($profileData)[0];
|
||||||
|
$attributes = $orgData['attributes'];
|
||||||
|
|
||||||
|
$rels = $orgData['relationships'] ?? [];
|
||||||
|
$favorites = array_key_exists('favorites', $rels) ? $rels['favorites'] : [];
|
||||||
|
|
||||||
|
$stats = [];
|
||||||
|
foreach ($rels['stats'] as $sid => &$item)
|
||||||
|
{
|
||||||
|
$key = $item['attributes']['kind'];
|
||||||
|
$stats[$key] = $item['attributes']['statsData'];
|
||||||
|
unset($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$waifu = [];
|
||||||
|
if (array_key_exists('waifu', $rels))
|
||||||
|
{
|
||||||
|
$waifu = [
|
||||||
|
'label' => $attributes['waifuOrHusbando'],
|
||||||
|
'character' => $rels['waifu']['attributes'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new User([
|
||||||
|
'about' => $attributes['about'],
|
||||||
|
'avatar' => getLocalImg($attributes['avatar']['original'], FALSE),
|
||||||
|
'favorites' => $this->organizeFavorites($favorites),
|
||||||
|
'location' => $attributes['location'],
|
||||||
|
'name' => $attributes['name'],
|
||||||
|
'slug' => $attributes['slug'],
|
||||||
|
'stats' => $this->organizeStats($stats, $attributes),
|
||||||
|
'waifu' => $waifu,
|
||||||
|
'website' => $attributes['website'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorganize favorites data to be more useful
|
||||||
|
*
|
||||||
|
* @param array $rawFavorites
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function organizeFavorites(array $rawFavorites): array
|
||||||
|
{
|
||||||
|
$output = [];
|
||||||
|
|
||||||
|
unset($rawFavorites['data']);
|
||||||
|
|
||||||
|
foreach ($rawFavorites as $item)
|
||||||
|
{
|
||||||
|
$rank = $item['attributes']['favRank'];
|
||||||
|
foreach ($item['relationships']['item'] as $key => $fav)
|
||||||
|
{
|
||||||
|
$output[$key] = $output[$key] ?? [];
|
||||||
|
foreach ($fav as $id => $data)
|
||||||
|
{
|
||||||
|
$output[$key][$rank] = array_merge(['id' => $id], $data['attributes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($output[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the time spent on anime in a more readable format
|
||||||
|
*
|
||||||
|
* @param int $minutes
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function formatAnimeTime(int $minutes): string
|
||||||
|
{
|
||||||
|
$minutesPerDay = 1440;
|
||||||
|
$minutesPerYear = $minutesPerDay * 365;
|
||||||
|
|
||||||
|
// Minutes short of a year
|
||||||
|
$years = (int)floor($minutes / $minutesPerYear);
|
||||||
|
$minutes %= $minutesPerYear;
|
||||||
|
|
||||||
|
// Minutes short of a day
|
||||||
|
$extraMinutes = $minutes % $minutesPerDay;
|
||||||
|
|
||||||
|
$days = ($minutes - $extraMinutes) / $minutesPerDay;
|
||||||
|
|
||||||
|
// Minutes short of an hour
|
||||||
|
$remMinutes = $extraMinutes % 60;
|
||||||
|
|
||||||
|
$hours = ($extraMinutes - $remMinutes) / 60;
|
||||||
|
|
||||||
|
$output = "{$days} days, {$hours} hours, and {$remMinutes} minutes.";
|
||||||
|
|
||||||
|
if ($years > 0)
|
||||||
|
{
|
||||||
|
$output = "{$years} year(s),{$output}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function organizeStats($stats, $data): array
|
||||||
|
{
|
||||||
|
// $timeOnAnime = $this->formatAnimeTime($orgData['attributes']['lifeSpentOnAnime']);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'Time spent watching anime:' => $this->formatAnimeTime($stats['anime-amount-consumed']['time']),
|
||||||
|
'Anime series watched:' => number_format($stats['anime-amount-consumed']['media']),
|
||||||
|
'Anime episodes watched:' => number_format($stats['anime-amount-consumed']['units']),
|
||||||
|
'Manga series read:' => number_format($stats['manga-amount-consumed']['media']),
|
||||||
|
'Manga chapters read:' => number_format($stats['manga-amount-consumed']['units']),
|
||||||
|
'Posts:' => number_format($data['postsCount']),
|
||||||
|
'Comments:' => number_format($data['commentsCount']),
|
||||||
|
'Media Rated:' => number_format($data['ratingsCount']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -23,15 +23,11 @@ use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
|
|||||||
use Aviat\AnimeClient\Types\FormItem;
|
use Aviat\AnimeClient\Types\FormItem;
|
||||||
use Aviat\Ion\Di\ContainerInterface;
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
use Aviat\Ion\Json;
|
use Aviat\Ion\Json;
|
||||||
use Aviat\Ion\StringWrapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for Anime-related pages
|
* Controller for Anime-related pages
|
||||||
*/
|
*/
|
||||||
final class Anime extends BaseController {
|
final class Anime extends BaseController {
|
||||||
|
|
||||||
use StringWrapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The anime list model
|
* The anime list model
|
||||||
* @var \Aviat\AnimeClient\Model\Anime $model
|
* @var \Aviat\AnimeClient\Model\Anime $model
|
||||||
@ -276,8 +272,6 @@ final class Anime extends BaseController {
|
|||||||
public function details(string $animeId): void
|
public function details(string $animeId): void
|
||||||
{
|
{
|
||||||
$data = $this->model->getAnime($animeId);
|
$data = $this->model->getAnime($animeId);
|
||||||
$characters = [];
|
|
||||||
$staff = [];
|
|
||||||
|
|
||||||
if (empty($data))
|
if (empty($data))
|
||||||
{
|
{
|
||||||
@ -291,77 +285,13 @@ final class Anime extends BaseController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('animeCharacters', $data['included']))
|
|
||||||
{
|
|
||||||
$animeCharacters = $data['included']['animeCharacters'];
|
|
||||||
|
|
||||||
foreach ($animeCharacters as $rel)
|
|
||||||
{
|
|
||||||
$charId = $rel['relationships']['character']['data']['id'];
|
|
||||||
$role = $rel['role'];
|
|
||||||
|
|
||||||
if (array_key_exists($charId, $data['included']['characters']))
|
|
||||||
{
|
|
||||||
$characters[$role][$charId] = $data['included']['characters'][$charId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('mediaStaff', $data['included']))
|
|
||||||
{
|
|
||||||
foreach ($data['included']['mediaStaff'] as $id => $staffing)
|
|
||||||
{
|
|
||||||
$personId = $staffing['relationships']['person']['data']['id'];
|
|
||||||
$personDetails = $data['included']['people'][$personId];
|
|
||||||
|
|
||||||
$role = $staffing['role'];
|
|
||||||
|
|
||||||
if ( ! array_key_exists($role, $staff))
|
|
||||||
{
|
|
||||||
$staff[$role] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$staff[$role][$personId] = [
|
|
||||||
'id' => $personId,
|
|
||||||
'name' => $personDetails['name'] ?? '??',
|
|
||||||
'image' => $personDetails['image'],
|
|
||||||
];
|
|
||||||
|
|
||||||
usort($staff[$role], function ($a, $b) {
|
|
||||||
return $a['name'] <=> $b['name'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty($characters['main']))
|
|
||||||
{
|
|
||||||
uasort($characters['main'], function ($a, $b) {
|
|
||||||
return $a['name'] <=> $b['name'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty($characters['supporting']))
|
|
||||||
{
|
|
||||||
uasort($characters['supporting'], function ($a, $b) {
|
|
||||||
return $a['name'] <=> $b['name'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ksort($characters);
|
|
||||||
ksort($staff);
|
|
||||||
|
|
||||||
// dump($characters);
|
|
||||||
// dump($staff);
|
|
||||||
|
|
||||||
$this->outputHTML('anime/details', [
|
$this->outputHTML('anime/details', [
|
||||||
'title' => $this->formatTitle(
|
'title' => $this->formatTitle(
|
||||||
$this->config->get('whose_list') . "'s Anime List",
|
$this->config->get('whose_list') . "'s Anime List",
|
||||||
'Anime',
|
'Anime',
|
||||||
$data->title
|
$data->title
|
||||||
),
|
),
|
||||||
'characters' => $characters,
|
'data' => $data,
|
||||||
'show_data' => $data,
|
|
||||||
'staff' => $staff,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,30 +17,42 @@
|
|||||||
namespace Aviat\AnimeClient\Controller;
|
namespace Aviat\AnimeClient\Controller;
|
||||||
|
|
||||||
use Aviat\AnimeClient\Controller as BaseController;
|
use Aviat\AnimeClient\Controller as BaseController;
|
||||||
use Aviat\AnimeClient\API\JsonAPI;
|
use Aviat\AnimeClient\API\Kitsu\Transformer\CharacterTransformer;
|
||||||
use Aviat\Ion\ArrayWrapper;
|
|
||||||
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for character description pages
|
* Controller for character description pages
|
||||||
*/
|
*/
|
||||||
class Character extends BaseController {
|
class Character extends BaseController {
|
||||||
|
|
||||||
use ArrayWrapper;
|
/**
|
||||||
|
* @var \Aviat\AnimeClient\API\Kitsu\Model
|
||||||
|
*/
|
||||||
|
private $model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Character constructor.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $container
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\ContainerException
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\NotFoundException
|
||||||
|
*/
|
||||||
|
public function __construct(ContainerInterface $container)
|
||||||
|
{
|
||||||
|
parent::__construct($container);
|
||||||
|
$this->model = $container->get('kitsu-model');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show information about a character
|
* Show information about a character
|
||||||
*
|
*
|
||||||
* @param string $slug
|
* @param string $slug
|
||||||
* @throws \Aviat\Ion\Di\ContainerException
|
|
||||||
* @throws \Aviat\Ion\Di\NotFoundException
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function index(string $slug): void
|
public function index(string $slug): void
|
||||||
{
|
{
|
||||||
$model = $this->container->get('kitsu-model');
|
$rawData = $this->model->getCharacter($slug);
|
||||||
|
|
||||||
$rawData = $model->getCharacter($slug);
|
|
||||||
|
|
||||||
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
|
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
|
||||||
{
|
{
|
||||||
@ -55,167 +67,14 @@ class Character extends BaseController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = JsonAPI::organizeData($rawData);
|
$data = (new CharacterTransformer())->transform($rawData)->toArray();
|
||||||
|
|
||||||
$data['names'] = array_unique(
|
$this->outputHTML('character/details', [
|
||||||
array_merge(
|
|
||||||
[ $data[0]['attributes']['canonicalName'] ],
|
|
||||||
$data[0]['attributes']['names']
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$data['name'] = array_shift($data['names']);
|
|
||||||
|
|
||||||
if (array_key_exists('included', $data))
|
|
||||||
{
|
|
||||||
if (array_key_exists('anime', $data['included']))
|
|
||||||
{
|
|
||||||
uasort($data['included']['anime'], function ($a, $b) {
|
|
||||||
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('manga', $data['included']))
|
|
||||||
{
|
|
||||||
uasort($data['included']['manga'], function ($a, $b) {
|
|
||||||
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$viewData = [
|
|
||||||
'title' => $this->formatTitle(
|
'title' => $this->formatTitle(
|
||||||
'Characters',
|
'Characters',
|
||||||
$data[0]['attributes']['name']
|
$data['name']
|
||||||
),
|
),
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
'castCount' => 0,
|
]);
|
||||||
'castings' => []
|
|
||||||
];
|
|
||||||
|
|
||||||
if (array_key_exists('included', $data))
|
|
||||||
{
|
|
||||||
if (array_key_exists('castings', $data['included']))
|
|
||||||
{
|
|
||||||
$viewData['castings'] = $this->organizeCast($data['included']['castings']);
|
|
||||||
$viewData['castCount'] = $this->getCastCount($viewData['castings']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->outputHTML('character/details', $viewData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Organize VA => anime relationships
|
|
||||||
*
|
|
||||||
* @param array $cast
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function dedupeCast(array $cast): array
|
|
||||||
{
|
|
||||||
$output = [];
|
|
||||||
$people = [];
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
foreach ($cast as &$role)
|
|
||||||
{
|
|
||||||
if (empty($role['attributes']['role']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$person = current($role['relationships']['person']['people'])['attributes'];
|
|
||||||
$hasName = array_key_exists($person['name'], $people);
|
|
||||||
|
|
||||||
if ( ! $hasName)
|
|
||||||
{
|
|
||||||
$people[$person['name']] = $i;
|
|
||||||
$role['relationships']['media']['anime'] = [current($role['relationships']['media']['anime'])];
|
|
||||||
$output[$i] = $role;
|
|
||||||
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('anime', $role['relationships']['media']))
|
|
||||||
{
|
|
||||||
$key = $people[$person['name']];
|
|
||||||
$output[$key]['relationships']['media']['anime'][] = current($role['relationships']['media']['anime']);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getCastCount(array $cast): int
|
|
||||||
{
|
|
||||||
$count = 0;
|
|
||||||
|
|
||||||
foreach($cast as $role)
|
|
||||||
{
|
|
||||||
$count++;
|
|
||||||
/* if (
|
|
||||||
array_key_exists('attributes', $role) &&
|
|
||||||
array_key_exists('role', $role['attributes']) &&
|
|
||||||
$role['attributes']['role'] !== NULL
|
|
||||||
) {
|
|
||||||
$count++;
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
return $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function organizeCast(array $cast): array
|
|
||||||
{
|
|
||||||
$cast = $this->dedupeCast($cast);
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
foreach($cast as $id => $role)
|
|
||||||
{
|
|
||||||
if (empty($role['attributes']['role']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$language = $role['attributes']['language'];
|
|
||||||
$roleName = $role['attributes']['role'];
|
|
||||||
$isVA = $role['attributes']['voiceActor'];
|
|
||||||
|
|
||||||
if ($isVA)
|
|
||||||
{
|
|
||||||
foreach($role['relationships']['person']['people'] as $pid => $peoples)
|
|
||||||
{
|
|
||||||
$p = $peoples;
|
|
||||||
}
|
|
||||||
|
|
||||||
$person = $p['attributes'];
|
|
||||||
$person['id'] = $pid;
|
|
||||||
$person['image'] = $person['image']['original'];
|
|
||||||
|
|
||||||
uasort($role['relationships']['media']['anime'], function ($a, $b) {
|
|
||||||
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
|
||||||
});
|
|
||||||
|
|
||||||
$item = [
|
|
||||||
'person' => $person,
|
|
||||||
'series' => $role['relationships']['media']['anime']
|
|
||||||
];
|
|
||||||
|
|
||||||
$output[$roleName][$language][] = $item;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach($role['relationships']['person']['people'] as $pid => $person)
|
|
||||||
{
|
|
||||||
$person['id'] = $pid;
|
|
||||||
$output[$roleName][$pid] = $person;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,12 +17,33 @@
|
|||||||
namespace Aviat\AnimeClient\Controller;
|
namespace Aviat\AnimeClient\Controller;
|
||||||
|
|
||||||
use Aviat\AnimeClient\Controller as BaseController;
|
use Aviat\AnimeClient\Controller as BaseController;
|
||||||
use Aviat\AnimeClient\API\JsonAPI;
|
use Aviat\AnimeClient\API\Kitsu\Transformer\PersonTransformer;
|
||||||
|
|
||||||
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for People pages
|
* Controller for People pages
|
||||||
*/
|
*/
|
||||||
final class People extends BaseController {
|
final class People extends BaseController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Aviat\AnimeClient\API\Kitsu\Model
|
||||||
|
*/
|
||||||
|
private $model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* People constructor.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $container
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\ContainerException
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\NotFoundException
|
||||||
|
*/
|
||||||
|
public function __construct(ContainerInterface $container)
|
||||||
|
{
|
||||||
|
parent::__construct($container);
|
||||||
|
$this->model = $container->get('kitsu-model');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show information about a person
|
* Show information about a person
|
||||||
*
|
*
|
||||||
@ -31,9 +52,8 @@ final class People extends BaseController {
|
|||||||
*/
|
*/
|
||||||
public function index(string $id): void
|
public function index(string $id): void
|
||||||
{
|
{
|
||||||
$model = $this->container->get('kitsu-model');
|
$rawData = $this->model->getPerson($id);
|
||||||
|
$data = (new PersonTransformer())->transform($rawData)->toArray();
|
||||||
$rawData = $model->getPerson($id);
|
|
||||||
|
|
||||||
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
|
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
|
||||||
{
|
{
|
||||||
@ -48,114 +68,12 @@ final class People extends BaseController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = JsonAPI::organizeData($rawData);
|
$this->outputHTML('person/details', [
|
||||||
$included = JsonAPI::organizeIncludes($rawData['included']);
|
|
||||||
|
|
||||||
$orgData = $this->organizeData($included);
|
|
||||||
|
|
||||||
$viewData = [
|
|
||||||
'included' => $included,
|
|
||||||
'title' => $this->formatTitle(
|
'title' => $this->formatTitle(
|
||||||
'People',
|
'People',
|
||||||
$data['attributes']['name']
|
$data['name']
|
||||||
),
|
),
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
'castCount' => 0,
|
]);
|
||||||
'castings' => [],
|
|
||||||
'characters' => $orgData['characters'],
|
|
||||||
'staff' => $orgData['staff'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->outputHTML('person/details', $viewData);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function organizeData(array $data): array
|
|
||||||
{
|
|
||||||
$output = [
|
|
||||||
'characters' => [
|
|
||||||
'main' => [],
|
|
||||||
'supporting' => [],
|
|
||||||
],
|
|
||||||
'staff' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
if (array_key_exists('characterVoices', $data))
|
|
||||||
{
|
|
||||||
foreach ($data['characterVoices'] as $cv)
|
|
||||||
{
|
|
||||||
$mcId = $cv['relationships']['mediaCharacter']['data']['id'];
|
|
||||||
|
|
||||||
if ( ! array_key_exists($mcId, $data['mediaCharacters']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mc = $data['mediaCharacters'][$mcId];
|
|
||||||
|
|
||||||
$role = $mc['role'];
|
|
||||||
|
|
||||||
$charId = $mc['relationships']['character']['data']['id'];
|
|
||||||
$mediaId = $mc['relationships']['media']['data']['id'];
|
|
||||||
|
|
||||||
$existingMedia = array_key_exists($charId, $output['characters'][$role])
|
|
||||||
? $output['characters'][$role][$charId]['media']
|
|
||||||
: [];
|
|
||||||
|
|
||||||
$relatedMedia = [
|
|
||||||
$mediaId => $data['anime'][$mediaId],
|
|
||||||
];
|
|
||||||
|
|
||||||
$includedMedia = array_replace_recursive($existingMedia, $relatedMedia);
|
|
||||||
|
|
||||||
uasort($includedMedia, function ($a, $b) {
|
|
||||||
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
|
||||||
});
|
|
||||||
|
|
||||||
$character = $data['characters'][$charId];
|
|
||||||
|
|
||||||
$output['characters'][$role][$charId] = [
|
|
||||||
'character' => $character,
|
|
||||||
'media' => $includedMedia,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('mediaStaff', $data))
|
|
||||||
{
|
|
||||||
foreach($data['mediaStaff'] as $rid => $role)
|
|
||||||
{
|
|
||||||
$roleName = $role['role'];
|
|
||||||
$mediaType = $role['relationships']['media']['data']['type'];
|
|
||||||
$mediaId = $role['relationships']['media']['data']['id'];
|
|
||||||
$media = $data[$mediaType][$mediaId];
|
|
||||||
$output['staff'][$roleName][$mediaType][$mediaId] = $media;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uasort($output['characters']['main'], function ($a, $b) {
|
|
||||||
return $a['character']['canonicalName'] <=> $b['character']['canonicalName'];
|
|
||||||
});
|
|
||||||
uasort($output['characters']['supporting'], function ($a, $b) {
|
|
||||||
return $a['character']['canonicalName'] <=> $b['character']['canonicalName'];
|
|
||||||
});
|
|
||||||
ksort($output['staff']);
|
|
||||||
foreach($output['staff'] as $role => &$media)
|
|
||||||
{
|
|
||||||
if (array_key_exists('anime', $media))
|
|
||||||
{
|
|
||||||
uasort($media['anime'], function ($a, $b) {
|
|
||||||
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('manga', $media))
|
|
||||||
{
|
|
||||||
uasort($media['manga'], function ($a, $b) {
|
|
||||||
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ use Aviat\Ion\Di\ContainerInterface;
|
|||||||
*/
|
*/
|
||||||
final class Settings extends BaseController {
|
final class Settings extends BaseController {
|
||||||
/**
|
/**
|
||||||
* @var \Aviat\API\Anilist\Model
|
* @var \Aviat\AnimeClient\API\Anilist\Model
|
||||||
*/
|
*/
|
||||||
private $anilistModel;
|
private $anilistModel;
|
||||||
|
|
||||||
@ -33,6 +33,13 @@ final class Settings extends BaseController {
|
|||||||
*/
|
*/
|
||||||
private $settingsModel;
|
private $settingsModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings constructor.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $container
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\ContainerException
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\NotFoundException
|
||||||
|
*/
|
||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container)
|
||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
@ -44,7 +51,7 @@ final class Settings extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* Show the user settings, if logged in
|
* Show the user settings, if logged in
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index(): void
|
||||||
{
|
{
|
||||||
$auth = $this->container->get('auth');
|
$auth = $this->container->get('auth');
|
||||||
$form = $this->settingsModel->getSettingsForm();
|
$form = $this->settingsModel->getSettingsForm();
|
||||||
@ -66,7 +73,7 @@ final class Settings extends BaseController {
|
|||||||
*
|
*
|
||||||
* @throws \Aura\Router\Exception\RouteNotFound
|
* @throws \Aura\Router\Exception\RouteNotFound
|
||||||
*/
|
*/
|
||||||
public function update()
|
public function update(): void
|
||||||
{
|
{
|
||||||
$post = $this->request->getParsedBody();
|
$post = $this->request->getParsedBody();
|
||||||
unset($post['settings-tabs']);
|
unset($post['settings-tabs']);
|
||||||
@ -88,22 +95,23 @@ final class Settings extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* Redirect to Anilist to start Oauth flow
|
* Redirect to Anilist to start Oauth flow
|
||||||
*/
|
*/
|
||||||
public function anilistRedirect()
|
public function anilistRedirect(): void
|
||||||
{
|
{
|
||||||
$redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' .
|
$query = http_build_query([
|
||||||
http_build_query([
|
|
||||||
'client_id' => $this->config->get(['anilist', 'client_id']),
|
'client_id' => $this->config->get(['anilist', 'client_id']),
|
||||||
'redirect_uri' => $this->urlGenerator->url('/anilist-oauth'),
|
'redirect_uri' => $this->urlGenerator->url('/anilist-oauth'),
|
||||||
'response_type' => 'code',
|
'response_type' => 'code',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$redirectUrl = "https://anilist.co/api/v2/oauth/authorize?{$query}";
|
||||||
|
|
||||||
$this->redirect($redirectUrl, 303);
|
$this->redirect($redirectUrl, 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Oauth callback for Anilist API
|
* Oauth callback for Anilist API
|
||||||
*/
|
*/
|
||||||
public function anilistCallback()
|
public function anilistCallback(): void
|
||||||
{
|
{
|
||||||
$query = $this->request->getQueryParams();
|
$query = $this->request->getQueryParams();
|
||||||
$authCode = $query['code'];
|
$authCode = $query['code'];
|
||||||
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\Controller;
|
namespace Aviat\AnimeClient\Controller;
|
||||||
|
|
||||||
|
use Aviat\AnimeClient\API\Kitsu\Transformer\UserTransformer;
|
||||||
use Aviat\AnimeClient\Controller as BaseController;
|
use Aviat\AnimeClient\Controller as BaseController;
|
||||||
use Aviat\AnimeClient\API\JsonAPI;
|
|
||||||
use Aviat\Ion\Di\ContainerInterface;
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +26,18 @@ use Aviat\Ion\Di\ContainerInterface;
|
|||||||
*/
|
*/
|
||||||
final class User extends BaseController {
|
final class User extends BaseController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Aviat\AnimeClient\API\Kitsu\Model
|
||||||
|
*/
|
||||||
private $kitsuModel;
|
private $kitsuModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User constructor.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $container
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\ContainerException
|
||||||
|
* @throws \Aviat\Ion\Di\Exception\NotFoundException
|
||||||
|
*/
|
||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container)
|
||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
@ -56,103 +67,16 @@ final class User extends BaseController {
|
|||||||
? $this->config->get(['kitsu_username'])
|
? $this->config->get(['kitsu_username'])
|
||||||
: $username;
|
: $username;
|
||||||
|
|
||||||
$data = $this->kitsuModel->getUserData($username);
|
|
||||||
$orgData = JsonAPI::organizeData($data)[0];
|
|
||||||
$rels = $orgData['relationships'] ?? [];
|
|
||||||
$favorites = array_key_exists('favorites', $rels) ? $rels['favorites'] : [];
|
|
||||||
|
|
||||||
$stats = [];
|
|
||||||
foreach ($rels['stats'] as $sid => &$item)
|
|
||||||
{
|
|
||||||
$key = $item['attributes']['kind'];
|
|
||||||
$stats[$key] = $item['attributes']['statsData'];
|
|
||||||
unset($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
//dump($orgData);
|
|
||||||
// dump($stats);
|
|
||||||
|
|
||||||
// $timeOnAnime = $this->formatAnimeTime($orgData['attributes']['lifeSpentOnAnime']);
|
|
||||||
$timeOnAnime = $this->formatAnimeTime($stats['anime-amount-consumed']['time']);
|
|
||||||
|
|
||||||
|
|
||||||
$whom = $isMainUser
|
$whom = $isMainUser
|
||||||
? $this->config->get('whose_list')
|
? $this->config->get('whose_list')
|
||||||
: $username;
|
: $username;
|
||||||
|
|
||||||
|
$rawData = $this->kitsuModel->getUserData($username);
|
||||||
|
$data = (new UserTransformer())->transform($rawData)->toArray();
|
||||||
|
|
||||||
$this->outputHTML('user/details', [
|
$this->outputHTML('user/details', [
|
||||||
'title' => 'About ' . $whom,
|
'title' => 'About ' . $whom,
|
||||||
'data' => $orgData,
|
'data' => $data,
|
||||||
'attributes' => $orgData['attributes'],
|
|
||||||
'relationships' => $rels,
|
|
||||||
'favorites' => $this->organizeFavorites($favorites),
|
|
||||||
'stats' => $stats,
|
|
||||||
'timeOnAnime' => $timeOnAnime,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reorganize favorites data to be more useful
|
|
||||||
*
|
|
||||||
* @param array $rawFavorites
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function organizeFavorites(array $rawFavorites): array
|
|
||||||
{
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
unset($rawFavorites['data']);
|
|
||||||
|
|
||||||
foreach ($rawFavorites as $item)
|
|
||||||
{
|
|
||||||
$rank = $item['attributes']['favRank'];
|
|
||||||
foreach ($item['relationships']['item'] as $key => $fav)
|
|
||||||
{
|
|
||||||
$output[$key] = $output[$key] ?? [];
|
|
||||||
foreach ($fav as $id => $data)
|
|
||||||
{
|
|
||||||
$output[$key][$rank] = array_merge(['id' => $id], $data['attributes']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ksort($output[$key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the time spent on anime in a more readable format
|
|
||||||
*
|
|
||||||
* @param int $minutes
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function formatAnimeTime(int $minutes): string
|
|
||||||
{
|
|
||||||
$minutesPerDay = 1440;
|
|
||||||
$minutesPerYear = $minutesPerDay * 365;
|
|
||||||
|
|
||||||
// Minutes short of a year
|
|
||||||
$years = (int)floor($minutes / $minutesPerYear);
|
|
||||||
$minutes %= $minutesPerYear;
|
|
||||||
|
|
||||||
// Minutes short of a day
|
|
||||||
$extraMinutes = $minutes % $minutesPerDay;
|
|
||||||
|
|
||||||
$days = ($minutes - $extraMinutes) / $minutesPerDay;
|
|
||||||
|
|
||||||
// Minutes short of an hour
|
|
||||||
$remMinutes = $extraMinutes % 60;
|
|
||||||
|
|
||||||
$hours = ($extraMinutes - $remMinutes) / 60;
|
|
||||||
|
|
||||||
$output = "{$days} days, {$hours} hours, and {$remMinutes} minutes.";
|
|
||||||
|
|
||||||
if ($years > 0)
|
|
||||||
{
|
|
||||||
$output = "{$years} year(s),{$output}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -17,9 +17,9 @@
|
|||||||
namespace Aviat\AnimeClient\Types;
|
namespace Aviat\AnimeClient\Types;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type representing an Anime object for display
|
* Type representing an anime within a watch list
|
||||||
*/
|
*/
|
||||||
final class Anime extends AbstractType {
|
class Anime extends AbstractType {
|
||||||
public $age_rating;
|
public $age_rating;
|
||||||
public $age_rating_guide;
|
public $age_rating_guide;
|
||||||
public $cover_image;
|
public $cover_image;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
namespace Aviat\AnimeClient\Types;
|
namespace Aviat\AnimeClient\Types;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type representing an Anime object for display
|
* Type representing an anime watch list item
|
||||||
*/
|
*/
|
||||||
final class AnimeListItem extends AbstractType {
|
final class AnimeListItem extends AbstractType {
|
||||||
public $id;
|
public $id;
|
||||||
@ -40,4 +40,9 @@ final class AnimeListItem extends AbstractType {
|
|||||||
public $rewatched;
|
public $rewatched;
|
||||||
public $user_rating;
|
public $user_rating;
|
||||||
public $watching_status;
|
public $watching_status;
|
||||||
|
|
||||||
|
public function setAnime($anime): void
|
||||||
|
{
|
||||||
|
$this->anime = new Anime($anime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
src/Types/AnimePage.php
Normal file
25
src/Types/AnimePage.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?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\Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type representing an Anime object for a detail page
|
||||||
|
*/
|
||||||
|
final class AnimePage extends Anime {
|
||||||
|
public $characters;
|
||||||
|
public $staff;
|
||||||
|
}
|
39
src/Types/Character.php
Normal file
39
src/Types/Character.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?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\Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type representing a character for display
|
||||||
|
*/
|
||||||
|
final class Character extends AbstractType {
|
||||||
|
public $castings;
|
||||||
|
public $description;
|
||||||
|
public $id;
|
||||||
|
public $included;
|
||||||
|
public $media;
|
||||||
|
public $name;
|
||||||
|
public $names;
|
||||||
|
public $otherNames;
|
||||||
|
|
||||||
|
public function setMedia ($media): void
|
||||||
|
{
|
||||||
|
$this->media = new class($media) extends AbstractType {
|
||||||
|
public $anime;
|
||||||
|
public $manga;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
35
src/Types/Person.php
Normal file
35
src/Types/Person.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?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\Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type representing a person for display
|
||||||
|
*/
|
||||||
|
final class Person extends AbstractType {
|
||||||
|
public $id;
|
||||||
|
public $name;
|
||||||
|
public $characters;
|
||||||
|
public $staff;
|
||||||
|
|
||||||
|
public function setCharacters($characters): void
|
||||||
|
{
|
||||||
|
$this->characters = new class($characters) extends AbstractType {
|
||||||
|
public $main;
|
||||||
|
public $supporting;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
32
src/Types/User.php
Normal file
32
src/Types/User.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?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\Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type representing a Kitsu user for display
|
||||||
|
*/
|
||||||
|
final class User extends AbstractType {
|
||||||
|
public $about;
|
||||||
|
public $avatar;
|
||||||
|
public $favorites;
|
||||||
|
public $location;
|
||||||
|
public $name;
|
||||||
|
public $slug;
|
||||||
|
public $stats;
|
||||||
|
public $waifu;
|
||||||
|
public $website;
|
||||||
|
}
|
@ -1,4 +1,10 @@
|
|||||||
<?php return Aviat\AnimeClient\Types\Anime::__set_state(array(
|
<?php return Aviat\AnimeClient\Types\AnimePage::__set_state(array(
|
||||||
|
'characters' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'staff' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
'age_rating' => 'R',
|
'age_rating' => 'R',
|
||||||
'age_rating_guide' => 'Violence, Profanity',
|
'age_rating_guide' => 'Violence, Profanity',
|
||||||
'cover_image' => 'https://media.kitsu.io/anime/poster_images/7442/small.jpg?1418580054',
|
'cover_image' => 'https://media.kitsu.io/anime/poster_images/7442/small.jpg?1418580054',
|
||||||
|
Loading…
Reference in New Issue
Block a user