Ugly Progress Commit
All checks were successful
timw4mail/HummingBirdAnimeClient/develop This commit looks good
All checks were successful
timw4mail/HummingBirdAnimeClient/develop This commit looks good
* Update Person pages to have series organized by character for Voice Acting * Miscellaneous style updates * Add placeholder images for items missing images
This commit is contained in:
parent
14be365a16
commit
50b65d66e1
@ -1,6 +1,6 @@
|
||||
<main class="details fixed">
|
||||
<section class="flex flex-no-wrap">
|
||||
<div>
|
||||
<section class="flex">
|
||||
<aside class="info">
|
||||
<picture class="cover">
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/anime/{$show_data['id']}-original.webp") ?>" type="image/webp">
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/anime/{$show_data['id']}-original.jpg") ?>" type="image/jpeg">
|
||||
@ -40,8 +40,8 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
</aside>
|
||||
<article class="text">
|
||||
<h2><a rel="external" href="<?= $show_data['url'] ?>"><?= $show_data['title'] ?></a></h2>
|
||||
<?php foreach ($show_data['titles'] as $title): ?>
|
||||
<h3><?= $title ?></h3>
|
||||
@ -85,13 +85,13 @@
|
||||
<h4>Trailer</h4>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/<?= $show_data['trailer_id'] ?>" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<?php if (count($characters) > 0): ?>
|
||||
<hr />
|
||||
<br />
|
||||
<h2>Characters</h2>
|
||||
<section class="align_center media-wrap">
|
||||
<section class="media-wrap flex flex-wrap flex-justify-start">
|
||||
<?php foreach($characters as $id => $char): ?>
|
||||
<?php if ( ! empty($char['image']['original'])): ?>
|
||||
<article class="character">
|
||||
|
@ -4,18 +4,29 @@ use Aviat\AnimeClient\API\Kitsu;
|
||||
?>
|
||||
<main class="details fixed">
|
||||
<section class="flex flex-no-wrap">
|
||||
<div>
|
||||
<picture class="cover">
|
||||
<aside class="info cover">
|
||||
<picture>
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/characters/{$data[0]['id']}-original.webp") ?>" type="image/webp">
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/characters/{$data[0]['id']}-original.jpg") ?>" type="image/jpeg">
|
||||
<img src="<?= $urlGenerator->assetUrl("images/characters/{$data[0]['id']}-original.jpg") ?>" alt="" />
|
||||
</picture>
|
||||
</div>
|
||||
<div>
|
||||
<h2><?= $data[0]['attributes']['name'] ?></h2>
|
||||
<?php if ( ! empty($data[0]['attributes']['otherNames'])): ?>
|
||||
<h3>Nicknames / Other names</h3>
|
||||
<?php foreach ($data[0]['attributes']['otherNames'] as $name): ?>
|
||||
<h4><?= $name ?></h4>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
</aside>
|
||||
<article class="text">
|
||||
<h2><?= $data['name'] ?></h2>
|
||||
<?php foreach ($data['names'] as $name): ?>
|
||||
<h3><?= $name ?></h3>
|
||||
<?php endforeach ?>
|
||||
|
||||
<hr />
|
||||
|
||||
<p class="description"><?= $data[0]['attributes']['description'] ?></p>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<?php if (array_key_exists('anime', $data['included']) || array_key_exists('manga', $data['included'])): ?>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<main class="details fixed">
|
||||
<section class="flex flex-no-wrap">
|
||||
<div>
|
||||
<aside class="info">
|
||||
<picture class="cover">
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/manga/{$data['id']}-original.webp") ?>" type="image/webp">
|
||||
<source srcset="<?= $urlGenerator->assetUrl("images/manga/{$data['id']}-original.jpg") ?>" type="image/jpeg">
|
||||
@ -28,8 +28,8 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
</aside>
|
||||
<article class="text">
|
||||
<h2><a rel="external" href="<?= $data['url'] ?>"><?= $data['title'] ?></a></h2>
|
||||
<?php foreach($data['titles'] as $title): ?>
|
||||
<h3><?= $title ?></h3>
|
||||
@ -37,12 +37,12 @@
|
||||
|
||||
<br />
|
||||
<p><?= nl2br($data['synopsis']) ?></p>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<?php if (count($characters) > 0): ?>
|
||||
<h2>Characters</h2>
|
||||
<section class="media-wrap">
|
||||
<section class="media-wrap flex flex-wrap flex-justify-start">
|
||||
<?php foreach($characters as $id => $char): ?>
|
||||
<?php if ( ! empty($char['image']['original'])): ?>
|
||||
<article class="character">
|
||||
|
62
app/views/person/character-mapping.php
Normal file
62
app/views/person/character-mapping.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
use function Aviat\AnimeClient\getLocalImg;
|
||||
use Aviat\AnimeClient\API\Kitsu;
|
||||
?>
|
||||
<?php foreach ($entries as $type => $casting): ?>
|
||||
<?php if($type === 'characters'): ?>
|
||||
<table class="min-table">
|
||||
<tr>
|
||||
<th>Character</th>
|
||||
<th>Series</th>
|
||||
</tr>
|
||||
<?php foreach ($casting as $cid => $character): ?>
|
||||
<tr>
|
||||
<td style="width:229px">
|
||||
<article class="character">
|
||||
<?php
|
||||
$link = $url->generate('character', ['slug' => $character['character']['slug']]);
|
||||
?>
|
||||
<a href="<?= $link ?>">
|
||||
<?php $imgPath = ($character['character']['image'] === NULL)
|
||||
? $urlGenerator->assetUrl('images/characters/empty.png')
|
||||
: $urlGenerator->assetUrl(getLocalImg($character['character']['image']['original']));
|
||||
?>
|
||||
<img src="<?= $imgPath ?>" alt="" />
|
||||
<div class="name">
|
||||
<?= $character['character']['canonicalName'] ?>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
</td>
|
||||
<td>
|
||||
<section class="align_left media-wrap">
|
||||
<?php foreach ($character['media'] as $sid => $series): ?>
|
||||
<article class="media">
|
||||
<?php
|
||||
$link = $url->generate('anime.details', ['id' => $series['slug']]);
|
||||
$titles = Kitsu::filterTitles($series);
|
||||
?>
|
||||
<a href="<?= $link ?>">
|
||||
<img
|
||||
src="<?= $urlGenerator->assetUrl("images/anime/{$sid}.jpg") ?>"
|
||||
width="220" alt=""
|
||||
/>
|
||||
</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 endif ?>
|
||||
<?php endforeach ?>
|
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
use function Aviat\AnimeClient\getLocalImg;
|
||||
use Aviat\AnimeClient\API\Kitsu;
|
||||
?>
|
||||
<main class="details fixed">
|
||||
@ -27,7 +26,11 @@ use Aviat\AnimeClient\API\Kitsu;
|
||||
<h3>Castings</h3>
|
||||
<?php foreach ($castings as $role => $entries): ?>
|
||||
<h4><?= $role ?></h4>
|
||||
<?php if($role === 'Voice Actor'): ?>
|
||||
<?php include 'character-mapping.php' ?>
|
||||
<?php else: ?>
|
||||
<?php foreach ($entries as $type => $casting): ?>
|
||||
<?php if ($type === 'characters') continue; ?>
|
||||
<?php if ( ! empty($entries['manga'])): ?>
|
||||
<h5><?= ucfirst($type) ?></h5>
|
||||
<?php endif ?>
|
||||
@ -68,6 +71,7 @@ use Aviat\AnimeClient\API\Kitsu;
|
||||
</section>
|
||||
<br />
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
</section>
|
@ -24,6 +24,7 @@
|
||||
"aura/session": "^2.0",
|
||||
"aviat/banker": "^1.0.0",
|
||||
"aviat/ion": "^2.4.1",
|
||||
"ext-iconv": "*",
|
||||
"ext-json": "*",
|
||||
"ext-gd":"*",
|
||||
"ext-pdo": "*",
|
||||
|
@ -20,6 +20,8 @@ use Aviat\AnimeClient\Types\Config as ConfigType;
|
||||
|
||||
use function Aviat\Ion\_dir;
|
||||
|
||||
setlocale(LC_CTYPE, 'en_US');
|
||||
|
||||
// Work around the silly timezone error
|
||||
$timezone = ini_get('date.timezone');
|
||||
if ($timezone === '' || $timezone === FALSE)
|
||||
|
2
public/css/app.min.css
vendored
2
public/css/app.min.css
vendored
File diff suppressed because one or more lines are too long
@ -91,6 +91,10 @@ a:hover, a:active {
|
||||
flex-wrap: nowrap
|
||||
}
|
||||
|
||||
.flex-align-start {
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.flex-align-end {
|
||||
align-items: flex-end
|
||||
}
|
||||
@ -99,6 +103,10 @@ a:hover, a:active {
|
||||
align-content: space-around
|
||||
}
|
||||
|
||||
.flex-justify-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.flex-justify-space-around {
|
||||
justify-content: space-around
|
||||
}
|
||||
@ -107,6 +115,10 @@ a:hover, a:active {
|
||||
align-self: center
|
||||
}
|
||||
|
||||
.flex-space-evenly {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex
|
||||
}
|
||||
@ -671,7 +683,13 @@ picture.cover {
|
||||
}
|
||||
|
||||
.fixed {
|
||||
max-width: 93rem;
|
||||
max-width: 100rem;
|
||||
/* max-width: 80%; */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.fixed .text {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.details .cover {
|
||||
@ -684,14 +702,10 @@ picture.cover {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.details .flex > div {
|
||||
.details .flex > * {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.details .media_details {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.details .media_details td {
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
@ -752,6 +766,15 @@ picture.cover {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
aside.info {
|
||||
max-width: 390px;
|
||||
}
|
||||
|
||||
aside.info picture, aside.info img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
User page styles
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
BIN
public/images/placeholder.png
Normal file
BIN
public/images/placeholder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 242 B |
@ -101,27 +101,28 @@ final class JsonAPI {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Single data item
|
||||
else if (array_key_exists('id', $props['data']))
|
||||
if (array_key_exists('id', $props['data']))
|
||||
{
|
||||
$idKey = $props['data']['id'];
|
||||
$typeKey = $props['data']['type'];
|
||||
$dataType = $props['data']['type'];
|
||||
$relationship =& $item['relationships'][$relType];
|
||||
unset($relationship['data']);
|
||||
|
||||
if (in_array($relType, $singular))
|
||||
if (\in_array($relType, $singular, TRUE))
|
||||
{
|
||||
$relationship = $included[$typeKey][$idKey];
|
||||
$relationship = $included[$dataType][$idKey];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($relType === $typeKey)
|
||||
if ($relType === $dataType)
|
||||
{
|
||||
$relationship[$idKey] = $included[$typeKey][$idKey];
|
||||
$relationship[$idKey] = $included[$dataType][$idKey];
|
||||
continue;
|
||||
}
|
||||
|
||||
$relationship[$typeKey][$idKey] = $included[$typeKey][$idKey];
|
||||
$relationship[$dataType][$idKey] = $included[$dataType][$idKey];
|
||||
}
|
||||
// Multiple data items
|
||||
else
|
||||
@ -129,16 +130,16 @@ final class JsonAPI {
|
||||
foreach($props['data'] as $j => $datum)
|
||||
{
|
||||
$idKey = $props['data'][$j]['id'];
|
||||
$typeKey = $props['data'][$j]['type'];
|
||||
$dataType = $props['data'][$j]['type'];
|
||||
$relationship =& $item['relationships'][$relType];
|
||||
|
||||
if ($relType === $typeKey)
|
||||
if ($relType === $dataType)
|
||||
{
|
||||
$relationship[$idKey] = $included[$typeKey][$idKey];
|
||||
$relationship[$idKey] = $included[$dataType][$idKey];
|
||||
continue;
|
||||
}
|
||||
|
||||
$relationship[$typeKey][$idKey][$j] = $included[$typeKey][$idKey];
|
||||
$relationship[$dataType][$idKey][$j] = $included[$dataType][$idKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,29 +202,33 @@ final class JsonAPI {
|
||||
{
|
||||
foreach($items as $id => $item)
|
||||
{
|
||||
if (array_key_exists('relationships', $item) && is_array($item['relationships']))
|
||||
if (array_key_exists('relationships', $item) && \is_array($item['relationships']))
|
||||
{
|
||||
foreach($item['relationships'] as $relType => $props)
|
||||
{
|
||||
if (array_key_exists('data', $props) && is_array($props['data']) && array_key_exists('id', $props['data']))
|
||||
{
|
||||
if (array_key_exists($props['data']['id'], $organized[$props['data']['type']]))
|
||||
if (array_key_exists('data', $props) && \is_array($props['data']) && array_key_exists('id', $props['data']))
|
||||
{
|
||||
$idKey = $props['data']['id'];
|
||||
$typeKey = $props['data']['type'];
|
||||
$dataType = $props['data']['type'];
|
||||
|
||||
if ( ! array_key_exists($dataType, $organized))
|
||||
{
|
||||
$organized[$dataType] = [];
|
||||
}
|
||||
|
||||
$relationship =& $organized[$type][$id]['relationships'][$relType];
|
||||
unset($relationship['links']);
|
||||
unset($relationship['data']);
|
||||
|
||||
if ($relType === $typeKey)
|
||||
if ($relType === $dataType)
|
||||
{
|
||||
$relationship[$idKey] = $included[$typeKey][$idKey];
|
||||
$relationship[$idKey] = $included[$dataType][$idKey];
|
||||
continue;
|
||||
}
|
||||
|
||||
$relationship[$typeKey][$idKey] = $organized[$typeKey][$idKey];
|
||||
if (array_key_exists($idKey, $organized[$dataType]))
|
||||
{
|
||||
$relationship[$dataType][$idKey] = $organized[$dataType][$idKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,11 +229,26 @@ final class Model {
|
||||
*/
|
||||
public function getPerson(string $id): array
|
||||
{
|
||||
return $this->getRequest("people/{$id}", [
|
||||
$cacheItem = $this->cache->getItem("kitsu-person-{$id}");
|
||||
|
||||
if ( ! $cacheItem->isHit())
|
||||
{
|
||||
$data = $this->getRequest("people/{$id}", [
|
||||
'query' => [
|
||||
'include' => 'castings,castings.media,staff,staff.media,voices'
|
||||
'fields' => [
|
||||
'characters' => 'canonicalName,slug,image',
|
||||
'anime' => 'canonicalTitle,titles,slug,posterImage',
|
||||
'manga' => 'canonicalTitle,titles,slug,posterImage',
|
||||
],
|
||||
'include' => 'castings.character,castings.media'
|
||||
],
|
||||
]);
|
||||
|
||||
$cacheItem->set($data);
|
||||
$cacheItem->save();
|
||||
}
|
||||
|
||||
return $cacheItem->get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -206,14 +206,14 @@ function getLocalImg ($kitsuUrl): string
|
||||
{
|
||||
if ( ! is_string($kitsuUrl))
|
||||
{
|
||||
return '/404';
|
||||
return 'images/404/404.png';
|
||||
}
|
||||
|
||||
$parts = parse_url($kitsuUrl);
|
||||
|
||||
if ($parts === FALSE)
|
||||
{
|
||||
return '/404';
|
||||
return 'images/404/404.png';
|
||||
}
|
||||
|
||||
$file = basename($parts['path']);
|
||||
@ -221,11 +221,51 @@ function getLocalImg ($kitsuUrl): string
|
||||
$ext = array_pop($fileParts);
|
||||
$segments = explode('/', trim($parts['path'], '/'));
|
||||
|
||||
// dump($segments);
|
||||
|
||||
$type = $segments[0] === 'users' ? $segments[1] : $segments[0];
|
||||
|
||||
$id = $segments[count($segments) - 2];
|
||||
|
||||
return implode('/', ['images', $type, "{$id}.{$ext}"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transparent placeholder image
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $text
|
||||
*/
|
||||
function createPlaceholderImage ($path, $width, $height, $text = 'Image Unavailable')
|
||||
{
|
||||
$width = $width ?? 200;
|
||||
$height = $height ?? 200;
|
||||
|
||||
$img = imagecreate($width, $height);
|
||||
|
||||
$path = rtrim($path, '/');
|
||||
|
||||
// Background is the first color by default
|
||||
imagecolorallocatealpha($img, 255, 255, 255, 127);
|
||||
$textColor = imagecolorallocate($img, 64, 64, 64);
|
||||
|
||||
imagealphablending($img, TRUE);
|
||||
|
||||
// Generate placeholder text
|
||||
$fontSize = 10;
|
||||
$fontWidth = imagefontwidth($fontSize);
|
||||
$fontHeight = imagefontheight($fontSize);
|
||||
$length = strlen($text);
|
||||
$textWidth = $length * $fontWidth;
|
||||
$fxPos = (int) ceil((imagesx($img) - $textWidth) / 2);
|
||||
$fyPos = (int) ceil((imagesy($img) - $fontHeight) / 2);
|
||||
|
||||
// Add the image text
|
||||
imagestring($img, $fontSize, $fxPos, $fyPos, $text, $textColor);
|
||||
|
||||
// Save the images
|
||||
imagesavealpha($img, TRUE);
|
||||
imagepng($img, $path . '/placeholder.png', 9);
|
||||
|
||||
imagedestroy($img);
|
||||
}
|
@ -59,6 +59,14 @@ class Character extends BaseController {
|
||||
|
||||
$data = JsonAPI::organizeData($rawData);
|
||||
|
||||
$data['names'] = array_unique(
|
||||
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']))
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
namespace Aviat\AnimeClient\Controller;
|
||||
|
||||
use function Aviat\AnimeClient\createPlaceholderImage;
|
||||
use function Amp\Promise\wait;
|
||||
|
||||
use Aviat\AnimeClient\Controller as BaseController;
|
||||
@ -269,45 +270,60 @@ final class Index extends BaseController {
|
||||
$fileName = str_replace('-original', '', $file);
|
||||
[$id, $ext] = explode('.', basename($fileName));
|
||||
|
||||
$baseSavePath = $this->config->get('img_cache_path');
|
||||
|
||||
$typeMap = [
|
||||
'anime' => [
|
||||
'kitsuUrl' => "anime/poster_images/{$id}/medium.{$ext}",
|
||||
'width' => 220,
|
||||
'height' => 312,
|
||||
],
|
||||
'avatars' => [
|
||||
'kitsuUrl' => "users/avatars/{$id}/original.{$ext}",
|
||||
'width' => null,
|
||||
'height' => null,
|
||||
],
|
||||
'characters' => [
|
||||
'kitsuUrl' => "characters/images/{$id}/original.{$ext}",
|
||||
'width' => 225,
|
||||
'height' => 350,
|
||||
],
|
||||
'manga' => [
|
||||
'kitsuUrl' => "manga/poster_images/{$id}/medium.{$ext}",
|
||||
'width' => 220,
|
||||
'height' => 312,
|
||||
],
|
||||
'people' => [
|
||||
'kitsuUrl' => "people/images/{$id}/original.{$ext}",
|
||||
'width' => null,
|
||||
'height' => null,
|
||||
],
|
||||
];
|
||||
|
||||
if ( ! array_key_exists($type, $typeMap))
|
||||
{
|
||||
$this->notFound();
|
||||
$this->getPlaceholder($baseSavePath, 100, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
$kitsuUrl .= $typeMap[$type]['kitsuUrl'];
|
||||
$width = $typeMap[$type]['width'];
|
||||
$height = $typeMap[$type]['height'];
|
||||
|
||||
$promise = (new HummingbirdClient)->request($kitsuUrl);
|
||||
$response = wait($promise);
|
||||
|
||||
if ($response->getStatus() !== 200)
|
||||
{
|
||||
if ($display)
|
||||
{
|
||||
$this->getPlaceholder("{$baseSavePath}/{$type}", $width, $height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$data = wait($response->getBody());
|
||||
|
||||
// echo "Fetching {$kitsuUrl}\n";
|
||||
|
||||
$baseSavePath = $this->config->get('img_cache_path');
|
||||
$filePrefix = "{$baseSavePath}/{$type}/{$id}";
|
||||
|
||||
[$origWidth] = getimagesizefromstring($data);
|
||||
@ -371,4 +387,19 @@ final class Index extends BaseController {
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function getPlaceholder (string $path, ?int $width = 200, ?int $height = NULL): void
|
||||
{
|
||||
$height = $height ?? $width;
|
||||
|
||||
$filename = $path . '/placeholder.png';
|
||||
|
||||
if ( ! file_exists($path . '/placeholder.png'))
|
||||
{
|
||||
createPlaceholderImage($path, $width, $height);
|
||||
}
|
||||
|
||||
header('Content-Type: image/png');
|
||||
echo file_get_contents($filename);
|
||||
}
|
||||
}
|
@ -62,11 +62,12 @@ final class People extends BaseController {
|
||||
|
||||
if (array_key_exists('included', $data) && array_key_exists('castings', $data['included']))
|
||||
{
|
||||
$viewData['included'] = $data['included'];
|
||||
$viewData['castings'] = $this->organizeCast($data['included']['castings']);
|
||||
$viewData['castCount'] = count($viewData['castings']);
|
||||
}
|
||||
|
||||
$this->outputHTML('person', $viewData);
|
||||
$this->outputHTML('person/index', $viewData);
|
||||
}
|
||||
|
||||
protected function organizeCast(array $cast): array
|
||||
@ -82,6 +83,52 @@ final class People extends BaseController {
|
||||
|
||||
$roleName = $role['attributes']['role'];
|
||||
$media = $role['relationships']['media'];
|
||||
$chars = $role['relationships']['character']['characters'] ?? [];
|
||||
|
||||
if ( ! array_key_exists($roleName, $output))
|
||||
{
|
||||
$output[$roleName] = [
|
||||
'characters' => [],
|
||||
];
|
||||
}
|
||||
|
||||
if ( ! empty($chars))
|
||||
{
|
||||
$relatedMedia = [];
|
||||
|
||||
if (array_key_exists('anime', $media))
|
||||
{
|
||||
foreach($media['anime'] as $sid => $series)
|
||||
{
|
||||
$relatedMedia[$sid] = $series['attributes'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach($chars as $cid => $character)
|
||||
{
|
||||
// To make sure all the media are properly associated,
|
||||
// merge the found media for this iteration with
|
||||
// existing media, making sure to preserve array keys
|
||||
$existingMedia = array_key_exists($cid, $output[$roleName]['characters'])
|
||||
? $output[$roleName]['characters'][$cid]['media']
|
||||
: [];
|
||||
|
||||
$includedMedia = array_replace_recursive($existingMedia, $relatedMedia);
|
||||
|
||||
uasort($includedMedia, function ($a, $b) {
|
||||
return $a['canonicalTitle'] <=> $b['canonicalTitle'];
|
||||
});
|
||||
|
||||
$output[$roleName]['characters'][$cid] = [
|
||||
'character' => $character['attributes'],
|
||||
'media' => $includedMedia,
|
||||
];
|
||||
}
|
||||
|
||||
uasort($output[$roleName]['characters'], function ($a, $b) {
|
||||
return $a['character']['canonicalName'] <=> $b['character']['canonicalName'];
|
||||
});
|
||||
}
|
||||
|
||||
if (array_key_exists('anime', $media))
|
||||
{
|
||||
@ -99,7 +146,7 @@ final class People extends BaseController {
|
||||
{
|
||||
$output[$roleName]['manga'][$sid] = $series;
|
||||
}
|
||||
uasort($output[$roleName]['anime'], function ($a, $b) {
|
||||
uasort($output[$roleName]['manga'], function ($a, $b) {
|
||||
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user