diff --git a/src/API/ListItemInterface.php b/src/API/AbstractListItem.php similarity index 78% rename from src/API/ListItemInterface.php rename to src/API/AbstractListItem.php index e1ad53a4..795621b3 100644 --- a/src/API/ListItemInterface.php +++ b/src/API/AbstractListItem.php @@ -22,7 +22,7 @@ use Aviat\AnimeClient\Types\FormItemData; /** * Common interface for anime and manga list item CRUD */ -interface ListItemInterface { +abstract class AbstractListItem { /** * Create a list item @@ -30,7 +30,7 @@ interface ListItemInterface { * @param array $data - * @return Request */ - public function create(array $data): Request; + abstract public function create(array $data): Request; /** * Retrieve a list item @@ -38,7 +38,7 @@ interface ListItemInterface { * @param string $id - The id of the list item * @return array */ - public function get(string $id): array; + abstract public function get(string $id): array; /** * Increase progress on a list item @@ -47,7 +47,7 @@ interface ListItemInterface { * @param FormItemData $data * @return Request */ - public function increment(string $id, FormItemData $data): Request; + abstract public function increment(string $id, FormItemData $data): Request; /** * Update a list item @@ -56,7 +56,7 @@ interface ListItemInterface { * @param FormItemData $data - The data with which to update the list item * @return Request */ - public function update(string $id, FormItemData $data): Request; + abstract public function update(string $id, FormItemData $data): Request; /** * Delete a list item @@ -64,5 +64,5 @@ interface ListItemInterface { * @param string $id - The id of the list item to delete * @return Request */ - public function delete(string $id): Request; + abstract public function delete(string $id):?Request; } \ No newline at end of file diff --git a/src/API/Anilist/ListItem.php b/src/API/Anilist/ListItem.php index caf5d23e..51cd3ce2 100644 --- a/src/API/Anilist/ListItem.php +++ b/src/API/Anilist/ListItem.php @@ -18,7 +18,7 @@ namespace Aviat\AnimeClient\API\Anilist; use Amp\Artax\Request; -use Aviat\AnimeClient\API\ListItemInterface; +use Aviat\AnimeClient\API\AbstractListItem; use Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Anilist as AnilistStatus; use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus; use Aviat\AnimeClient\Types\FormItemData; @@ -26,7 +26,7 @@ use Aviat\AnimeClient\Types\FormItemData; /** * CRUD operations for MAL list items */ -final class ListItem implements ListItemInterface{ +final class ListItem extends AbstractListItem { use AnilistTrait; /** @@ -37,7 +37,8 @@ final class ListItem implements ListItemInterface{ */ public function create(array $data): Request { - return $this->mutateRequest('CreateMediaListEntry', $data); + $checkedData = (new Types\MediaListEntry($data))->toArray(); + return $this->mutateRequest('CreateMediaListEntry', $checkedData); } /** @@ -48,7 +49,8 @@ final class ListItem implements ListItemInterface{ */ public function createFull(array $data): Request { - return $this->mutateRequest('CreateFullMediaListEntry', $data); + $checkedData = (new Types\MediaListEntry($data))->toArray(); + return $this->mutateRequest('CreateFullMediaListEntry', $checkedData); } /** @@ -83,10 +85,12 @@ final class ListItem implements ListItemInterface{ */ public function increment(string $id, FormItemData $data): Request { - return $this->mutateRequest('IncrementMediaListEntry', [ + $checkedData = (new Types\MediaListEntry([ 'id' => $id, - 'progress' => $data['progress'], - ]); + 'progress' => $data->progress, + ]))->toArray(); + + return $this->mutateRequest('IncrementMediaListEntry', $checkedData); } /** @@ -98,15 +102,15 @@ final class ListItem implements ListItemInterface{ */ public function update(string $id, FormItemData $data): Request { - $array = $data->toArray(); + $notes = $data->notes ?? ''; + $progress = (int)$data->progress; + $private = (bool)$data->private; + $rating = $data->ratingTwenty; + $status = ($data->reconsuming === TRUE) + ? AnilistStatus::REPEATING + : AnimeWatchingStatus::KITSU_TO_ANILIST[$data->status]; - $notes = $data['notes'] ?? ''; - $progress = array_key_exists('progress', $array) ? $data['progress'] : 0; - $private = array_key_exists('private', $array) ? (bool)$data['private'] : false; - $rating = array_key_exists('ratingTwenty', $array) ? $data['ratingTwenty'] : NULL; - $status = ($data['reconsuming'] === true) ? AnilistStatus::REPEATING : AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']]; - - $updateData = [ + $updateData = (new Types\MediaListEntry([ 'id' => (int)$id, 'status' => $status, 'score' => $rating * 5, @@ -114,7 +118,7 @@ final class ListItem implements ListItemInterface{ 'repeat' => (int)$data['reconsumeCount'], 'private' => $private, 'notes' => $notes, - ]; + ]))->toArray(); return $this->mutateRequest('UpdateMediaListEntry', $updateData); } diff --git a/src/API/Anilist/Model.php b/src/API/Anilist/Model.php index ce14b400..dc6454ab 100644 --- a/src/API/Anilist/Model.php +++ b/src/API/Anilist/Model.php @@ -123,16 +123,16 @@ final class Model * @param string $type * @return Request */ - public function createListItem(array $data, string $type = 'anime'): Request + public function createListItem(array $data, string $type = 'anime'): ?Request { $createData = []; $mediaId = $this->getMediaIdFromMalId($data['mal_id'], mb_strtoupper($type)); - /* if (empty($mediaId)) + if ($mediaId === NULL) { - throw new InvalidArgumentException('Media id missing'); - } */ + return NULL; + } if ($type === 'ANIME') { @@ -200,9 +200,13 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function incrementListItem(FormItem $data, string $type): Request + public function incrementListItem(FormItem $data, string $type): ?Request { $id = $this->getListIdFromMalId($data['mal_id'], $type); + if ($id === NULL) + { + return NULL; + } return $this->listItem->increment($id, $data['data']); } @@ -214,10 +218,15 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function updateListItem(FormItem $data, string $type): Request + public function updateListItem(FormItem $data, string $type): ?Request { $id = $this->getListIdFromMalId($data['mal_id'], mb_strtoupper($type)); + if ($id === NULL) + { + return NULL; + } + return $this->listItem->update($id, $data['data']); } @@ -228,11 +237,15 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function deleteListItem(string $malId, string $type): Request + public function deleteListItem(string $malId, string $type): ?Request { - $item_id = $this->getListIdFromMalId($malId, $type); + $id = $this->getListIdFromMalId($malId, $type); + if ($id === NULL) + { + return NULL; + } - return $this->listItem->delete($item_id); + return $this->listItem->delete($id); } /** @@ -245,6 +258,11 @@ final class Model public function getListIdFromMalId(string $malId, string $type): ?string { $mediaId = $this->getMediaIdFromMalId($malId, $type); + if ($mediaId === NULL) + { + return NULL; + } + return $this->getListIdFromMediaId($mediaId); } diff --git a/src/API/Anilist/Types/MediaListEntry.php b/src/API/Anilist/Types/MediaListEntry.php new file mode 100644 index 00000000..36473014 --- /dev/null +++ b/src/API/Anilist/Types/MediaListEntry.php @@ -0,0 +1,56 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\API\Anilist\Types; + +use Aviat\AnimeClient\Types\AbstractType; + +class MediaListEntry extends AbstractType { + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $notes; + + /** + * @var bool + */ + public $private; + + /** + * @var int + */ + public $progress; + + /** + * @var int + */ + public $repeat; + + /** + * @var string + */ + public $status; + + /** + * @var int + */ + public $score; +} \ No newline at end of file diff --git a/src/API/Kitsu/ListItem.php b/src/API/Kitsu/ListItem.php index 397acb17..9fce9409 100644 --- a/src/API/Kitsu/ListItem.php +++ b/src/API/Kitsu/ListItem.php @@ -24,7 +24,7 @@ use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; use Amp\Artax\Request; -use Aviat\AnimeClient\API\ListItemInterface; +use Aviat\AnimeClient\API\AbstractListItem; use Aviat\AnimeClient\Types\FormItemData; use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Json; @@ -34,7 +34,7 @@ use Throwable; /** * CRUD operations for Kitsu list items */ -final class ListItem implements ListItemInterface { +final class ListItem extends AbstractListItem { use ContainerAware; use KitsuTrait; diff --git a/src/Model/Anime.php b/src/Model/Anime.php index 13960bb4..110c4528 100644 --- a/src/Model/Anime.php +++ b/src/Model/Anime.php @@ -173,7 +173,12 @@ class Anime extends API { if ($this->anilistEnabled && $data['mal_id'] !== null) { - $requester->addRequest($this->anilistModel->createListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->createListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -195,7 +200,12 @@ class Anime extends API { if (( ! empty($data['mal_id'])) && $this->anilistEnabled) { - $requester->addRequest($this->anilistModel->incrementListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->incrementListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -223,7 +233,12 @@ class Anime extends API { if (( ! empty($data['mal_id'])) && $this->anilistEnabled) { - $requester->addRequest($this->anilistModel->updateListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->updateListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -252,7 +267,12 @@ class Anime extends API { if ($this->anilistEnabled && $malId !== null) { - $requester->addRequest($this->anilistModel->deleteListItem($malId, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->deleteListItem($malId, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); diff --git a/src/Types/AbstractType.php b/src/Types/AbstractType.php index f7ca8935..a38177f7 100644 --- a/src/Types/AbstractType.php +++ b/src/Types/AbstractType.php @@ -63,6 +63,8 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function __isset($name): bool { + // This returns the expected results because unset + // properties no longer exist on the class return property_exists($this, $name); } @@ -101,12 +103,9 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function __get($name) { - if (property_exists($this, $name)) - { - return $this->$name; - } - - throw new UndefinedPropertyException("Trying to get undefined property: '$name'"); + // Be a bit more lenient here, so that you can easily typecast missing + // values to reasonable defaults, and not have to resort to array indexes + return ($this->__isset($name)) ? $this->$name : NULL; } /** @@ -210,7 +209,7 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function isEmpty(): bool { - foreach ($this as $key => $value) + foreach ($this as $value) { if ( ! empty($value)) {