diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2709e948..59d45874 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,7 +15,7 @@ test:7:
- php composer.phar install --no-dev
image: php:7
script:
- - phpunit -c build
+ - phpunit -c build --coverage-text
test:7.1:
before_script:
@@ -24,7 +24,7 @@ test:7.1:
- php composer.phar install --no-dev
image: php:7.1
script:
- - phpunit -c build
+ - phpunit -c build --coverage-text
test:hhvm:
before_script:
@@ -34,4 +34,4 @@ test:hhvm:
- composer install --no-dev
image: 51systems/docker-gitlab-ci-runner-hhvm
script:
- - hhvm -d hhvm.php7.all=true vendor/bin/phpunit -c build
\ No newline at end of file
+ - hhvm -d hhvm.php7.all=true /usr/local/bin/phpunit -c build --coverage-text
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce2c5c1b..799612aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,8 @@
# Changelog
## Version 4
-* Updated to use Kitsu API after discontinuation of Hummingbird
+* Updated to use Kitsu API after discontinuation of Hummingbird
+* Added streaming links to list entries from the Kitsu API
## Version 3
* Converted user configuration to toml files
diff --git a/app/bootstrap.php b/app/bootstrap.php
index e88450ca..ee510190 100644
--- a/app/bootstrap.php
+++ b/app/bootstrap.php
@@ -22,7 +22,7 @@ use Aura\Session\SessionFactory;
use Aviat\AnimeClient\API\Kitsu\{
Auth as KitsuAuth,
ListItem as KitsuListItem,
- KitsuModel
+ Model as KitsuModel
};
use Aviat\AnimeClient\API\MAL\{
ListItem as MALListItem,
diff --git a/app/views/anime/cover.php b/app/views/anime/cover.php
index 41bd3f4b..bd5d4bc2 100644
--- a/app/views/anime/cover.php
+++ b/app/views/anime/cover.php
@@ -54,7 +54,7 @@
-
+
= $link['meta']['logo'] ?>
diff --git a/build/docker_install.sh b/build/docker_install.sh
index e7b4a8d1..e8785741 100644
--- a/build/docker_install.sh
+++ b/build/docker_install.sh
@@ -12,27 +12,18 @@ set -xe
apt-get update -yqq
apt-get install \
git \
- unzip \
- libfreetype6 \
- libjpeg62-turbo \
- libmcrypt4 \
- libpng12-0 \
- libfreetype6-dev \
- libjpeg-dev \
- libmcrypt-dev \
- libpng12-dev \
libxslt1-dev \
libxslt1.1 \
zlib1g-dev \
+ unzip \
-yqq
# Install phpunit, the tool that we will use for testing
curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar
chmod +x /usr/local/bin/phpunit
-# Install gd
-docker-php-ext-configure gd --enable-gd-native-ttf --with-jpeg-dir=/usr/lib/x86_64-linux-gnu --with-png-dir=/usr/lib/x86_64-linux-gnu --with-freetype-dir=/usr/lib/x86_64-linux-gnu
-docker-php-ext-install gd
-docker-php-ext-install mcrypt
+# Install extensions
+pecl install xdebug
+echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini
docker-php-ext-install xsl
docker-php-ext-install zip
\ No newline at end of file
diff --git a/console b/console
index fb116f0a..638f9bcc 100755
--- a/console
+++ b/console
@@ -34,8 +34,8 @@ unset($CONF_DIR);
// Start console script
// ---------------------------------------------------------------------------------------------------------------------
$console = new \ConsoleKit\Console([
- 'cache-images' => '\Aviat\AnimeClient\Command\CacheImages',
'clear-cache' => '\Aviat\AnimeClient\Command\ClearCache',
+ 'sync-lists' => '\Aviat\AnimeClient\Command\SyncKitsuWithMal'
]);
$console->run();
\ No newline at end of file
diff --git a/public/css/base.css b/public/css/base.css
index c3bcb7b6..2192edcb 100644
--- a/public/css/base.css
+++ b/public/css/base.css
@@ -1307,4 +1307,13 @@ a:hover, a:active {
padding:0 0,5em 0.5em;
padding:0 0.5rem 0.5rem;
}
+}
+
+/* ----------------------------------------------------------------------------
+ Images / Logos
+-----------------------------------------------------------------------------*/
+
+.streaming-logo {
+ width: 50px;
+ height: 50px;
}
\ No newline at end of file
diff --git a/public/css/base.myth.css b/public/css/base.myth.css
index 3f481fb7..eabbf71b 100644
--- a/public/css/base.myth.css
+++ b/public/css/base.myth.css
@@ -560,4 +560,12 @@ a:hover, a:active {
padding:0 0,5em 0.5em;
padding:0 0.5rem 0.5rem;
}
+}
+
+/* ----------------------------------------------------------------------------
+ Images / Logos
+-----------------------------------------------------------------------------*/
+.streaming-logo {
+ width: 50px;
+ height: 50px;
}
\ No newline at end of file
diff --git a/src/API/Kitsu.php b/src/API/Kitsu.php
index 6a17f941..98378e5e 100644
--- a/src/API/Kitsu.php
+++ b/src/API/Kitsu.php
@@ -28,6 +28,8 @@ use DateTimeImmutable;
*/
class Kitsu {
const AUTH_URL = 'https://kitsu.io/api/oauth/token';
+ const AUTH_USER_ID_KEY = 'kitsu-auth-userid';
+ const AUTH_TOKEN_CACHE_KEY = 'kitsu-auth-token';
/**
* Map of Kitsu status to label for select menus
@@ -104,21 +106,21 @@ class Kitsu {
return [
'name' => 'Crunchyroll',
'link' => true,
- 'logo' => '
'
+ 'logo' => '
'
];
case 'www.funimation.com':
return [
'name' => 'Funimation',
'link' => true,
- 'logo' => '
'
+ 'logo' => '
'
];
case 'www.hulu.com':
return [
'name' => 'Hulu',
'link' => true,
- 'logo' => '
'
+ 'logo' => '
'
];
// Default to Netflix, because the API links are broken,
@@ -127,7 +129,7 @@ class Kitsu {
return [
'name' => 'Netflix',
'link' => false,
- 'logo' => '
'
+ 'logo' => '
'
];
}
}
@@ -161,6 +163,39 @@ class Kitsu {
return $links;
}
+
+ /**
+ * Reorganize streaming links for the current list item
+ *
+ * @param array $included
+ * @return array
+ */
+ public static function parseListItemStreamingLinks(array $included, string $animeId): array
+ {
+ // Anime lists have a different structure to search through
+ if (array_key_exists('anime', $included) && ! array_key_exists('streamingLinks', $included))
+ {
+ $links = [];
+ $anime = $included['anime'][$animeId];
+
+ if (count($anime['relationships']['streamingLinks']) > 0)
+ {
+ foreach ($anime['relationships']['streamingLinks'] as $streamingLink)
+ {
+ $host = parse_url($streamingLink['url'], \PHP_URL_HOST);
+
+ $links[] = [
+ 'meta' => static::getServiceMetaData($host),
+ 'link' => $streamingLink['url'],
+ 'subs' => $streamingLink['subs'],
+ 'dubs' => $streamingLink['dubs']
+ ];
+ }
+ }
+
+ return $links;
+ }
+ }
/**
* Filter out duplicate and very similar names from
diff --git a/src/API/Kitsu/Auth.php b/src/API/Kitsu/Auth.php
index 04e2e395..70691eb1 100644
--- a/src/API/Kitsu/Auth.php
+++ b/src/API/Kitsu/Auth.php
@@ -17,6 +17,10 @@
namespace Aviat\AnimeClient\API\Kitsu;
use Aviat\AnimeClient\AnimeClient;
+use Aviat\AnimeClient\API\{
+ CacheTrait,
+ Kitsu as K
+};
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Exception;
@@ -24,7 +28,7 @@ use Exception;
* Kitsu API Authentication
*/
class Auth {
-
+ use CacheTrait;
use ContainerAware;
/**
@@ -49,6 +53,7 @@ class Auth {
public function __construct(ContainerInterface $container)
{
$this->setContainer($container);
+ $this->setCache($container->get('cache'));
$this->segment = $container->get('session')
->getSegment(AnimeClient::SESSION_SEGMENT);
$this->model = $container->get('kitsu-model');
@@ -68,7 +73,7 @@ class Auth {
try
{
- $auth_token = $this->model->authenticate($username, $password);
+ $auth = $this->model->authenticate($username, $password);
}
catch (Exception $e)
{
@@ -76,9 +81,14 @@ class Auth {
}
- if (FALSE !== $auth_token)
+ if (FALSE !== $auth)
{
- $this->segment->set('auth_token', $auth_token);
+ // Set the token in the cache for command line operations
+ $cacheItem = $this->cache->getItem(K::AUTH_TOKEN_CACHE_KEY);
+ $cacheItem->set($auth['access_token']);
+ $cacheItem->save();
+
+ $this->segment->set('auth_token', $auth['access_token']);
return TRUE;
}
diff --git a/src/API/Kitsu/KitsuModel.php b/src/API/Kitsu/Model.php
similarity index 75%
rename from src/API/Kitsu/KitsuModel.php
rename to src/API/Kitsu/Model.php
index 97bd7998..fb2e90c3 100644
--- a/src/API/Kitsu/KitsuModel.php
+++ b/src/API/Kitsu/Model.php
@@ -20,7 +20,10 @@ 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, MangaListTransformer
+ AnimeTransformer,
+ AnimeListTransformer,
+ MangaTransformer,
+ MangaListTransformer
};
use Aviat\Ion\Di\ContainerAware;
use Aviat\Ion\Json;
@@ -29,7 +32,7 @@ use GuzzleHttp\Exception\ClientException;
/**
* Kitsu API Model
*/
-class KitsuModel {
+class Model {
use CacheTrait;
use ContainerAware;
use KitsuTrait;
@@ -65,7 +68,7 @@ class KitsuModel {
/**
- * KitsuModel constructor.
+ * Constructor.
*/
public function __construct(ListItem $listItem)
{
@@ -85,17 +88,30 @@ class KitsuModel {
* @param string $username
* @return string
*/
- public function getUserIdByUsername(string $username)
+ public function getUserIdByUsername(string $username = NULL)
{
- $data = $this->getRequest('users', [
- 'query' => [
- 'filter' => [
- 'name' => $username
+ if (is_null($username))
+ {
+ $username = $this->getUsername();
+ }
+
+ $cacheItem = $this->cache->getItem(K::AUTH_USER_ID_KEY);
+
+ if ( ! $cacheItem->isHit())
+ {
+ $data = $this->getRequest('users', [
+ 'query' => [
+ 'filter' => [
+ 'name' => $username
+ ]
]
- ]
- ]);
+ ]);
- return $data['data'][0]['id'];
+ $cacheItem->set($data['data'][0]['id']);
+ $cacheItem->save();
+ }
+
+ return $cacheItem->get();
}
/**
@@ -120,7 +136,7 @@ class KitsuModel {
if (array_key_exists('access_token', $data))
{
- return $data['access_token'];
+ return $data;
}
return false;
@@ -139,6 +155,12 @@ class KitsuModel {
return $this->animeTransformer->transform($baseData);
}
+ /**
+ * Get information about a particular anime
+ *
+ * @param string $animeId
+ * @return array
+ */
public function getAnimeById(string $animeId): array
{
$baseData = $this->getRawMediaDataById('anime', $animeId);
@@ -156,14 +178,16 @@ class KitsuModel {
$baseData = $this->getRawMediaData('manga', $mangaId);
return $this->mangaTransformer->transform($baseData);
}
-
+
/**
- * Get the anime list for the configured user
+ * Get the raw (unorganized) anime list for the configured user
*
* @param string $status - The watching status to filter the list with
+ * @param int $limit - The number of list entries to fetch for a page
+ * @param int $offset - The page offset
* @return array
*/
- public function getAnimeList(string $status): array
+ public function getRawAnimeList(string $status, int $limit = 600, int $offset = 0): array
{
$options = [
'query' => [
@@ -174,17 +198,31 @@ class KitsuModel {
],
'include' => 'media,media.genres,media.mappings,anime.streamingLinks',
'page' => [
- 'offset' => 0,
- 'limit' => 500
- ]
+ 'offset' => $offset,
+ 'limit' => $limit
+ ],
+ 'sort' => '-updated_at'
]
];
- $cacheItem = $this->cache->getItem($this->getHashForMethodCall($this, __METHOD__, $options));
+ return $this->getRequest('library-entries', $options);
+ }
+
+ /**
+ * Get the anime list for the configured user
+ *
+ * @param string $status - The watching status to filter the list with
+ * @param int $limit - The number of list entries to fetch for a page
+ * @param int $offset - The page offset
+ * @return array
+ */
+ 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->getRequest('library-entries', $options);
+ $data = $this->getRawAnimeList($status, $limit, $offset);
$included = JsonAPI::organizeIncludes($data['included']);
$included = JsonAPI::inlineIncludedRelationships($included, 'anime');
@@ -201,7 +239,15 @@ class KitsuModel {
return $cacheItem->get();
}
- public function getMangaList($status): array
+ /**
+ * Get the manga list for the configured user
+ *
+ * @param string $status - The reading status by which to filter the list
+ * @param int $limit - The number of list items to fetch per page
+ * @param int $offset - The page offset
+ * @return array
+ */
+ public function getMangaList(string $status, int $limit = 200, int $offset = 0): array
{
$options = [
'query' => [
@@ -212,8 +258,8 @@ class KitsuModel {
],
'include' => 'media',
'page' => [
- 'offset' => 0,
- 'limit' => 200
+ 'offset' => $offset,
+ 'limit' => $limit
],
'sort' => '-updated_at'
]
@@ -239,6 +285,13 @@ class KitsuModel {
return $cacheItem->get();
}
+ /**
+ * Search for an anime or manga
+ *
+ * @param string $type - 'anime' or 'manga'
+ * @param string $query - name of the item to search for
+ * @return array
+ */
public function search(string $type, string $query): array
{
$options = [
@@ -264,12 +317,24 @@ class KitsuModel {
return $raw;
}
+ /**
+ * Create a list item
+ *
+ * @param array $data
+ * @return bool
+ */
public function createListItem(array $data): bool
{
$data['user_id'] = $this->getUserIdByUsername($this->getUsername());
return $this->listItem->create($data);
}
+ /**
+ * Get the data for a specific list item, generally for editing
+ *
+ * @param string $listId - The unique identifier of that list item
+ * @return array
+ */
public function getListItem(string $listId): array
{
$baseData = $this->listItem->get($listId);
@@ -294,6 +359,12 @@ class KitsuModel {
}
}
+ /**
+ * Modify a list item
+ *
+ * @param array $data
+ * @return array
+ */
public function updateListItem(array $data)
{
try
@@ -313,6 +384,12 @@ class KitsuModel {
}
}
+ /**
+ * Remove a list item
+ *
+ * @param string $id - The id of the list item to remove
+ * @return bool
+ */
public function deleteListItem(string $id): bool
{
return $this->listItem->delete($id);
diff --git a/src/API/Kitsu/Transformer/AnimeListTransformer.php b/src/API/Kitsu/Transformer/AnimeListTransformer.php
index e153a2a1..959cc675 100644
--- a/src/API/Kitsu/Transformer/AnimeListTransformer.php
+++ b/src/API/Kitsu/Transformer/AnimeListTransformer.php
@@ -60,6 +60,10 @@ class AnimeListTransformer extends AbstractTransformer {
}
}
}
+
+ $streamingLinks = (array_key_exists('streamingLinks', $anime['relationships']))
+ ? Kitsu::parseListItemStreamingLinks($included, $animeId)
+ : [];
return [
'id' => $item['id'],
@@ -78,12 +82,13 @@ class AnimeListTransformer extends AbstractTransformer {
],
'anime' => [
'age_rating' => $anime['ageRating'],
+ 'title' => $anime['canonicalTitle'],
'titles' => Kitsu::filterTitles($anime),
'slug' => $anime['slug'],
'type' => $this->string($anime['showType'])->upperCaseFirst()->__toString(),
'image' => $anime['posterImage']['small'],
'genres' => $genres,
- 'streaming_links' => Kitsu::parseStreamingLinks($included),
+ 'streaming_links' => $streamingLinks,
],
'watching_status' => $item['attributes']['status'],
'notes' => $item['attributes']['notes'],
diff --git a/src/API/XML.php b/src/API/XML.php
index e8148737..35ef99ee 100644
--- a/src/API/XML.php
+++ b/src/API/XML.php
@@ -179,15 +179,43 @@ class XML {
for ($i = 0; $i < $length; $i++)
{
$el = $nodeList->item($i);
+ $current =& $root[$el->nodeName];
+
+ // It's a top level element!
if (is_a($el->childNodes->item(0), 'DomText') || ( ! $el->hasChildNodes()))
{
- $root[$el->nodeName] = $el->textContent;
+ $current = $el->textContent;
+ continue;
}
- else
+
+ // An empty value at the current root
+ if (is_null($current))
{
- $root[$el->nodeName] = [];
- static::childNodesToArray($root[$el->nodeName], $el->childNodes);
+ $current = [];
+ static::childNodesToArray($current, $el->childNodes);
+ continue;
}
+
+ $keys = array_keys($current);
+
+ // Wrap the array in a containing array
+ // if there are only string keys
+ if ( ! is_numeric($keys[0]))
+ {
+ // But if there is only one key, don't wrap it in
+ // an array, just recurse to parse the child nodes
+ if (count($current) === 1)
+ {
+ static::childNodesToArray($current, $el->childNodes);
+ continue;
+ }
+ $current = [$current];
+ }
+
+ array_push($current, []);
+ $index = count($current) - 1;
+
+ static::childNodesToArray($current[$index], $el->childNodes);
}
}
@@ -203,7 +231,17 @@ class XML {
{
foreach($data as $key => $props)
{
+ // 'Flatten' the array as you create the xml
+ if (is_numeric($key))
+ {
+ foreach($props as $key => $props)
+ {
+ break;
+ }
+ }
+
$node = $dom->createElement($key);
+
if (is_array($props))
{
static::arrayPropertiesToXmlNodes($dom, $node, $props);
diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php
index fecb2131..e929578f 100644
--- a/src/Command/BaseCommand.php
+++ b/src/Command/BaseCommand.php
@@ -22,20 +22,30 @@ use Aviat\AnimeClient\{
Model,
Util
};
-use Aviat\AnimeClient\Auth\HummingbirdAuth;
+use Aviat\AnimeClient\API\CacheTrait;
+use Aviat\AnimeClient\API\Kitsu\{
+ Auth as KitsuAuth,
+ ListItem as KitsuListItem,
+ Model as KitsuModel
+};
+use Aviat\AnimeClient\API\MAL\{
+ ListItem as MALListItem,
+ Model as MALModel
+};
use Aviat\Banker\Pool;
use Aviat\Ion\Config;
-use Aviat\Ion\Di\Container;
+use Aviat\Ion\Di\{Container, ContainerAware};
use ConsoleKit\Command;
use ConsoleKit\Widgets\Box;
-use Monolog\Handler\RotatingFileHandler;
+use Monolog\Handler\NullHandler;
use Monolog\Logger;
/**
* Base class for console command setup
*/
class BaseCommand extends Command {
- use \Aviat\Ion\Di\ContainerAware;
+ use CacheTrait;
+ use ContainerAware;
/**
* Echo text in a box
@@ -68,9 +78,16 @@ class BaseCommand extends Command {
$di = function ($config_array) use ($APP_DIR) {
$container = new Container();
+ // -------------------------------------------------------------------------
+ // Logging
+ // -------------------------------------------------------------------------
+
$app_logger = new Logger('animeclient');
- $app_logger->pushHandler(new RotatingFileHandler("{$APP_DIR}/logs/app.log", Logger::NOTICE));
+ $app_logger->pushHandler(new NullHandler);
+ $request_logger = new Logger('request');
+ $request_logger->pushHandler(new NullHandler);
$container->setLogger($app_logger, 'default');
+ $container->setLogger($request_logger, 'request');
// Create Config Object
$container->set('config', function() use ($config_array) {
@@ -90,18 +107,21 @@ class BaseCommand extends Command {
});
// Models
- $container->set('api-model', function($container) {
- return new Model\API($container);
+ $container->set('kitsu-model', function($container) {
+ $listItem = new KitsuListItem();
+ $listItem->setContainer($container);
+ $model = new KitsuModel($listItem);
+ $model->setContainer($container);
+ $cache = $container->get('cache');
+ $model->setCache($cache);
+ return $model;
});
- $container->set('anime-model', function($container) {
- return new Model\Anime($container);
- });
- $container->set('manga-model', function($container) {
- return new Model\Manga($container);
- });
-
- $container->set('auth', function($container) {
- return new HummingbirdAuth($container);
+ $container->set('mal-model', function($container) {
+ $listItem = new MALListItem();
+ $listItem->setContainer($container);
+ $model = new MALModel($listItem);
+ $model->setContainer($container);
+ return $model;
});
$container->set('util', function($container) {
return new Util($container);
diff --git a/src/Command/SyncKitsuWithMal.php b/src/Command/SyncKitsuWithMal.php
new file mode 100644
index 00000000..93a714c2
--- /dev/null
+++ b/src/Command/SyncKitsuWithMal.php
@@ -0,0 +1,86 @@
+
+ * @copyright 2015 - 2017 Timothy J. Warren
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version 4.0
+ * @link https://github.com/timw4mail/HummingBirdAnimeClient
+ */
+
+namespace Aviat\AnimeClient\Command;
+
+use Amp\Artax;
+use Aviat\AnimeClient\API\Kitsu;
+
+/**
+ * Clears the API Cache
+ */
+class SyncKitsuWithMal extends BaseCommand {
+
+ protected $kitsuModel;
+
+ public function getKitsuAnimeListPageCount()
+ {
+ $cacheItem = $this->cache->getItem(Kitsu::AUTH_TOKEN_CACHE_KEY);
+
+ $query = http_build_query([
+ 'filter' => [
+ 'user_id' => $this->kitsuModel->getUserIdByUsername(),
+ 'media_type' => 'Anime'
+ ],
+ 'include' => 'anime,anime.genres,anime.mappings,anime.streamingLinks',
+ 'page' => [
+ 'limit' => 1
+ ],
+ 'sort' => '-updated_at'
+ ]);
+ $request = (new Artax\Request)
+ ->setUri("https://kitsu.io/api/edge/library-entries?{$query}")
+ ->setProtocol('1.1')
+ ->setAllHeaders([
+ 'Accept' => 'application/vnd.api+json',
+ 'Content-Type' => 'application/vnd.api+json',
+ 'User-Agent' => "Tim's Anime Client/4.0"
+ ]);
+
+ if ($cacheItem->isHit())
+ {
+ $token = $cacheItem->get();
+ $request->setHeader('Authorization', "bearer {$token}");
+ }
+ else
+ {
+ $this->echoBox("WARNING: NOT LOGGED IN\nSome data might be missing");
+ }
+
+ $response = \Amp\wait((new Artax\Client)->request($request));
+
+ $body = json_decode($response->getBody(), TRUE);
+ return $body['meta']['count'];
+ }
+
+ /**
+ * Run the image conversion script
+ *
+ * @param array $args
+ * @param array $options
+ * @return void
+ * @throws \ConsoleKit\ConsoleException
+ */
+ public function execute(array $args, array $options = [])
+ {
+ $this->setContainer($this->setupContainer());
+ $this->setCache($this->container->get('cache'));
+ $this->kitsuModel = $this->container->get('kitsu-model');
+
+ $kitsuCount = $this->getKitsuAnimeListPageCount();
+ $this->echoBox("List item count: {$kitsuCount}");
+ }
+}
diff --git a/src/Model/API.php b/src/Model/API.php
index 40797eb4..d2c423af 100644
--- a/src/Model/API.php
+++ b/src/Model/API.php
@@ -34,7 +34,7 @@ class API extends Model {
/**
* Cache manager
- * @var \Aviat\Ion\Cache\CacheInterface
+ * @var \Psr\Cache\CacheItemPoolInterface
*/
protected $cache;
@@ -56,7 +56,7 @@ class API extends Model {
}
/**
- * Sort the manga entries by their title
+ * Sort the list entries by their title
*
* @codeCoverageIgnore
* @param array $array
@@ -75,4 +75,3 @@ class API extends Model {
array_multisort($sort, SORT_ASC, $array);
}
}
-// End of BaseApiModel.php
diff --git a/tests/API/XMLTest.php b/tests/API/XMLTest.php
index b14d3f5b..12a1e724 100644
--- a/tests/API/XMLTest.php
+++ b/tests/API/XMLTest.php
@@ -9,6 +9,7 @@ class XMLTest extends TestCase {
public function setUp()
{
+ $this->malExport = file_get_contents(__DIR__ . '/../test_data/XML/MALExport.xml');
$this->xml = file_get_contents(__DIR__ . '/../test_data/XML/xmlTestFile.xml');
$this->expectedXml = file_get_contents(__DIR__ . '/../test_data/XML/minifiedXmlTestFile.xml');
@@ -43,6 +44,13 @@ class XMLTest extends TestCase {
{
$this->assertEquals($this->array, XML::toArray($this->xml));
}
+
+ public function testMALExport()
+ {
+ $array = XML::toArray($this->malExport);
+ $this->assertEquals($array['myanimelist']['myinfo']['user_total_anime'], count($array['myanimelist']['anime']));
+ // $this->assertEquals($array, XML::toArray($this->malExport));
+ }
public function testParse()
{
diff --git a/tests/RequirementsTest.php b/tests/RequirementsTest.php
index 7c8c3bce..9b5ef3e8 100644
--- a/tests/RequirementsTest.php
+++ b/tests/RequirementsTest.php
@@ -7,16 +7,6 @@ class RequirementsTest extends AnimeClient_TestCase {
$this->assertTrue(version_compare(PHP_VERSION, "5.4", "ge"));
}
- public function testHasGd()
- {
- $this->assertTrue(extension_loaded('gd'));
- }
-
- public function testHasMcrypt()
- {
- $this->assertTrue(extension_loaded('mcrypt'));
- }
-
public function testHasPDO()
{
$this->assertTrue(class_exists('PDO'));
diff --git a/tests/test_data/Kitsu/animeAfterTransform.json b/tests/test_data/Kitsu/animeAfterTransform.json
index af3e16ca..19230fe7 100644
--- a/tests/test_data/Kitsu/animeAfterTransform.json
+++ b/tests/test_data/Kitsu/animeAfterTransform.json
@@ -15,7 +15,7 @@
"meta": {
"name": "Crunchyroll",
"link": true,
- "logo": "