* @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\Model; use Aviat\Ion\Di\ContainerInterface; use PDO; /** * Model for getting anime collection data */ final class AnimeCollection extends Collection { /** * Anime API Model * @var Anime $animeModel */ protected $animeModel; /** * Create the collection model * * @param ContainerInterface $container */ public function __construct(ContainerInterface $container) { parent::__construct($container); $this->animeModel = $container->get('anime-model'); } /** * Get collection from the database, and organize by media type * * @return array */ public function getCollection(): array { $rawCollection = $this->getCollectionFromDatabase(); $collection = []; foreach ($rawCollection as $row) { if (array_key_exists($row['media'], $collection)) { $collection[$row['media']][] = $row; } else { $collection[$row['media']] = [$row]; } } return $collection; } /** * Get list of media types * * @return array */ public function getMediaTypeList(): array { $output = []; $query = $this->db->select('id, type') ->from('media') ->get(); foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { $output[$row['id']] = $row['type']; } return $output; } /** * Get item from collection for editing * * @param string $id * @return array */ public function getCollectionEntry($id): array { $query = $this->db->from('anime_set') ->where('hummingbird_id', $id) ->get(); return $query->fetch(PDO::FETCH_ASSOC); } /** * Get full collection from the database * * @return array */ private function getCollectionFromDatabase(): array { if ( ! $this->validDatabase) { return []; } $query = $this->db->select('hummingbird_id, slug, title, alternate_title, show_type, age_rating, episode_count, episode_length, cover_image, notes, media.type as media') ->from('anime_set a') ->join('media', 'media.id=a.media_id', 'inner') ->order_by('media') ->order_by('title') ->group_by('a.hummingbird_id, media.type') ->get(); // Add genres associated with each item $rows = $query->fetchAll(PDO::FETCH_ASSOC); $genres = $this->getGenresForList(); foreach($rows as &$row) { $id = $row['hummingbird_id']; $row['genres'] = array_key_exists($id, $genres) ? $genres[$id] : []; sort($row['genres']); } return $rows; } /** * Add an item to the anime collection * * @param array $data * @return void */ public function add($data): void { $anime = (object)$this->animeModel->getAnimeById($data['id']); $this->db->set([ 'hummingbird_id' => $data['id'], 'slug' => $anime->slug, 'title' => array_shift($anime->titles), 'alternate_title' => implode('
', $anime->titles), 'show_type' => $anime->show_type, 'age_rating' => $anime->age_rating, 'cover_image' => $anime->cover_image, 'episode_count' => $anime->episode_count, 'episode_length' => $anime->episode_length, 'media_id' => $data['media_id'], 'notes' => $data['notes'] ])->insert('anime_set'); $this->updateGenre($data['id']); } /** * Update a collection item * * @param array $data * @return void */ public function update($data): void { // If there's no id to update, don't update if ( ! array_key_exists('hummingbird_id', $data)) { return; } $id = $data['hummingbird_id']; unset($data['hummingbird_id']); $this->db->set($data) ->where('hummingbird_id', $id) ->update('anime_set'); } /** * Remove a collection item * * @param array $data * @return void */ public function delete($data): void { // If there's no id to update, don't delete if ( ! array_key_exists('hummingbird_id', $data)) { return; } $this->db->where('hummingbird_id', $data['hummingbird_id']) ->delete('genre_anime_set_link'); $this->db->where('hummingbird_id', $data['hummingbird_id']) ->delete('anime_set'); } /** * Get the details of a collection item * * @param int $kitsuId * @return array */ public function get($kitsuId): array { $query = $this->db->from('anime_set') ->where('hummingbird_id', $kitsuId) ->get(); return $query->fetch(PDO::FETCH_ASSOC); } private function getGenresForList(): array { $query = $this->db->select('hummingbird_id, genre') ->from('genres g') ->join('genre_anime_set_link gasl', 'gasl.genre_id=g.id') ->get(); $rows = $query->fetchAll(PDO::FETCH_ASSOC); $output = []; foreach($rows as $row) { $output[$row['hummingbird_id']][] = $row['genre']; } return $output; } /** * Update genre information for selected anime * * @param string $animeId The current anime * @return void */ private function updateGenre($animeId): void { $genreInfo = $this->getGenreData(); $genres = $genreInfo['genres']; $links = $genreInfo['links']; // Get api information $anime = $this->animeModel->getAnimeById($animeId); foreach ($anime['genres'] as $genre) { // Add genres that don't currently exist if ( ! \in_array($genre, $genres, TRUE)) { $this->db->set('genre', $genre) ->insert('genres'); $genres[] = $genre; } // Update link table // Get id of genre to put in link table $flippedGenres = array_flip($genres); $insertArray = [ 'hummingbird_id' => $animeId, 'genre_id' => $flippedGenres[$genre] ]; if (array_key_exists($animeId, $links)) { if ( ! \in_array($flippedGenres[$genre], $links[$animeId], TRUE)) { $this->db->set($insertArray)->insert('genre_anime_set_link'); } } else { $this->db->set($insertArray)->insert('genre_anime_set_link'); } } } /** * Get list of existing genres * * @return array */ private function getGenreData(): array { $genres = []; $links = []; // Get existing genres $query = $this->db->select('id, genre') ->from('genres') ->get(); foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $genre) { $genres[$genre['id']] = $genre['genre']; } // Get existing link table entries $query = $this->db->select('hummingbird_id, genre_id') ->from('genre_anime_set_link') ->get(); foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $link) { if (array_key_exists($link['hummingbird_id'], $links)) { $links[$link['hummingbird_id']][] = $link['genre_id']; } else { $links[$link['hummingbird_id']] = [$link['genre_id']]; } } return [ 'genres' => $genres, 'links' => $links ]; } } // End of AnimeCollectionModel.php