Better id mapping error handling for Anilist
timw4mail/HummingBirdAnimeClient/develop This commit looks good Details

This commit is contained in:
Timothy Warren 2020-01-15 12:35:37 -05:00
parent 7a4cda5bf0
commit 580dbb5993
7 changed files with 141 additions and 44 deletions

View File

@ -22,7 +22,7 @@ use Aviat\AnimeClient\Types\FormItemData;
/** /**
* Common interface for anime and manga list item CRUD * Common interface for anime and manga list item CRUD
*/ */
interface ListItemInterface { abstract class AbstractListItem {
/** /**
* Create a list item * Create a list item
@ -30,7 +30,7 @@ interface ListItemInterface {
* @param array $data - * @param array $data -
* @return Request * @return Request
*/ */
public function create(array $data): Request; abstract public function create(array $data): Request;
/** /**
* Retrieve a list item * Retrieve a list item
@ -38,7 +38,7 @@ interface ListItemInterface {
* @param string $id - The id of the list item * @param string $id - The id of the list item
* @return array * @return array
*/ */
public function get(string $id): array; abstract public function get(string $id): array;
/** /**
* Increase progress on a list item * Increase progress on a list item
@ -47,7 +47,7 @@ interface ListItemInterface {
* @param FormItemData $data * @param FormItemData $data
* @return Request * @return Request
*/ */
public function increment(string $id, FormItemData $data): Request; abstract public function increment(string $id, FormItemData $data): Request;
/** /**
* Update a list item * Update a list item
@ -56,7 +56,7 @@ interface ListItemInterface {
* @param FormItemData $data - The data with which to update the list item * @param FormItemData $data - The data with which to update the list item
* @return Request * @return Request
*/ */
public function update(string $id, FormItemData $data): Request; abstract public function update(string $id, FormItemData $data): Request;
/** /**
* Delete a list item * Delete a list item
@ -64,5 +64,5 @@ interface ListItemInterface {
* @param string $id - The id of the list item to delete * @param string $id - The id of the list item to delete
* @return Request * @return Request
*/ */
public function delete(string $id): Request; abstract public function delete(string $id):?Request;
} }

View File

