4.1 Beta...ish #12

Merged
timw4mail merged 88 commits from develop into master 2018-11-05 13:15:59 -05:00
29 changed files with 411 additions and 222 deletions
Showing only changes of commit e3b4b9dd32 - Show all commits

View File

@ -49,6 +49,7 @@
</div>
<?php endif ?>
<div class="row">
<div><?= $item['manga']['type'] ?></div>
<div class="user_rating">Rating: <?= $item['user_rating'] ?> / 10</div>
</div>

View File

@ -1,12 +1,61 @@
<?php
use function Aviat\AnimeClient\arrayToToml;
use function Aviat\AnimeClient\loadTomlByFile;
$settings = loadTomlByFile($config->get('config_dir'));
if ( ! $auth->isAuthenticated())
{
echo '<h1>Not Authorized</h1>';
return;
}
function render_settings_form ($data, $file)
{
ob_start();
foreach ($data as $key => $value)
{
?>
<tr>
<td><label for="<?= $key ?>"><?= $key ?></label></td>
<td>
<?php if (is_scalar($value)): ?>
<input
type="text"
id="<?= $key ?>"
name="config[<?= $file ?>][<?= $key ?>]"
value="<?= $value ?>"
/>
<?php else: ?>
<table><?= render_settings_form($value, $file); ?></table>
<?php endif ?>
</td>
</tr>
<?php
}
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
?>
<pre><?= print_r($_POST, TRUE) ?></pre>
<?php foreach($settings as $file => $properties): ?>
<form action="<?= $_SERVER['REQUEST_URI'] ?>" method="POST">
<table class="form">
<caption><?= $file ?></caption>
<tbody>
<?= render_settings_form($properties, $file); ?>
</tbody>
</table>
<button type="submit">Save Changes</button>
</form>
<?php endforeach ?>

View File

@ -24,6 +24,7 @@
"aura/session": "^2.0",
"aviat/banker": "^1.0.0",
"aviat/ion": "^2.3.0",
"ext-json": "*",
"ext-gd":"*",
"ext-pdo": "*",
"maximebf/consolekit": "^1.0",

View File

@ -17,7 +17,8 @@ try
(new Console([
'cache:clear' => Command\CacheClear::class,
'cache:refresh' => Command\CachePrime::class,
// 'lists:sync' => Command\SyncLists::class,
'lists:sync' => Command\SyncLists::class,
'mal_id:check' => Command\MALIDCheck::class,
]))->run();
}
catch (\Exception $e)

View File

