From 09734515cacaaeac75f5c9bfdd34218c77d41fbf Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Mon, 17 Aug 2020 16:36:55 -0400 Subject: [PATCH] Full character page pulled from GraphQL API, see #27 --- app/views/character/details.php | 23 +++--- composer.json | 1 + src/AnimeClient/API/Kitsu.php | 28 +++++++ .../API/Kitsu/Queries/PersonDetails.graphql | 70 ++++++++-------- .../Transformer/CharacterTransformer.php | 81 +++++++++++++++++-- 5 files changed, 150 insertions(+), 53 deletions(-) diff --git a/app/views/character/details.php b/app/views/character/details.php index 8cbb7c79..8d1b8a65 100644 --- a/app/views/character/details.php +++ b/app/views/character/details.php @@ -43,15 +43,14 @@ use Aviat\AnimeClient\API\Kitsu;
generate('anime.details', ['id' => $anime['slug']]); - $titles = Kitsu::getTitles($anime['titles']); ?> picture("images/anime/{$anime['id']}.webp") ?>
- - + +
@@ -71,15 +70,14 @@ use Aviat\AnimeClient\API\Kitsu;
generate('manga.details', ['id' => $manga['slug']]); - $titles = Kitsu::getTitles($manga['titles']); ?> picture("images/manga/{$manga['id']}.webp") ?>
- - + +
@@ -172,12 +170,12 @@ use Aviat\AnimeClient\API\Kitsu; Cast Member Series - $c): ?> +
generate('person', ['id' => $c['person']['id']]); + $link = $url->generate('person', ['id' => $c['person']['id'], 'slug' => $c['person']['slug']]); ?> picture(getLocalImg($c['person']['image'])) ?> @@ -192,16 +190,15 @@ use Aviat\AnimeClient\API\Kitsu;
generate('anime.details', ['id' => $series['attributes']['slug']]); - $titles = Kitsu::filterTitles($series['attributes']); + $link = $url->generate('anime.details', ['id' => $series['slug']]); ?> - picture(getLocalImg($series['attributes']['posterImage']['small'], TRUE)) ?> + picture(getLocalImg($series['posterImage'], TRUE)) ?>
- - + +
diff --git a/composer.json b/composer.json index cea18548..bc469397 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "danielstjules/stringy": "^3.1.0", "ext-dom": "*", "ext-iconv": "*", + "ext-intl": "*", "ext-json": "*", "ext-gd": "*", "ext-pdo": "*", diff --git a/src/AnimeClient/API/Kitsu.php b/src/AnimeClient/API/Kitsu.php index 82b6b999..fd739c94 100644 --- a/src/AnimeClient/API/Kitsu.php +++ b/src/AnimeClient/API/Kitsu.php @@ -292,6 +292,34 @@ final class Kitsu { return $valid; } + /** + * Filter out duplicate and very similar titles from a GraphQL response + * + * @param array $titles + * @return array + */ + public static function getFilteredTitles(array $titles): array + { + // The 'canonical' title is always considered + $valid = [$titles['canonical']]; + + if (array_key_exists('localized', $titles) && is_array($titles['localized'])) + { + foreach($titles['localized'] as $alternateTitle) + { + if (self::titleIsUnique($alternateTitle, $valid)) + { + $valid[] = $alternateTitle; + } + } + } + + // Don't return the canonical titles + array_shift($valid); + + return $valid; + } + /** * Get the name and logo for the streaming service of the current link * diff --git a/src/AnimeClient/API/Kitsu/Queries/PersonDetails.graphql b/src/AnimeClient/API/Kitsu/Queries/PersonDetails.graphql index 9a23682e..48e8d484 100644 --- a/src/AnimeClient/API/Kitsu/Queries/PersonDetails.graphql +++ b/src/AnimeClient/API/Kitsu/Queries/PersonDetails.graphql @@ -1,6 +1,7 @@ query ($id: ID!) { findPersonById(id: $id) { id + description birthday image { original { @@ -22,46 +23,45 @@ query ($id: ID!) { localized } voices { - licensor { - name - } - locale - mediaCharacter { - role - character { - id - image { - original { - height - name - url - width + nodes { + locale + mediaCharacter { + role + character { + id + image { + original { + height + name + url + width + } + } + names { + canonical } } - names { - canonical - } - } - media { - id - posterImage { - original { - height - name - url - width + media { + id + posterImage { + original { + height + name + url + width + } + views { + height + name + url + width + } } - views { - height - name - url - width + titles { + canonical + localized } } - titles { - canonical - localized - } } } } diff --git a/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php index 12872b85..52340f66 100644 --- a/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php @@ -17,9 +17,11 @@ namespace Aviat\AnimeClient\API\Kitsu\Transformer; use Aviat\AnimeClient\API\JsonAPI; +use Aviat\AnimeClient\API\Kitsu; use Aviat\AnimeClient\Types\Character; use Aviat\Ion\Transformer\AbstractTransformer; +use Locale; /** * Data transformation class for character pages @@ -70,19 +72,88 @@ final class CharacterTransformer extends AbstractTransformer { return [[], []]; } + $titleSort = fn ($a, $b) => $a['title'] <=> $b['title']; + $rawMedia = array_column($data, 'media'); $rawAnime = array_filter($rawMedia, fn ($item) => $item['type'] === 'Anime'); $rawManga = array_filter($rawMedia, fn ($item) => $item['type'] === 'Manga'); - uasort($rawAnime, fn ($a, $b) => $a['titles']['canonical'] <=> $b['titles']['canonical']); - uasort($rawManga, fn ($a, $b) => $a['titles']['canonical'] <=> $b['titles']['canonical']); + $anime = array_map(static function ($item) { + $output = $item; + unset($output['titles']); + $output['title'] = $item['titles']['canonical']; + $output['titles'] = Kitsu::getFilteredTitles($item['titles']); + + return $output; + }, $rawAnime); + $manga = array_map(static function ($item) { + $output = $item; + unset($output['titles']); + $output['title'] = $item['titles']['canonical']; + $output['titles'] = Kitsu::getFilteredTitles($item['titles']); + + return $output; + }, $rawManga); + + uasort($anime, $titleSort); + uasort($manga, $titleSort); $media = [ - 'anime' => $rawAnime, - 'manga' => $rawManga, + 'anime' => $anime, + 'manga' => $manga, ]; - return [$media, []]; + $rawVoices = array_filter($data, fn($item) => count((array)$item['voices']['nodes']) > 0); + + if (empty($rawVoices)) + { + return [$media, []]; + } + + $castings = [ + 'Voice Actor' => [], + ]; + + foreach ($rawVoices as $voiceMap) + { + foreach ($voiceMap['voices']['nodes'] as $voice) + { + $lang = Locale::getDisplayLanguage($voice['locale'], 'en'); + $id = $voice['person']['name']; + $seriesId = $voiceMap['media']['id']; + + if ( ! array_key_exists($lang, $castings['Voice Actor'])) + { + $castings['Voice Actor'][$lang] = []; + } + + if ( ! array_key_exists($id, $castings['Voice Actor'][$lang])) + { + $castings['Voice Actor'][$lang][$id] = [ + 'person' => [ + 'id' => $voice['person']['id'], + 'slug' => $voice['person']['slug'], + 'image' => $voice['person']['image']['original']['url'], + 'name' => $voice['person']['name'], + ], + 'series' => [] + ]; + } + + $castings['Voice Actor'][$lang][$id]['series'][$seriesId] = [ + 'id' => $seriesId, + 'slug' => $voiceMap['media']['slug'], + 'title' => $voiceMap['media']['titles']['canonical'], + 'titles' => Kitsu::getFilteredTitles($voiceMap['media']['titles']), + 'posterImage' => $voiceMap['media']['posterImage']['views'][1]['url'], + ]; + + uasort($castings['Voice Actor'][$lang][$id]['series'], $titleSort); + ksort($castings['Voice Actor'][$lang]); + } + } + + return [$media, $castings]; } /**