4.1 Beta...ish #12
@ -10,6 +10,3 @@ whose_list = "Tim"
|
||||
|
||||
# do you wish to show the anime collection?
|
||||
show_anime_collection = true
|
||||
|
||||
# path to public directory on the server
|
||||
asset_dir = "/../../public"
|
@ -29,10 +29,10 @@ use Aviat\AnimeClient\API\Enum\{
|
||||
* Constants and mappings for the Anilist API
|
||||
*/
|
||||
final class Anilist {
|
||||
const AUTH_URL = 'https://anilist.co/api/v2/oauth/authorize';
|
||||
const BASE_URL = 'https://graphql.anilist.co';
|
||||
public const AUTH_URL = 'https://anilist.co/api/v2/oauth/authorize';
|
||||
public const BASE_URL = 'https://graphql.anilist.co';
|
||||
|
||||
const KITSU_ANILIST_WATCHING_STATUS_MAP = [
|
||||
public const KITSU_ANILIST_WATCHING_STATUS_MAP = [
|
||||
KAWS::WATCHING => AnimeWatchingStatus::WATCHING,
|
||||
KAWS::COMPLETED => AnimeWatchingStatus::COMPLETED,
|
||||
KAWS::ON_HOLD => AnimeWatchingStatus::ON_HOLD,
|
||||
@ -40,7 +40,7 @@ final class Anilist {
|
||||
KAWS::PLAN_TO_WATCH => AnimeWatchingStatus::PLAN_TO_WATCH,
|
||||
];
|
||||
|
||||
const ANILIST_KITSU_WATCHING_STATUS_MAP = [
|
||||
public const ANILIST_KITSU_WATCHING_STATUS_MAP = [
|
||||
AnimeWatchingStatus::WATCHING => KAWS::WATCHING,
|
||||
AnimeWatchingStatus::COMPLETED => KAWS::COMPLETED,
|
||||
AnimeWatchingStatus::ON_HOLD => KAWS::ON_HOLD,
|
||||
@ -48,7 +48,7 @@ final class Anilist {
|
||||
AnimeWatchingStatus::PLAN_TO_WATCH => KAWS::PLAN_TO_WATCH,
|
||||
];
|
||||
|
||||
const KITSU_ANILIST_READING_STATUS_MAP = [
|
||||
public const KITSU_ANILIST_READING_STATUS_MAP = [
|
||||
KMRS::READING => MangaReadingStatus::READING,
|
||||
KMRS::COMPLETED => MangaReadingStatus::COMPLETED,
|
||||
KMRS::ON_HOLD => MangaReadingStatus::ON_HOLD,
|
||||
@ -56,7 +56,7 @@ final class Anilist {
|
||||
KMRS::PLAN_TO_READ => MangaReadingStatus::PLAN_TO_READ,
|
||||
];
|
||||
|
||||
const ANILIST_KITSU_READING_STATUS_MAP = [
|
||||
public const ANILIST_KITSU_READING_STATUS_MAP = [
|
||||
MangaReadingStatus::READING => KMRS::READING,
|
||||
MangaReadingStatus::COMPLETED => KMRS::COMPLETED,
|
||||
MangaReadingStatus::ON_HOLD => KMRS::ON_HOLD,
|
||||
|
@ -341,9 +341,9 @@ final class Model {
|
||||
* Get information about a particular anime
|
||||
*
|
||||
* @param string $animeId
|
||||
* @return array
|
||||
* @return Anime
|
||||
*/
|
||||
public function getAnimeById(string $animeId): array
|
||||
public function getAnimeById(string $animeId): Anime
|
||||
{
|
||||
$baseData = $this->getRawMediaDataById('anime', $animeId);
|
||||
return $this->animeTransformer->transform($baseData);
|
||||
@ -455,7 +455,7 @@ final class Model {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the anine entries, that are organized for output to html
|
||||
* Get all the anime entries, that are organized for output to html
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -40,7 +40,7 @@ final class AnimeTransformer extends AbstractTransformer {
|
||||
sort($item['genres']);
|
||||
|
||||
$title = $item['canonicalTitle'];
|
||||
$titles = array_diff($item['titles'], [$title]);
|
||||
$titles = array_unique(array_diff($item['titles'], [$title]));
|
||||
|
||||
return new Anime([
|
||||
'age_rating' => $item['ageRating'],
|
||||
|
@ -33,7 +33,6 @@ final class MangaTransformer extends AbstractTransformer {
|
||||
*/
|
||||
public function transform($item): MangaPage
|
||||
{
|
||||
// \dump($item);
|
||||
$genres = [];
|
||||
|
||||
foreach($item['included'] as $included)
|
||||
@ -46,11 +45,13 @@ final class MangaTransformer extends AbstractTransformer {
|
||||
|
||||
sort($genres);
|
||||
|
||||
$title = $item['canonicalTitle'];
|
||||
$titles = array_unique(array_diff($item['titles'], [$title]));
|
||||
|
||||
return new MangaPage([
|
||||
'id' => $item['id'],
|
||||
'title' => $item['canonicalTitle'],
|
||||
'en_title' => $item['titles']['en'],
|
||||
'jp_title' => $item['titles']['en_jp'],
|
||||
'title' => $title,
|
||||
'titles' => $titles,
|
||||
'cover_image' => $item['posterImage']['small'],
|
||||
'manga_type' => $item['mangaType'],
|
||||
'chapter_count' => $this->count($item['chapterCount']),
|
||||
|
@ -85,11 +85,11 @@ final class ListItem {
|
||||
* Update a list item
|
||||
*
|
||||
* @param string $id
|
||||
* @param AbstractType $data
|
||||
* @param array $data
|
||||
* @param string $type
|
||||
* @return Request
|
||||
*/
|
||||
public function update(string $id, AbstractType $data, string $type = 'anime'): Request
|
||||
public function update(string $id, array $data, string $type = 'anime'): Request
|
||||
{
|
||||
$config = $this->container->get('config');
|
||||
|
||||
|
@ -148,11 +148,11 @@ final class Model {
|
||||
/**
|
||||
* Update a list item
|
||||
*
|
||||
* @param FormItem $data
|
||||
* @param array $data
|
||||
* @param string $type "anime" or "manga"
|
||||
* @return Request
|
||||
*/
|
||||
public function updateListItem(FormItem $data, string $type = 'anime'): Request
|
||||
public function updateListItem($data, string $type = 'anime'): Request
|
||||
{
|
||||
$updateData = [];
|
||||
|
||||
|
@ -38,10 +38,10 @@ final class AnimeListTransformer extends AbstractTransformer {
|
||||
/**
|
||||
* Transform Kitsu episode data to MAL episode data
|
||||
*
|
||||
* @param array $item
|
||||
* @return AnimeFormItem
|
||||
* @param mixed $item
|
||||
* @return array
|
||||
*/
|
||||
public function untransform(array $item): AnimeFormItem
|
||||
public function untransform($item): array
|
||||
{
|
||||
$map = [
|
||||
'id' => $item['mal_id'],
|
||||
@ -81,6 +81,6 @@ final class AnimeListTransformer extends AbstractTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
return new AnimeFormItem($map);
|
||||
return $map;
|
||||
}
|
||||
}
|
@ -37,18 +37,16 @@ final class MangaListTransformer extends AbstractTransformer {
|
||||
/**
|
||||
* Transform Kitsu data to MAL data
|
||||
*
|
||||
* @param array $item
|
||||
* @return array
|
||||
* @param mixed $item
|
||||
* @return
|
||||
*/
|
||||
public function untransform(array $item): array
|
||||
public function untransform($item): array
|
||||
{
|
||||
$map = [
|
||||
'id' => $item['mal_id'],
|
||||
'id' => $item['mal_id'] ?? $item['malId'],
|
||||
'data' => []
|
||||
];
|
||||
|
||||
$data =& $item['data'];
|
||||
|
||||
foreach($item['data'] as $key => $value)
|
||||
{
|
||||
switch($key)
|
||||
|
@ -17,7 +17,7 @@
|
||||
namespace Aviat\AnimeClient;
|
||||
|
||||
use Aviat\Ion\ConfigInterface;
|
||||
use Yosymfony\Toml\Toml;
|
||||
use Yosymfony\Toml\{Toml, TomlBuilder};
|
||||
|
||||
/**
|
||||
* Load configuration options from .toml files
|
||||
@ -51,6 +51,86 @@ function loadToml(string $path): array
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the array sequential, not associative?
|
||||
*
|
||||
* @param mixed $array
|
||||
* @return bool
|
||||
*/
|
||||
function isSequentialArray($array): bool
|
||||
{
|
||||
if ( ! is_array($array))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach ($array as $k => $v)
|
||||
{
|
||||
if ($k !== $i++)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
function _iterateToml(TomlBuilder $builder, $data, $parentKey = NULL): void
|
||||
{
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
if ($value === NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (is_scalar($value) || isSequentialArray($value))
|
||||
{
|
||||
// $builder->addTable('');
|
||||
$builder->addValue($key, $value);
|
||||
continue;
|
||||
}
|
||||
|
||||
$newKey = ($parentKey !== NULL)
|
||||
? "{$parentKey}.{$key}"
|
||||
: $key;
|
||||
|
||||
if ( ! isSequentialArray($value))
|
||||
{
|
||||
$builder->addTable($newKey);
|
||||
}
|
||||
|
||||
_iterateToml($builder, $value, $newKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize config data into a Toml file
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return string
|
||||
*/
|
||||
function arrayToToml($data): string
|
||||
{
|
||||
$builder = new TomlBuilder();
|
||||
|
||||
_iterateToml($builder, $data);
|
||||
|
||||
return $builder->getTomlString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize toml back to an array
|
||||
*
|
||||
* @param string $toml
|
||||
* @return array
|
||||
*/
|
||||
function tomlToArray(string $toml): array
|
||||
{
|
||||
return Toml::parse($toml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that folder permissions are correct for proper operation
|
||||
*
|
||||
@ -64,7 +144,6 @@ function checkFolderPermissions(ConfigInterface $config): array
|
||||
|
||||
$pathMap = [
|
||||
'app/logs' => realpath(__DIR__ . '/../app/logs'),
|
||||
'public/js/cache' => "{$publicDir}/js/cache",
|
||||
'public/images/avatars' => "{$publicDir}/images/avatars",
|
||||
'public/images/anime' => "{$publicDir}/images/anime",
|
||||
'public/images/characters' => "{$publicDir}/images/characters",
|
||||
|
@ -170,9 +170,8 @@ final class Index extends BaseController {
|
||||
$auth = $this->container->get('auth');
|
||||
$this->outputHTML('settings', [
|
||||
'auth' => $auth,
|
||||
'config' => $this->config,
|
||||
'title' => $this->config->get('whose_list') . "'s Settings",
|
||||
'base_settings' => $this->config->get('default_config'),
|
||||
'user_settings' => $this->config->get('user_config_settings'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -109,9 +109,9 @@ class Anime extends API {
|
||||
* Get anime by its kitsu id
|
||||
*
|
||||
* @param string $animeId
|
||||
* @return array
|
||||
* @return AnimeType
|
||||
*/
|
||||
public function getAnimeById(string $animeId): array
|
||||
public function getAnimeById(string $animeId): AnimeType
|
||||
{
|
||||
return $this->kitsuModel->getAnimeById($animeId);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\Types;
|
||||
use ArrayAccess;
|
||||
use LogicException;
|
||||
|
||||
abstract class AbstractType implements ArrayAccess {
|
||||
class AbstractType implements ArrayAccess {
|
||||
/**
|
||||
* Populate values for unserializing data
|
||||
*
|
||||
|
@ -22,14 +22,13 @@ namespace Aviat\AnimeClient\Types;
|
||||
final class MangaPage extends AbstractType {
|
||||
public $chapter_count;
|
||||
public $cover_image;
|
||||
public $en_title;
|
||||
public $genres;
|
||||
public $id;
|
||||
public $included;
|
||||
public $jp_title;
|
||||
public $manga_type;
|
||||
public $synopsis;
|
||||
public $title;
|
||||
public $titles;
|
||||
public $url;
|
||||
public $volume_count;
|
||||
}
|
||||
|
60
tests/AnimeClientTest.php
Normal file
60
tests/AnimeClientTest.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* Hummingbird Anime List Client
|
||||
*
|
||||
* An API client for Kitsu and MyAnimeList 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\Tests;
|
||||
|
||||
use function Aviat\AnimeClient\arrayToToml;
|
||||
use function Aviat\AnimeClient\tomlToArray;
|
||||
|
||||
class AnimeClientTest extends AnimeClientTestCase
|
||||
{
|
||||
public function testArrayToToml ()
|
||||
{
|
||||
$arr = [
|
||||
'cat' => false,
|
||||
'foo' => 'bar',
|
||||
'dateTime' => (array) new \DateTime(),
|
||||
'bar' => [
|
||||
'a' => 1,
|
||||
'b' => 2,
|
||||
'c' => 3,
|
||||
],
|
||||
'baz' => [
|
||||
'x' => [1, 2, 3],
|
||||
'y' => [2, 4, 6],
|
||||
'z' => [3, 6, 9],
|
||||
],
|
||||
'foobar' => [
|
||||
'z' => 22/7,
|
||||
'a' => [
|
||||
'aa' => -8,
|
||||
'b' => [
|
||||
'aaa' => 4028,
|
||||
'c' => [1, 2, 3],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$toml = arrayToToml($arr);
|
||||
|
||||
echo $toml . "\n";
|
||||
|
||||
$parsedArray = tomlToArray($toml);
|
||||
|
||||
$this->assertEquals($arr, $parsedArray);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user