diff --git a/app/bootstrap.php b/app/bootstrap.php index ee510190..0a16687b 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -48,10 +48,13 @@ return function(array $config_array = []) { $app_logger = new Logger('animeclient'); $app_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/app.log', Logger::NOTICE)); - $request_logger = new Logger('request'); - $request_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/request.log', Logger::NOTICE)); + $kitsu_request_logger = new Logger('kitsu_request'); + $kitsu_request_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/kitsu_request.log', Logger::NOTICE)); + $mal_request_logger = new Logger('mal_request'); + $mal_request_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/mal_request.log', Logger::NOTICE)); $container->setLogger($app_logger, 'default'); - $container->setLogger($request_logger, 'request'); + $container->setLogger($kitsu_request_logger, 'kitsu_request'); + $container->setLogger($mal_request_logger, 'mal_request'); // ------------------------------------------------------------------------- // Injected Objects diff --git a/app/views/anime/edit.php b/app/views/anime/edit.php index 7d234129..75cc7578 100644 --- a/app/views/anime/edit.php +++ b/app/views/anime/edit.php @@ -1,5 +1,4 @@ is_authenticated()): ?> - */ ?>

Edit Anime List Item

@@ -86,15 +85,20 @@
+
+
Danger Zone
- + diff --git a/src/API/Kitsu/Enum/AnimeWatchingStatus.php b/src/API/Kitsu/Enum/AnimeWatchingStatus.php index c517ff7d..be86960a 100644 --- a/src/API/Kitsu/Enum/AnimeWatchingStatus.php +++ b/src/API/Kitsu/Enum/AnimeWatchingStatus.php @@ -27,5 +27,4 @@ class AnimeWatchingStatus extends BaseEnum { const COMPLETED = 'completed'; const ON_HOLD = 'on_hold'; const DROPPED = 'dropped'; -} -// End of AnimeWatchingStatus.php \ No newline at end of file +} \ No newline at end of file diff --git a/src/API/Kitsu/KitsuTrait.php b/src/API/Kitsu/KitsuTrait.php index 30d97fa1..79d219af 100644 --- a/src/API/Kitsu/KitsuTrait.php +++ b/src/API/Kitsu/KitsuTrait.php @@ -93,7 +93,7 @@ trait KitsuTrait { 'headers' => $this->defaultHeaders ]; - $logger = $this->container->getLogger('request'); + $logger = $this->container->getLogger('kitsu_request'); $sessionSegment = $this->getContainer() ->get('session') ->getSegment(AnimeClient::SESSION_SEGMENT); @@ -106,10 +106,19 @@ trait KitsuTrait { $options = array_merge($defaultOptions, $options); - $logger->debug(Json::encode([$type, $url])); - $logger->debug(Json::encode($options)); + $response = $this->client->request($type, $url, $options); - return $this->client->request($type, $url, $options); + $logger->debug('Kitsu API request', [ + 'requestParams' => [ + 'type' => $type, + 'url' => $url, + ], + 'responseValues' => [ + 'status' => $response->getStatusCode() + ] + ]); + + return $response; } /** @@ -125,7 +134,7 @@ trait KitsuTrait { $logger = null; if ($this->getContainer()) { - $logger = $this->container->getLogger('request'); + $logger = $this->container->getLogger('kitsu_request'); } $response = $this->getResponse($type, $url, $options); @@ -134,11 +143,8 @@ trait KitsuTrait { { if ($logger) { - $logger->warning('Non 200 response for api call'); - $logger->warning($response->getBody()); + $logger->warning('Non 200 response for api call', $response->getBody()); } - - // throw new RuntimeException($response->getBody()); } return JSON::decode($response->getBody(), TRUE); @@ -177,7 +183,7 @@ trait KitsuTrait { $logger = null; if ($this->getContainer()) { - $logger = $this->container->getLogger('request'); + $logger = $this->container->getLogger('kitsu_request'); } $response = $this->getResponse('POST', ...$args); @@ -187,11 +193,8 @@ trait KitsuTrait { { if ($logger) { - $logger->warning('Non 201 response for POST api call'); - $logger->warning($response->getBody()); + $logger->warning('Non 201 response for POST api call', $response->getBody()); } - - // throw new RuntimeException($response->getBody()); } return JSON::decode($response->getBody(), TRUE); diff --git a/src/API/Kitsu/Model.php b/src/API/Kitsu/Model.php index cc7dd71f..7077f809 100644 --- a/src/API/Kitsu/Model.php +++ b/src/API/Kitsu/Model.php @@ -20,9 +20,9 @@ use Aviat\AnimeClient\API\CacheTrait; use Aviat\AnimeClient\API\JsonAPI; use Aviat\AnimeClient\API\Kitsu as K; use Aviat\AnimeClient\API\Kitsu\Transformer\{ - AnimeTransformer, - AnimeListTransformer, - MangaTransformer, + AnimeTransformer, + AnimeListTransformer, + MangaTransformer, MangaListTransformer }; use Aviat\Ion\Di\ContainerAware; @@ -65,7 +65,7 @@ class Model { * @var MangaListTransformer */ protected $mangaListTransformer; - + /** * Constructor. @@ -94,9 +94,9 @@ class Model { { $username = $this->getUsername(); } - + $cacheItem = $this->cache->getItem(K::AUTH_USER_ID_KEY); - + if ( ! $cacheItem->isHit()) { $data = $this->getRequest('users', [ @@ -110,7 +110,7 @@ class Model { $cacheItem->set($data['data'][0]['id']); $cacheItem->save(); } - + return $cacheItem->get(); } @@ -154,7 +154,7 @@ class Model { $baseData = $this->getRawMediaData('anime', $slug); return $this->animeTransformer->transform($baseData); } - + /** * Get information about a particular anime * @@ -167,6 +167,34 @@ class Model { return $this->animeTransformer->transform($baseData); } + /** + * Get the mal id for the anime represented by the kitsu id + * to enable updating MyAnimeList + * + * @param string $kitsuAnimeId The id of the anime on Kitsu + * @return string|null Returns the mal id if it exists, otherwise null + */ + public function getMalIdForAnime(string $kitsuAnimeId) + { + $options = [ + 'query' => [ + 'include' => 'mappings' + ] + ]; + $data = $this->getRequest("anime/{$kitsuAnimeId}", $options); + $mappings = array_column($data['included'], 'attributes'); + + foreach($mappings as $map) + { + if ($map['externalSite'] === 'myanimelist/anime') + { + return $map['externalId']; + } + } + + return null; + } + /** * Get information about a particular manga * @@ -178,7 +206,17 @@ class Model { $baseData = $this->getRawMediaData('manga', $mangaId); return $this->mangaTransformer->transform($baseData); } - + + /** + * Get and transform the entirety of the user's anime list + * + * @return array + */ + public function getFullAnimeList(): array + { + + } + /** * Get the raw (unorganized) anime list for the configured user * @@ -204,7 +242,7 @@ class Model { 'sort' => '-updated_at' ] ]; - + return $this->getRequest('library-entries', $options); } @@ -219,7 +257,7 @@ class Model { public function getAnimeList(string $status, int $limit = 600, int $offset = 0): array { $cacheItem = $this->cache->getItem($this->getHashForMethodCall($this, __METHOD__, [$status])); - + if ( ! $cacheItem->isHit()) { $data = $this->getRawAnimeList($status, $limit, $offset); @@ -231,7 +269,7 @@ class Model { $item['included'] = $included; } $transformed = $this->animeListTransformer->transformCollection($data['data']); - + $cacheItem->set($transformed); $cacheItem->save(); } @@ -264,7 +302,7 @@ class Model { 'sort' => '-updated_at' ] ]; - + $cacheItem = $this->cache->getItem($this->getHashForMethodCall($this, __METHOD__, $options)); if ( ! $cacheItem->isHit()) @@ -277,7 +315,7 @@ class Model { $cacheItem->set($transformed); $cacheItem->save(); } - + return $cacheItem->get(); } @@ -397,7 +435,7 @@ class Model { ->get('config') ->get(['kitsu_username']); } - + private function getRawMediaDataById(string $type, string $id): array { $options = [ diff --git a/src/API/Kitsu/Transformer/AnimeListTransformer.php b/src/API/Kitsu/Transformer/AnimeListTransformer.php index 959cc675..2591aab0 100644 --- a/src/API/Kitsu/Transformer/AnimeListTransformer.php +++ b/src/API/Kitsu/Transformer/AnimeListTransformer.php @@ -113,6 +113,7 @@ class AnimeListTransformer extends AbstractTransformer { $untransformed = [ 'id' => $item['id'], + 'mal_id' => $item['mal_id'] ?? null, 'data' => [ 'status' => $item['watching_status'], 'rating' => $item['user_rating'] / 2, diff --git a/src/API/MAL.php b/src/API/MAL.php index ec55f880..a346993a 100644 --- a/src/API/MAL.php +++ b/src/API/MAL.php @@ -16,6 +16,10 @@ namespace Aviat\AnimeClient\API; +use Aviat\AnimeClient\API\Kitsu\Enum\{ + AnimeWatchingStatus as KAWS, + MangaReadingStatus as KMRS +}; use Aviat\AnimeClient\API\MAL\Enum\{AnimeWatchingStatus, MangaReadingStatus}; /** @@ -25,6 +29,14 @@ class MAL { const AUTH_URL = 'https://myanimelist.net/api/account/verify_credentials.xml'; const BASE_URL = 'https://myanimelist.net/api/'; + const KITSU_MAL_WATCHING_STATUS_MAP = [ + KAWS::WATCHING => AnimeWatchingStatus::WATCHING, + KAWS::COMPLETED => AnimeWatchingStatus::COMPLETED, + KAWS::ON_HOLD => AnimeWatchingStatus::ON_HOLD, + KAWS::DROPPED => AnimeWatchingStatus::DROPPED, + KAWS::PLAN_TO_WATCH => AnimeWatchingStatus::PLAN_TO_WATCH + ]; + public static function getIdToWatchingStatusMap() { return [ @@ -32,7 +44,12 @@ class MAL { 2 => AnimeWatchingStatus::COMPLETED, 3 => AnimeWatchingStatus::ON_HOLD, 4 => AnimeWatchingStatus::DROPPED, - 5 => AnimeWatchingStatus::PLAN_TO_WATCH + 6 => AnimeWatchingStatus::PLAN_TO_WATCH, + 'watching' => AnimeWatchingStatus::WATCHING, + 'completed' => AnimeWatchingStatus::COMPLETED, + 'onhold' => AnimeWatchingStatus::ON_HOLD, + 'dropped' => AnimeWatchingStatus::DROPPED, + 'plantowatch' => AnimeWatchingStatus::PLAN_TO_WATCH ]; } @@ -43,7 +60,12 @@ class MAL { 2 => MangaReadingStatus::COMPLETED, 3 => MangaReadingStatus::ON_HOLD, 4 => MangaReadingStatus::DROPPED, - 5 => MangaReadingStatus::PLAN_TO_READ + 6 => MangaReadingStatus::PLAN_TO_READ, + 'reading' => MangaReadingStatus::READING, + 'completed' => MangaReadingStatus::COMPLETED, + 'onhold' => MangaReadingStatus::ON_HOLD, + 'dropped' => MangaReadingStatus::DROPPED, + 'plantoread' => MangaReadingStatus::PLAN_TO_WATCH ]; } } \ No newline at end of file diff --git a/src/API/MAL/Enum/AnimeWatchingStatus.php b/src/API/MAL/Enum/AnimeWatchingStatus.php index b12e2657..e6eb0097 100644 --- a/src/API/MAL/Enum/AnimeWatchingStatus.php +++ b/src/API/MAL/Enum/AnimeWatchingStatus.php @@ -22,9 +22,9 @@ use Aviat\Ion\Enum as BaseEnum; * Possible values for watching status for the current anime */ class AnimeWatchingStatus extends BaseEnum { - const WATCHING = 'watching'; - const COMPLETED = 'completed'; - const ON_HOLD = 'onhold'; - const DROPPED = 'dropped'; - const PLAN_TO_WATCH = 'plantowatch'; + const WATCHING = 1; + const COMPLETED = 2; + const ON_HOLD = 3; + const DROPPED = 4; + const PLAN_TO_WATCH = 6; } \ No newline at end of file diff --git a/src/API/MAL/ListItem.php b/src/API/MAL/ListItem.php index 95f9633c..715be392 100644 --- a/src/API/MAL/ListItem.php +++ b/src/API/MAL/ListItem.php @@ -33,27 +33,27 @@ class ListItem { public function create(array $data): bool { $id = $data['id']; - $body = (new FormBody) - ->addField('id', $data['id']) - ->addField('data', XML::toXML(['entry' => $data['data']])); + $createData = [ + 'id' => $id, + 'data' => XML::toXML([ + 'entry' => $data['data'] + ]) + ]; + $response = $this->getResponse('POST', "animelist/add/{$id}.xml", [ - 'headers' => [ - 'Content-type' => 'application/x-www-form-urlencoded', - 'Accept' => 'text/plain' - ], - 'body' => $body + 'body' => $this->fixBody((new FormBody)->addFields($createData)) ]); - - return $response->getStatus() === 201; + + return $response->getBody() === 'Created'; } public function delete(string $id): bool { - $response = $this->getResponse('DELETE', "animeclient/delete/{$id}.xml", [ - 'body' => (new FormBody)->addField('id', $id) + $response = $this->getResponse('DELETE', "animelist/delete/{$id}.xml", [ + 'body' => $this->fixBody((new FormBody)->addField('id', $id)) ]); - - return $response->getBody() === 'Deleted'; + + return $response->getBody() === 'Deleted'; } public function get(string $id): array @@ -61,18 +61,15 @@ class ListItem { return []; } - public function update(string $id, array $data): Response + public function update(string $id, array $data) { + $xml = XML::toXML(['entry' => $data]); $body = (new FormBody) ->addField('id', $id) - ->addField('data', XML::toXML(['entry' => $data])) - - return $this->postRequest("animelist/update/{$id}.xml", [ - 'headers' => [ - 'Content-type' => 'application/x-www-form-urlencoded', - 'Accept' => 'text/plain' - ], - 'body' => $body + ->addField('data', $xml); + + return $this->getResponse('POST', "animelist/update/{$id}.xml", [ + 'body' => $this->fixBody($body) ]); } } \ No newline at end of file diff --git a/src/API/MAL/MALTrait.php b/src/API/MAL/MALTrait.php index 5a7cfbb3..15ac7757 100644 --- a/src/API/MAL/MALTrait.php +++ b/src/API/MAL/MALTrait.php @@ -16,7 +16,7 @@ namespace Aviat\AnimeClient\API\MAL; -use Amp\Artax\{Client, Request}; +use Amp\Artax\{Client, FormBody, Request}; use Aviat\AnimeClient\API\{ MAL as M, XML @@ -38,8 +38,26 @@ trait MALTrait { * @var array */ protected $defaultHeaders = [ + 'Accept' => 'text/xml', + 'Accept-Encoding' => 'gzip', + 'Content-type' => 'application/x-www-form-urlencoded', 'User-Agent' => "Tim's Anime Client/4.0" ]; + + /** + * Unencode the dual-encoded ampersands in the body + * + * This is a dirty hack until I can fully track down where + * the dual-encoding happens + * + * @param FormBody $formBody The form builder object to fix + * @return string + */ + private function fixBody(FormBody $formBody): string + { + $rawBody = \Amp\wait($formBody->getBody()); + return html_entity_decode($rawBody, \ENT_HTML5, 'UTF-8'); + } /** * Make a request via Guzzle @@ -51,39 +69,60 @@ trait MALTrait { */ private function getResponse(string $type, string $url, array $options = []) { + $this->defaultHeaders['User-Agent'] = $_SERVER['HTTP_USER_AGENT'] ?? $this->defaultHeaders; + $type = strtoupper($type); - $validTypes = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']; + $validTypes = ['GET', 'POST', 'DELETE']; if ( ! in_array($type, $validTypes)) { throw new InvalidArgumentException('Invalid http request type'); } - + $config = $this->container->get('config'); - $logger = $this->container->getLogger('request'); - + $logger = $this->container->getLogger('mal_request'); + $headers = array_merge($this->defaultHeaders, $options['headers'] ?? [], [ - 'Authorization' => 'Basic ' . + 'Authorization' => 'Basic ' . base64_encode($config->get(['mal','username']) . ':' .$config->get(['mal','password'])) ]); - + $query = $options['query'] ?? []; - + $url = (strpos($url, '//') !== FALSE) - ? $url . '?' . http_build_query($query) - : $this->baseUrl . $url . '?' . http_build_query($query); - + ? $url + : $this->baseUrl . $url; + + if ( ! empty($query)) + { + $url .= '?' . http_build_query($query); + } + $request = (new Request) ->setMethod($type) ->setUri($url) ->setProtocol('1.1') - ->setAllHeaders($headers) - ->setBody($options['body']); + ->setAllHeaders($headers); - $logger->debug(Json::encode([$type, $url])); - $logger->debug(Json::encode($options)); + if (array_key_exists('body', $options)) + { + $request->setBody($options['body']); + } - return \Amp\wait((new Client)->request($request)); + $response = \Amp\wait((new Client)->request($request)); + + $logger->debug('MAL api request', [ + 'url' => $url, + 'status' => $response->getStatus(), + 'reason' => $response->getReason(), + 'headers' => $response->getAllHeaders(), + 'requestHeaders' => $request->getAllHeaders(), + 'requestBody' => $request->hasBody() ? $request->getBody() : 'No request body', + 'requestBodyBeforeEncode' => $request->hasBody() ? urldecode($request->getBody()) : '', + 'body' => $response->getBody() + ]); + + return $response; } /** @@ -99,7 +138,7 @@ trait MALTrait { $logger = null; if ($this->getContainer()) { - $logger = $this->container->getLogger('request'); + $logger = $this->container->getLogger('mal_request'); } $response = $this->getResponse($type, $url, $options); @@ -108,8 +147,7 @@ trait MALTrait { { if ($logger) { - $logger->warning('Non 200 response for api call'); - $logger->warning($response->getBody()); + $logger->warning('Non 200 response for api call', $response->getBody()); } } @@ -138,7 +176,7 @@ trait MALTrait { $logger = null; if ($this->getContainer()) { - $logger = $this->container->getLogger('request'); + $logger = $this->container->getLogger('mal_request'); } $response = $this->getResponse('POST', ...$args); @@ -148,8 +186,7 @@ trait MALTrait { { if ($logger) { - $logger->warning('Non 201 response for POST api call'); - $logger->warning($response->getBody()); + $logger->warning('Non 201 response for POST api call', $response->getBody()); } } diff --git a/src/API/MAL/Model.php b/src/API/MAL/Model.php index 650df789..a2d0633e 100644 --- a/src/API/MAL/Model.php +++ b/src/API/MAL/Model.php @@ -17,13 +17,10 @@ namespace Aviat\AnimeClient\API\MAL; use Aviat\AnimeClient\API\MAL as M; -use Aviat\AnimeClient\API\MAL\{ - AnimeListTransformer, - ListItem -}; +use Aviat\AnimeClient\API\MAL\ListItem; +use Aviat\AnimeClient\API\MAL\Transformer\AnimeListTransformer; use Aviat\AnimeClient\API\XML; use Aviat\Ion\Di\ContainerAware; -use Aviat\Ion\Json; /** * MyAnimeList API Model @@ -42,13 +39,37 @@ class Model { */ public function __construct(ListItem $listItem) { - //$this->animeListTransformer = new AnimeListTransformer(); + $this->animeListTransformer = new AnimeListTransformer(); $this->listItem = $listItem; } public function createListItem(array $data): bool { - return $this->listItem->create($data); + $createData = [ + 'id' => $data['id'], + 'data' => [ + 'status' => M::KITSU_MAL_WATCHING_STATUS_MAP[$data['status']] + ] + ]; + + return $this->listItem->create($createData); + } + + public function getFullList(): array + { + $config = $this->container->get('config'); + $userName = $config->get(['mal', 'username']); + $list = $this->getRequest('https://myanimelist.net/malappinfo.php', [ + 'headers' => [ + 'Accept' => 'text/xml' + ], + 'query' => [ + 'u' => $userName, + 'status' => 'all' + ] + ]); + + return $list;//['anime']; } public function getListItem(string $listId): array @@ -58,8 +79,8 @@ class Model { public function updateListItem(array $data) { - //$updateData = $this->animeListTransformer->transform($data['data']); - return $this->listItem->update($data['mal_id'], $updateData); + $updateData = $this->animeListTransformer->untransform($data); + return $this->listItem->update($updateData['id'], $updateData['data']); } public function deleteListItem(string $id): bool diff --git a/src/API/MAL/Transformer/AnimeListTransformer.php b/src/API/MAL/Transformer/AnimeListTransformer.php index 881adaf5..29dd293c 100644 --- a/src/API/MAL/Transformer/AnimeListTransformer.php +++ b/src/API/MAL/Transformer/AnimeListTransformer.php @@ -14,27 +14,32 @@ * @link https://github.com/timw4mail/HummingBirdAnimeClient */ -namespace Aviat\AnimeClient\API\MAL; +namespace Aviat\AnimeClient\API\MAL\Transformer; +use Aviat\AnimeClient\API\Kitsu\Enum\AnimeWatchingStatus; use Aviat\Ion\Transformer\AbstractTransformer; /** * Transformer for updating MAL List */ class AnimeListTransformer extends AbstractTransformer { + + const statusMap = [ + AnimeWatchingStatus::WATCHING => '1', + AnimeWatchingStatus::COMPLETED => '2', + AnimeWatchingStatus::ON_HOLD => '3', + AnimeWatchingStatus::DROPPED => '4', + AnimeWatchingStatus::PLAN_TO_WATCH => '6' + ]; public function transform($item) { - $rewatching = 'false'; - if (array_key_exists('rewatching', $item) && $item['rewatching']) - { - $rewatching = 'true'; - } + $rewatching = (array_key_exists('rewatching', $item) && $item['rewatching']); return [ - 'id' => $item['id'], + 'id' => $item['mal_id'], 'data' => [ - 'status' => $item['watching_status'], + 'status' => self::statusMap[$item['watching_status']], 'rating' => $item['user_rating'], 'rewatch_value' => (int) $rewatching, 'times_rewatched' => $item['rewatched'], @@ -43,4 +48,31 @@ class AnimeListTransformer extends AbstractTransformer { ] ]; } + + /** + * Transform Kitsu episode data to MAL episode data + * + * @param array $item + * @return array + */ + public function untransform(array $item): array + { + $rewatching = (array_key_exists('reconsuming', $item['data']) && $item['data']['reconsuming']); + + $map = [ + 'id' => $item['mal_id'], + 'data' => [ + 'episode' => $item['data']['progress'], + 'status' => self::statusMap[$item['data']['status']], + 'score' => (array_key_exists('rating', $item['data'])) + ? $item['data']['rating'] * 2 + : "", + // 'enable_rewatching' => $rewatching, + // 'times_rewatched' => $item['data']['reconsumeCount'], + // 'comments' => $item['data']['notes'], + ] + ]; + + return $map; + } } \ No newline at end of file diff --git a/src/API/XML.php b/src/API/XML.php index 35ef99ee..86c27e1d 100644 --- a/src/API/XML.php +++ b/src/API/XML.php @@ -107,12 +107,7 @@ class XML { { $data = []; - // Get rid of unimportant text nodes by removing - // whitespace characters from between xml tags, - // except for the xml declaration tag, Which looks - // something like: - /* */ - $xml = preg_replace('/([^\?])>\s+<', $xml); + $xml = static::stripXMLWhitespace($xml); $dom = new DOMDocument(); $dom->loadXML($xml); @@ -166,6 +161,16 @@ class XML { return static::toXML($this->getData()); } + private static function stripXMLWhitespace(string $xml): string + { + // Get rid of unimportant text nodes by removing + // whitespace characters from between xml tags, + // except for the xml declaration tag, Which looks + // something like: + /* */ + return preg_replace('/([^\?])>\s+<', $xml); + } + /** * Recursively create array structure based on xml structure * @@ -180,7 +185,7 @@ class XML { { $el = $nodeList->item($i); $current =& $root[$el->nodeName]; - + // It's a top level element! if (is_a($el->childNodes->item(0), 'DomText') || ( ! $el->hasChildNodes())) { @@ -239,9 +244,9 @@ class XML { break; } } - + $node = $dom->createElement($key); - + if (is_array($props)) { static::arrayPropertiesToXmlNodes($dom, $node, $props); diff --git a/src/Controller/Anime.php b/src/Controller/Anime.php index 455921a0..d06d2a76 100644 --- a/src/Controller/Anime.php +++ b/src/Controller/Anime.php @@ -259,7 +259,7 @@ class Anime extends BaseController { $data = $this->request->getParsedBody(); } - $response = $this->model->updateLibraryItem($data); + $response = $this->model->updateLibraryItem($data, $data); $this->cache->clear(); $this->outputJSON($response['body'], $response['statusCode']); @@ -273,7 +273,7 @@ class Anime extends BaseController { public function delete() { $body = $this->request->getParsedBody(); - $response = $this->model->deleteLibraryItem($body['id']); + $response = $this->model->deleteLibraryItem($body['id'], $body['mal_id']); if ((bool)$response === TRUE) { diff --git a/src/Model/Anime.php b/src/Model/Anime.php index ba2eb889..14bc58a1 100644 --- a/src/Model/Anime.php +++ b/src/Model/Anime.php @@ -43,6 +43,12 @@ class Anime extends API { AnimeWatchingStatus::COMPLETED => self::COMPLETED, ]; + protected $kitsuModel; + + protected $malModel; + + protected $useMALAPI; + /** * Anime constructor. * @param ContainerInterface $container @@ -50,7 +56,11 @@ class Anime extends API { public function __construct(ContainerInterface $container) { parent::__construct($container); + $config = $container->get('config'); $this->kitsuModel = $container->get('kitsu-model'); + $this->malModel = $container->get('mal-model'); + + $this->useMALAPI = $config->get(['use_mal_api']) === TRUE; } /** @@ -80,7 +90,7 @@ class Anime extends API { { return $this->kitsuModel->getAnime($slug); } - + public function getAnimeById($anime_id) { return $this->kitsuModel->getAnimeById($anime_id); @@ -110,8 +120,26 @@ class Anime extends API { return $this->kitsuModel->getListItem($itemId); } + /** + * Add an anime to your list + * + * @param array $data + * @return bool + */ public function createLibraryItem(array $data): bool { + if ($this->useMALAPI) + { + $malData = $data; + $malId = $this->kitsuModel->getMalIdForAnime($malData['id']); + + if ( ! is_null($malId)) + { + $malData['id'] = $malId; + $this->malModel->createListItem($malData); + } + } + return $this->kitsuModel->createListItem($data); } @@ -123,11 +151,28 @@ class Anime extends API { */ public function updateLibraryItem(array $data): array { + if ($this->useMALAPI) + { + $this->malModel->updateListItem($data); + } + return $this->kitsuModel->updateListItem($data); } - public function deleteLibraryItem($id): bool + /** + * Delete a list entry + * + * @param string $id + * @param string|null $malId + * @return bool + */ + public function deleteLibraryItem(string $id, string $malId = null): bool { + if ($this->useMALAPI && ! is_null($malId)) + { + $this->malModel->deleteListItem($malId); + } + return $this->kitsuModel->deleteListItem($id); } } diff --git a/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php b/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php index 84e6f883..de87f29a 100644 --- a/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php +++ b/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php @@ -44,6 +44,7 @@ class AnimeListTransformerTest extends AnimeClient_TestCase { ], 'expected' => [ 'id' => 14047981, + 'mal_id' => null, 'data' => [ 'status' => 'current', 'rating' => 4, @@ -57,6 +58,7 @@ class AnimeListTransformerTest extends AnimeClient_TestCase { ], [ 'input' => [ 'id' => 14047981, + 'mal_id' => '12345', 'watching_status' => 'current', 'user_rating' => 8, 'episodes_watched' => 38, @@ -68,6 +70,7 @@ class AnimeListTransformerTest extends AnimeClient_TestCase { ], 'expected' => [ 'id' => 14047981, + 'mal_id' => '12345', 'data' => [ 'status' => 'current', 'rating' => 4,