@ -365,12 +365,10 @@
});
}
// Wire up mal checkbox
// Click on hidden MAL checkbox so
// that MAL id is passed
AnimeClient.on('main', 'change', '.big-check', (e) => {
const id = e.target.id;
AnimeClient.$('.mal-check').forEach(el => {
el.checked = false;
});
document.getElementById(`mal_${id}`).checked = true;
});
@ -386,7 +384,7 @@
results.push(`
<article class="media search">
<div class="name">
<input type="checkbox" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${x.id}" />
<label for="${item.slug}">
<img src="/public/images/anime/${x.id}.jpg" alt="" width="220" />
@ -422,7 +420,7 @@
results.push(`
<article class="media search">
<div class="name">
<input type="checkbox" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${x.id}" />
<label for="${item.slug}">
<img src="/public/images/manga/${x.id}.jpg" alt="" width="220" />
@ -595,7 +593,7 @@
AnimeClient.show(AnimeClient.$('#loading-shadow')[ 0 ]);
AnimeClient.ajax(AnimeClient.url('/manga/update'), {
AnimeClient.ajax(AnimeClient.url('/manga/increment'), {
data,
dataType: 'json',
type: 'POST',

File diff suppressed because one or more lines are too long

View File

@ -61,7 +61,7 @@ _.on('.manga.list', 'click', '.edit_buttons button', (e) => {
_.show(_.$('#loading-shadow')[ 0 ]);
_.ajax(_.url('/manga/update'), {
_.ajax(_.url('/manga/increment'), {
data,
dataType: 'json',
type: 'POST',

View File

@ -1,11 +1,9 @@
import _ from './base/AnimeClient.js';
// Wire up mal checkbox
// Click on hidden MAL checkbox so
// that MAL id is passed
_.on('main', 'change', '.big-check', (e) => {
const id = e.target.id;
_.$('.mal-check').forEach(el => {
el.checked = false;
})
document.getElementById(`mal_${id}`).checked = true;
});
@ -21,7 +19,7 @@ export function renderAnimeSearchResults (data) {
results.push(`
<article class="media search">
<div class="name">
<input type="checkbox" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${x.id}" />
<label for="${item.slug}">
<img src="/public/images/anime/${x.id}.jpg" alt="" width="220" />
@ -57,7 +55,7 @@ export function renderMangaSearchResults (data) {
results.push(`
<article class="media search">
<div class="name">
<input type="checkbox" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" id="mal_${item.slug}" name="mal_id" value="${x.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${x.id}" />
<label for="${item.slug}">
<img src="/public/images/manga/${x.id}.jpg" alt="" width="220" />

View File

@ -11,6 +11,7 @@ query ($name: String, $type: MediaType) {
private
notes
status
updatedAt
media {
id
idMal

View File

@ -18,10 +18,12 @@ namespace Aviat\AnimeClient\API\Anilist\Transformer;
use Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Anilist as AnilistStatus;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\{Anime, AnimeListItem, AnimeFormItem};
use Aviat\AnimeClient\Types\{AnimeListItem, FormItem};
use Aviat\Ion\Transformer\AbstractTransformer;
use DateTime;
class AnimeListTransformer extends AbstractTransformer {
public function transform($item): AnimeListItem
@ -33,11 +35,11 @@ class AnimeListTransformer extends AbstractTransformer {
* Transform Anilist list item to Kitsu form update format
*
* @param array $item
* @return AnimeFormItem
* @return FormItem
*/
public function untransform(array $item): AnimeFormItem
public function untransform(array $item): FormItem
{
return new AnimeFormItem([
return new FormItem([
'id' => $item['id'],
'mal_id' => $item['media']['idMal'],
'data' => [
@ -48,7 +50,10 @@ class AnimeListTransformer extends AbstractTransformer {
'reconsumeCount' => $item['repeat'],
'reconsuming' => $item['status'] === AnilistStatus::REPEATING,
'status' => AnimeWatchingStatus::ANILIST_TO_KITSU[$item['status']],
]
'updatedAt' => (new DateTime())
->setTimestamp($item['updatedAt'])
->format(DateTime::W3C)
],
]);
}

View File

@ -18,10 +18,12 @@ namespace Aviat\AnimeClient\API\Anilist\Transformer;
use Aviat\AnimeClient\API\Enum\MangaReadingStatus\Anilist as AnilistStatus;
use Aviat\AnimeClient\API\Mapping\MangaReadingStatus;
use Aviat\AnimeClient\Types\MangaFormItem;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Transformer\AbstractTransformer;
use DateTime;
class MangaListTransformer extends AbstractTransformer {
public function transform($item)
@ -33,11 +35,11 @@ class MangaListTransformer extends AbstractTransformer {
* Transform Anilist list item to Kitsu form update format
*
* @param array $item
* @return MangaFormItem
* @return FormItem
*/
public function untransform(array $item): MangaFormItem
public function untransform(array $item): FormItem
{
return new MangaFormItem([
return new FormItem([
'id' => $item['id'],
'mal_id' => $item['media']['idMal'],
'data' => [
@ -48,6 +50,9 @@ class MangaListTransformer extends AbstractTransformer {
'reconsumeCount' => $item['repeat'],
'reconsuming' => $item['status'] === AnilistStatus::REPEATING,
'status' => MangaReadingStatus::ANILIST_TO_KITSU[$item['status']],
'updatedAt' => (new DateTime())
->setTimestamp($item['updatedAt'])
->format(DateTime::W3C),
]
]);
}

View File

@ -67,7 +67,7 @@ final class Auth {
* @param string $password
* @return boolean
*/
public function authenticate($password)
public function authenticate(string $password): bool
{
$config = $this->container->get('config');
$username = $config->get(['kitsu_username']);
@ -117,7 +117,7 @@ final class Auth {
* @param string $token
* @return boolean
*/
public function reAuthenticate(string $token)
public function reAuthenticate(string $token): bool
{
try
{
@ -162,7 +162,7 @@ final class Auth {
*
* @return boolean
*/
public function isAuthenticated()
public function isAuthenticated(): bool
{
return ($this->get_auth_token() !== FALSE);
}
@ -172,7 +172,7 @@ final class Auth {
*
* @return void
*/
public function logout()
public function logout(): void
{
$this->segment->clear();
}
@ -185,16 +185,20 @@ final class Auth {
public function get_auth_token()
{
$token = $this->segment->get('auth_token', FALSE);
$refresh_token = $this->segment->get('refresh_token', FALSE);
$refreshToken = $this->segment->get('refresh_token', FALSE);
$isExpired = time() > $this->segment->get('auth_token_expires', 0);
// Attempt to re-authenticate with refresh token
if ($isExpired && $refresh_token)
if ($isExpired && $refreshToken)
{
if ($this->reAuthenticate($refreshToken))
{
$reauthenticated = $this->reAuthenticate($refresh_token);
return $this->segment->get('auth_token', FALSE);
}
return FALSE;
}
return $token;
}
}

View File

@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\API\Kitsu\Transformer;
use Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\Types\{
Anime,
AnimeFormItem,
FormItem,
AnimeListItem
};
use Aviat\Ion\Transformer\AbstractTransformer;
@ -95,7 +95,7 @@ final class AnimeListTransformer extends AbstractTransformer {
'title' => $title,
'titles' => $titles,
'slug' => $anime['slug'],
'show_type' => $this->string($anime['showType'])->upperCaseFirst()->__toString(),
'show_type' => $this->string($anime['subtype'])->upperCaseFirst()->__toString(),
'cover_image' => $anime['posterImage']['small'],
'genres' => $genres,
'streaming_links' => $streamingLinks,
@ -114,14 +114,14 @@ final class AnimeListTransformer extends AbstractTransformer {
* api response format
*
* @param array $item Transformed library item
* @return AnimeFormItem API library item
* @return FormItem API library item
*/
public function untransform($item): AnimeFormItem
public function untransform($item): FormItem
{
$privacy = (array_key_exists('private', $item) && $item['private']);
$rewatching = (array_key_exists('rewatching', $item) && $item['rewatching']);
$untransformed = new AnimeFormItem([
$untransformed = new FormItem([
'id' => $item['id'],
'anilist_item_id' => $item['anilist_item_id'] ?? NULL,
'mal_id' => $item['mal_id'] ?? NULL,

View File

@ -18,7 +18,7 @@ namespace Aviat\AnimeClient\API\Kitsu\Transformer;
use Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\Types\{
MangaFormItem, MangaFormItemData,
FormItem, FormItemData,
MangaListItem, MangaListItemDetail
};
use Aviat\Ion\StringWrapper;
@ -97,7 +97,7 @@ final class MangaListTransformer extends AbstractTransformer {
'slug' => $manga['slug'],
'title' => $title,
'titles' => $titles,
'type' => $manga['mangaType'],
'type' => $this->string($manga['subtype'])->upperCaseFirst()->__toString(),
'url' => 'https://kitsu.io/manga/' . $manga['slug'],
]),
'reading_status' => $item['attributes']['status'],
@ -114,16 +114,16 @@ final class MangaListTransformer extends AbstractTransformer {
* Untransform data to update the api
*
* @param array $item
* @return MangaFormItem
* @return FormItem
*/
public function untransform($item): MangaFormItem
public function untransform($item): FormItem
{
$rereading = array_key_exists('rereading', $item) && (bool)$item['rereading'];
$map = new MangaFormItem([
$map = new FormItem([
'id' => $item['id'],
'mal_id' => $item['mal_id'],
'data' => new MangaFormItemData([
'data' => new FormItemData([
'status' => $item['status'],
'reconsuming' => $rereading,
'reconsumeCount' => (int)$item['reread_count'],

View File

@ -51,6 +51,26 @@ function loadToml(string $path): array
return $output;
}
/**
* Load configuration from toml files, keyed by the original file
*
* @param string $path
* @return array
*/
function loadTomlByFile(string $path): array
{
$output = [];
$files = glob("{$path}/*.toml");
foreach ($files as $file)
{
$config = Toml::parseFile($file);
$output[basename($file)] = $config;
}
return $output;
}
/**
* Is the array sequential, not associative?
*

192
src/Command/MALIDCheck.php Normal file
View File

@ -0,0 +1,192 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Command;
use Aviat\AnimeClient\API\{
APIRequestBuilder,
JsonAPI,
FailedResponseException,
ParallelAPIRequest
};
use Aviat\Ion\Json;
final class MALIDCheck extends BaseCommand {
private $kitsuModel;
/**
* Check MAL mapping validity
*
* @param array $args
* @param array $options
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
*/
public function execute(array $args, array $options = []): void
{
$this->setContainer($this->setupContainer());
$this->setCache($this->container->get('cache'));
$this->kitsuModel = $this->container->get('kitsu-model');
// @TODO: Stuff!
}
private function getListIds()
{
$this->getListCounts('anime');
$this->getListCounts('manga');
}
private function getListCounts($type): void
{
$uType = ucfirst($type);
$kitsuCount = 0;
try
{
$kitsuCount = $this->kitsuModel->{"get{$uType}ListCount"}();
} catch (FailedResponseException $e)
{
dump($e);
}
$this->echoBox("Number of Kitsu {$type} list items: {$kitsuCount}");
}
/**
* Format a kitsu list for the sake of comparision
*
* @param string $type
* @return array
*/
protected function formatKitsuList(string $type = 'anime'): array
{
$data = $this->kitsuModel->{'getFull' . ucfirst($type) . 'List'}();
if (empty($data))
{
return [];
}
$includes = JsonAPI::organizeIncludes($data['included']);
$includes['mappings'] = $this->filterMappings($includes['mappings'], $type);
$output = [];
foreach ($data['data'] as $listItem)
{
$id = $listItem['relationships'][$type]['data']['id'];
$potentialMappings = $includes[$type][$id]['relationships']['mappings'];
$malId = NULL;
foreach ($potentialMappings as $mappingId)
{
if (array_key_exists($mappingId, $includes['mappings']))
{
$malId = $includes['mappings'][$mappingId]['externalId'];
}
}
// Skip to the next item if there isn't a MAL ID
if ($malId === NULL)
{
continue;
}
$output[$listItem['id']] = [
'id' => $listItem['id'],
'malId' => $malId,
'data' => $listItem['attributes'],
];
}
return $output;
}
/**
* Filter Kitsu mappings for the specified type
*
* @param array $includes
* @param string $type
* @return array
*/
protected function filterMappings(array $includes, string $type = 'anime'): array
{
$output = [];
foreach ($includes as $id => $mapping)
{
if ($mapping['externalSite'] === "myanimelist/{$type}")
{
$output[$id] = $mapping;
}
}
return $output;
}
protected function checkMALIds(array $kitsuList, string $type)
{
$requester = new ParallelAPIRequest();
}
/**
* Create/Update list items on Kitsu
*
* @param array $itemsToUpdate
* @param string $action
* @param string $type
*/
protected function updateKitsuListItems(array $itemsToUpdate, string $action = 'update', string $type = 'anime'): void
{
$requester = new ParallelAPIRequest();
foreach ($itemsToUpdate as $item)
{
if ($action === 'update')
{
$requester->addRequest($this->kitsuModel->updateListItem($item));
} else if ($action === 'create')
{
$requester->addRequest($this->kitsuModel->createListItem($item));
}
}
$responses = $requester->makeRequests();
foreach ($responses as $key => $response)
{
$responseData = Json::decode($response);
$id = $itemsToUpdate[$key]['id'];
if ( ! array_key_exists('errors', $responseData))
{
$verb = ($action === 'update') ? 'updated' : 'created';
$this->echoBox("Successfully {$verb} Kitsu {$type} list item with id: {$id}");
} else
{
dump($responseData);
$verb = ($action === 'update') ? 'update' : 'create';
$this->echoBox("Failed to {$verb} Kitsu {$type} list item with id: {$id}");
}
}
}
}

View File

@ -16,14 +16,18 @@
namespace Aviat\AnimeClient\Command;
use Aviat\AnimeClient\API\
{FailedResponseException, JsonAPI, Kitsu\Transformer\MangaListTransformer, ParallelAPIRequest};
use Aviat\AnimeClient\API\{
FailedResponseException,
JsonAPI,
Kitsu\Transformer\MangaListTransformer,
ParallelAPIRequest
};
use Aviat\AnimeClient\API\Anilist\Transformer\{
AnimeListTransformer as AALT,
MangaListTransformer as AMLT,
MangaListTransformer as AMLT
};
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
use Aviat\AnimeClient\Types\{AnimeFormItem, MangaFormItem};
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Json;
use DateTime;
@ -49,9 +53,9 @@ final class SyncLists extends BaseCommand {
*
* @param array $args
* @param array $options
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @return void
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @throws \Throwable
*/
public function execute(array $args, array $options = []): void
{
@ -65,10 +69,10 @@ final class SyncLists extends BaseCommand {
}
/**
* Attempt to synchronize external apis
* Attempt to synchronize external APIs
*
* @param string $type anime|manga
* @return void
* @param string $type
* @throws \Throwable
*/
protected function sync(string $type): void
{
@ -157,6 +161,8 @@ final class SyncLists extends BaseCommand {
* Format an Anilist anime list for comparison
*
* @return array
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
*/
protected function formatAnilistAnimeList(): array
{
@ -188,6 +194,8 @@ final class SyncLists extends BaseCommand {
* Format an Anilist manga list for comparison
*
* @return array
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
*/
protected function formatAnilistMangaList(): array
{
@ -223,7 +231,8 @@ final class SyncLists extends BaseCommand {
*/
protected function formatKitsuList(string $type = 'anime'): array
{
$data = $this->kitsuModel->{'getFullRaw' . ucfirst($type) . 'List'}();
$method = 'getFullRaw' . ucfirst($type) . 'List';
$data = $this->kitsuModel->$method();
if (empty($data))
{
@ -312,7 +321,7 @@ final class SyncLists extends BaseCommand {
{
$malId = $kitsuItem['malId'];
if (in_array($malId, $malBlackList))
if (\in_array((int)$malId, $malBlackList, TRUE))
{
continue;
}
@ -356,14 +365,10 @@ final class SyncLists extends BaseCommand {
'repeat' => $kItem['reconsumeCount'],
'score' => $kItem['ratingTwenty'] / 2,
'status' => $newItemStatus,
], // $kitsuItem['data']
],
];
}
//dump($itemsToAddToAnilist);
//die();
return [
'addToAnilist' => $itemsToAddToAnilist,
'updateAnilist' => $anilistUpdateItems,
@ -390,6 +395,7 @@ final class SyncLists extends BaseCommand {
'status',
];
$diff = [];
$dateDiff = new DateTime($kitsuItem['data']['updatedAt']) <=> new DateTime((string)$anilistItem['data']['updatedAt']);
// Correct differences in notation
$kitsuItem['data']['rating'] = $kitsuItem['data']['ratingTwenty'] / 2;
@ -429,7 +435,6 @@ final class SyncLists extends BaseCommand {
$return['updateType'][] = 'kitsu';
}
// If status is the same, and progress count is different, use greater progress
if ($sameStatus && ( ! $sameProgress))
{
@ -445,16 +450,23 @@ final class SyncLists extends BaseCommand {
}
}
// If status is different, go with Kitsu
// If status is different, use the status of the more recently updated item
if ( ! $sameStatus)
{
if ($dateDiff === 1)
{
$update['data']['status'] = $kitsuItem['data']['status'];
$return['updateType'][] = 'anilist';
} else if ($dateDiff === -1)
{
$update['data']['status'] = $anilistItem['data']['status'];
$return['updateType'][] = 'kitsu';
}
}
// If status and progress are different, it's a bit more complicated...
// But, at least for now, assume newer record is correct
/* if ( ! ($sameStatus || $sameProgress))
if ( ! ($sameStatus || $sameProgress))
{
if ($dateDiff === 1)
{
@ -478,18 +490,17 @@ final class SyncLists extends BaseCommand {
$return['updateType'][] = 'kitsu';
}
}*/
}
// If rating is different, use the kitsu rating, unless the other rating
// is set, and the kitsu rating is not set
// Use the first set rating, otherwise use the newer rating
if ( ! $sameRating)
{
if ($kitsuItem['data']['rating'] !== 0)
if ($kitsuItem['data']['rating'] !== 0 && $dateDiff === 1)
{
$update['data']['rating'] = $kitsuItem['data']['rating'];
$return['updateType'][] = 'anilist';
}
else
else if($dateDiff === -1)
{
$update['data']['rating'] = $anilistItem['data']['rating'];
$return['updateType'][] = 'kitsu';
@ -526,25 +537,12 @@ final class SyncLists extends BaseCommand {
}
}
// If status is different, use the status of the more recently updated item
/* if ( ! $sameStatus)
{
if ($dateDiff === 1)
{
$update['data']['status'] = $kitsuItem['data']['status'];
$return['updateType'][] = 'anilist';
}
else if ($dateDiff === -1)
{
$update['data']['status'] = $anilistItem['data']['status'];
$return['updateType'][] = 'kitsu';
}
} */
$return['meta'] = [
'kitsu' => $kitsuItem['data'],
'anilist' => $anilistItem['data'],
// 'dateDiff' => $dateDiff,
'dateDiff' => $dateDiff,
'diff' => $diff,
];
$return['data'] = $update;
@ -568,7 +566,7 @@ final class SyncLists extends BaseCommand {
$return['data']['data'] = array_merge($prevData, $return['data']['data']);
}
// dump($return);
dump($return);
return $return;
}
@ -579,18 +577,17 @@ final class SyncLists extends BaseCommand {
* @param array $itemsToUpdate
* @param string $action
* @param string $type
* @throws \Throwable
*/
protected function updateKitsuListItems(array $itemsToUpdate, string $action = 'update', string $type = 'anime'): void
{
$requester = new ParallelAPIRequest();
foreach($itemsToUpdate as $item)
{
$typeClass = '\\Aviat\\AnimeClient\\Types\\' . ucFirst($type) . 'FormItem';
if ($action === 'update')
{
$requester->addRequest(
$this->kitsuModel->updateListItem(new $typeClass($item))
$this->kitsuModel->updateListItem(new FormItem($item))
);
}
else if ($action === 'create')
@ -626,19 +623,18 @@ final class SyncLists extends BaseCommand {
* @param array $itemsToUpdate
* @param string $action
* @param string $type
* @throws \Throwable
*/
protected function updateAnilistListItems(array $itemsToUpdate, string $action = 'update', string $type = 'anime'): void
{
$requester = new ParallelAPIRequest();
$typeClass = '\\Aviat\\AnimeClient\\Types\\' . ucFirst($type) . 'FormItem';
foreach($itemsToUpdate as $item)
{
if ($action === 'update')
{
$requester->addRequest(
$this->anilistModel->updateListItem(new $typeClass($item), $type)
$this->anilistModel->updateListItem(new FormItem($item), $type)
);
}
else if ($action === 'create')

View File

@ -20,7 +20,7 @@ use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\API\Kitsu\Transformer\AnimeListTransformer;
use Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Kitsu as KitsuWatchingStatus;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\AnimeFormItem;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Json;
use Aviat\Ion\StringWrapper;
@ -204,7 +204,7 @@ final class Anime extends BaseController {
// large form-based updates
$transformer = new AnimeListTransformer();
$postData = $transformer->untransform($data);
$fullResult = $this->model->updateLibraryItem(new AnimeFormItem($postData));
$fullResult = $this->model->updateLibraryItem(new FormItem($postData));
if ($fullResult['statusCode'] === 200)
{
@ -235,7 +235,7 @@ final class Anime extends BaseController {
$data = $this->request->getParsedBody();
}
$response = $this->model->incrementLibraryItem(new AnimeFormItem($data));
$response = $this->model->incrementLibraryItem(new FormItem($data));
$this->cache->clear();
$this->outputJSON($response['body'], $response['statusCode']);

View File

@ -175,6 +175,16 @@ final class Index extends BaseController {
]);
}
public function settings_post()
{
$auth = $this->container->get('auth');
$this->outputHTML('settings', [
'auth' => $auth,
'config' => $this->config,
'title' => $this->config->get('whose_list') . "'s Settings",
]);
}
/**
* Get image covers from kitsu
*

View File

@ -20,7 +20,7 @@ use Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\API\Kitsu\Transformer\MangaListTransformer;
use Aviat\AnimeClient\API\Mapping\MangaReadingStatus;
use Aviat\AnimeClient\Model\Manga as MangaModel;
use Aviat\AnimeClient\Types\MangaFormItem;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\{Json, StringWrapper};
@ -207,7 +207,7 @@ final class Manga extends Controller {
// large form-based updates
$transformer = new MangaListTransformer();
$post_data = $transformer->untransform($data);
$full_result = $this->model->updateLibraryItem(new MangaFormItem($post_data));
$full_result = $this->model->updateLibraryItem(new FormItem($post_data));
if ($full_result['statusCode'] === 200)
{
@ -237,7 +237,7 @@ final class Manga extends Controller {
$data = $this->request->getParsedBody();
}
$response = $this->model->incrementLibraryItem(new MangaFormItem($data));
$response = $this->model->incrementLibraryItem(new FormItem($data));
$this->cache->clear();
$this->outputJSON($response['body'], $response['statusCode']);

View File

@ -20,7 +20,7 @@ use Aviat\AnimeClient\API\ParallelAPIRequest;
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Types\{
Anime as AnimeType,
AnimeFormItem,
FormItem,
AnimeListItem
};
use Aviat\Ion\Di\ContainerInterface;
@ -187,10 +187,10 @@ class Anime extends API {
/**
* Increment progress for the specified anime
*
* @param AnimeFormItem $data
* @param FormItem $data
* @return array
*/
public function incrementLibraryItem(AnimeFormItem $data): array
public function incrementLibraryItem(FormItem $data): array
{
$requester = new ParallelAPIRequest();
$requester->addRequest($this->kitsuModel->incrementListItem($data), 'kitsu');
@ -216,10 +216,10 @@ class Anime extends API {
/**
* Update a list entry
*
* @param AnimeFormItem $data
* @param FormItem $data
* @return array
*/
public function updateLibraryItem(AnimeFormItem $data): array
public function updateLibraryItem(FormItem $data): array
{
$requester = new ParallelAPIRequest();
$requester->addRequest($this->kitsuModel->updateListItem($data), 'kitsu');

View File

@ -22,7 +22,7 @@ use Aviat\AnimeClient\API\{
ParallelAPIRequest
};
use Aviat\AnimeClient\Types\{
MangaFormItem,
FormItem,
MangaListItem,
MangaPage
};
@ -149,10 +149,10 @@ class Manga extends API {
/**
* Update a list entry
*
* @param MangaFormItem $data
* @param FormItem $data
* @return array
*/
public function updateLibraryItem(MangaFormItem $data): array
public function updateLibraryItem(FormItem $data): array
{
$requester = new ParallelAPIRequest();
$requester->addRequest($this->kitsuModel->updateListItem($data), 'kitsu');
@ -177,10 +177,10 @@ class Manga extends API {
/**
* Increase the progress of a list entry
*
* @param MangaFormItem $data
* @param FormItem $data
* @return array
*/
public function incrementLibraryItem(MangaFormItem $data): array
public function incrementLibraryItem(FormItem $data): array
{
$requester = new ParallelAPIRequest();
$requester->addRequest($this->kitsuModel->incrementListItem($data), 'kitsu');

View File

@ -26,7 +26,7 @@ abstract class AbstractType implements ArrayAccess {
* @param $properties
* @return mixed
*/
public static function __set_state($properties)
public static function __set_state($properties): self
{
return new static($properties);
}
@ -165,7 +165,7 @@ abstract class AbstractType implements ArrayAccess {
{
$object = $parent ?? $this;
if (is_scalar($object))
if (is_scalar($object) || empty($object))
{
return $object;
}
@ -174,7 +174,7 @@ abstract class AbstractType implements ArrayAccess {
foreach ($object as $key => $value)
{
$output[$key] = is_scalar($value)
$output[$key] = (is_scalar($value) || empty($value))
? $value
: $this->toArray((array) $value);
}

View File

@ -1,27 +0,0 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class AnimeFormItem extends FormItem {
public function setData($value): void
{
$this->data = new AnimeFormItemData($value);
}
}

View File

@ -1,22 +0,0 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
final class AnimeFormItemData extends FormItemData {}

View File

@ -19,12 +19,15 @@ namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
*/
abstract class FormItem extends AbstractType {
class FormItem extends AbstractType {
public $id;
public $anilist_item_id;
public $mal_id;
public $data;
abstract public function setData($value): void;
public function setData($value): void
{
$this->data = new FormItemData($value);
}
}

View File

@ -17,9 +17,9 @@
namespace Aviat\AnimeClient\Types;
/**
* Type representing an Anime object for display
* Type representing a Media object for editing/syncing
*/
abstract class FormItemData extends AbstractType {
class FormItemData extends AbstractType {
public $notes;
public $private;
public $progress;
@ -28,4 +28,5 @@ abstract class FormItemData extends AbstractType {
public $reconsumeCount;
public $reconsuming;
public $status;
public $updatedAt;
}

View File

@ -1,28 +0,0 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
/**
* Form data for updating a Manga List item
*/
final class MangaFormItem extends FormItem {
public function setData($value): void
{
$this->data = new MangaFormItemData($value);
}
}

View File

@ -1,19 +0,0 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.0
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
final class MangaFormItemData extends FormItemData {}