@ -18,7 +18,7 @@ namespace Aviat\AnimeClient\API\Anilist;
use Amp\Artax\Request; 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\Enum\AnimeWatchingStatus\Anilist as AnilistStatus;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus; use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\FormItemData; use Aviat\AnimeClient\Types\FormItemData;
@ -26,7 +26,7 @@ use Aviat\AnimeClient\Types\FormItemData;
/** /**
* CRUD operations for MAL list items * CRUD operations for MAL list items
*/ */
final class ListItem implements ListItemInterface{ final class ListItem extends AbstractListItem {
use AnilistTrait; use AnilistTrait;
/** /**
@ -37,7 +37,8 @@ final class ListItem implements ListItemInterface{
*/ */
public function create(array $data): Request 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 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 public function increment(string $id, FormItemData $data): Request
{ {
return $this->mutateRequest('IncrementMediaListEntry', [ $checkedData = (new Types\MediaListEntry([
'id' => $id, '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 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'] ?? ''; $updateData = (new Types\MediaListEntry([
$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 = [
'id' => (int)$id, 'id' => (int)$id,
'status' => $status, 'status' => $status,
'score' => $rating * 5, 'score' => $rating * 5,
@ -114,7 +118,7 @@ final class ListItem implements ListItemInterface{
'repeat' => (int)$data['reconsumeCount'], 'repeat' => (int)$data['reconsumeCount'],
'private' => $private, 'private' => $private,
'notes' => $notes, 'notes' => $notes,
]; ]))->toArray();
return $this->mutateRequest('UpdateMediaListEntry', $updateData); return $this->mutateRequest('UpdateMediaListEntry', $updateData);
} }

View File

@ -123,16 +123,16 @@ final class Model
* @param string $type * @param string $type
* @return Request * @return Request
*/ */
public function createListItem(array $data, string $type = 'anime'): Request public function createListItem(array $data, string $type = 'anime'): ?Request
{ {
$createData = []; $createData = [];
$mediaId = $this->getMediaIdFromMalId($data['mal_id'], mb_strtoupper($type)); $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') if ($type === 'ANIME')
{ {
@ -200,9 +200,13 @@ final class Model
* @param string $type - Them media type (anime/manga) * @param string $type - Them media type (anime/manga)
* @return Request * @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); $id = $this->getListIdFromMalId($data['mal_id'], $type);
if ($id === NULL)
{
return NULL;
}
return $this->listItem->increment($id, $data['data']); return $this->listItem->increment($id, $data['data']);
} }
@ -214,10 +218,15 @@ final class Model
* @param string $type - Them media type (anime/manga) * @param string $type - Them media type (anime/manga)
* @return Request * @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)); $id = $this->getListIdFromMalId($data['mal_id'], mb_strtoupper($type));
if ($id === NULL)
{
return NULL;
}
return $this->listItem->update($id, $data['data']); return $this->listItem->update($id, $data['data']);
} }
@ -228,11 +237,15 @@ final class Model
* @param string $type - Them media type (anime/manga) * @param string $type - Them media type (anime/manga)
* @return Request * @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 public function getListIdFromMalId(string $malId, string $type): ?string
{ {
$mediaId = $this->getMediaIdFromMalId($malId, $type); $mediaId = $this->getMediaIdFromMalId($malId, $type);
if ($mediaId === NULL)
{
return NULL;
}
return $this->getListIdFromMediaId($mediaId); return $this->getListIdFromMediaId($mediaId);
} }

View File

@ -0,0 +1,56 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.2
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @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;
}

View File

@ -24,7 +24,7 @@ use function Amp\Promise\wait;
use function Aviat\AnimeClient\getResponse; use function Aviat\AnimeClient\getResponse;
use Amp\Artax\Request; use Amp\Artax\Request;
use Aviat\AnimeClient\API\ListItemInterface; use Aviat\AnimeClient\API\AbstractListItem;
use Aviat\AnimeClient\Types\FormItemData; use Aviat\AnimeClient\Types\FormItemData;
use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Di\ContainerAware;
use Aviat\Ion\Json; use Aviat\Ion\Json;
@ -34,7 +34,7 @@ use Throwable;
/** /**
* CRUD operations for Kitsu list items * CRUD operations for Kitsu list items
*/ */
final class ListItem implements ListItemInterface { final class ListItem extends AbstractListItem {
use ContainerAware; use ContainerAware;
use KitsuTrait; use KitsuTrait;

View File

@ -173,7 +173,12 @@ class Anime extends API {
if ($this->anilistEnabled && $data['mal_id'] !== null) 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(); $results = $requester->makeRequests();
@ -195,7 +200,12 @@ class Anime extends API {
if (( ! empty($data['mal_id'])) && $this->anilistEnabled) 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(); $results = $requester->makeRequests();
@ -223,7 +233,12 @@ class Anime extends API {
if (( ! empty($data['mal_id'])) && $this->anilistEnabled) 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(); $results = $requester->makeRequests();
@ -252,7 +267,12 @@ class Anime extends API {
if ($this->anilistEnabled && $malId !== null) 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(); $results = $requester->makeRequests();

View File

@ -63,6 +63,8 @@ abstract class AbstractType implements ArrayAccess, Countable {
*/ */
public function __isset($name): bool public function __isset($name): bool
{ {
// This returns the expected results because unset
// properties no longer exist on the class
return property_exists($this, $name); return property_exists($this, $name);
} }
@ -101,12 +103,9 @@ abstract class AbstractType implements ArrayAccess, Countable {
*/ */
public function __get($name) public function __get($name)
{ {
if (property_exists($this, $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->$name; return ($this->__isset($name)) ? $this->$name : NULL;
}
throw new UndefinedPropertyException("Trying to get undefined property: '$name'");
} }
/** /**
@ -210,7 +209,7 @@ abstract class AbstractType implements ArrayAccess, Countable {
*/ */
public function isEmpty(): bool public function isEmpty(): bool
{ {
foreach ($this as $key => $value) foreach ($this as $value)
{ {
if ( ! empty($value)) if ( ! empty($value))
{ {