Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
19 changed files with 128 additions and 297 deletions
Showing only changes of commit 951f4362db - Show all commits

View File

@ -50,7 +50,8 @@
"spatie/phpunit-snapshot-assertions": "^2.2.1",
"squizlabs/php_codesniffer": "^3.2.2",
"symfony/var-dumper": "^4.4.1",
"theseer/phpdox": "*"
"theseer/phpdox": "*",
"vimeo/psalm": "^3.7"
},
"scripts": {
"build": "vendor/bin/robo build",
@ -58,10 +59,11 @@
"build:js": "cd public && npm run build:js && cd ..",
"clean": "vendor/bin/robo clean",
"coverage": "phpdbg -qrr -- vendor/bin/phpunit -c build",
"phpstan": "phpstan analyse -l 4 -c phpstan.neon src tests ./console index.php",
"phpstan": "phpstan analyse -c phpstan.neon",
"watch:css": "cd public && npm run watch:css",
"watch:js": "cd public && npm run watch:js",
"test": "vendor/bin/phpunit"
"test": "vendor/bin/phpunit -c build --no-coverage",
"test-update": "vendor/bin/phpunit -c build --no-coverage -d --update-snapshots"
},
"scripts-descriptions": {
"build": "Generate the api docs",

View File

@ -1,9 +1,18 @@
parameters:
checkGenericClassInNonGenericObjectType: false
inferPrivatePropertyTypeFromConstructor: true
level: 7
autoload_files:
- %rootDir%/../../../tests/mocks.php
paths:
- src
- tests
- ./console
- index.php
ignoreErrors:
- '#Access to an undefined property Aviat\\\Ion\\\Friend::\$[a-zA-Z0-9_]+#'
- '#Call to an undefined method Aviat\\\Ion\\\Friend::[a-zA-Z0-9_]+\(\)#'
- '#Call to an undefined method Aura\\\Html\\\HelperLocator::[a-zA-Z0-9_]+\(\)#'
- '#Undefined variable: \$var#'
- '#Property Amp\\Artax\\Internal\\RequestCycle::\$[a-zA-Z0-9_]+#'
excludes_analyse:
- tests/mocks.php

55
psalm.xml Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<psalm
totallyTyped="false"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<LessSpecificReturnType errorLevel="info" />
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedFunction errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<InternalMethod errorLevel="info" />
<InternalProperty errorLevel="info" />
<InternalClass errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />
<MissingPropertyType errorLevel="info" />
<InvalidDocblock errorLevel="info" />
<MisplacedRequiredParam errorLevel="info" />
<PropertyNotSetInConstructor errorLevel="info" />
<MissingConstructor errorLevel="info" />
<MissingClosureParamType errorLevel="info" />
<MissingParamType errorLevel="info" />
<RedundantCondition errorLevel="info" />
<DocblockTypeContradiction errorLevel="info" />
<RedundantConditionGivenDocblockType errorLevel="info" />
<UnresolvableInclude errorLevel="info" />
<RawObjectIteration errorLevel="info" />
<InvalidStringClass errorLevel="info" />
</issueHandlers>
</psalm>

View File

@ -65,7 +65,7 @@ class APIRequestBuilder {
/**
* The current request
* @var \Amp\Artax\Request
* @var Request
*/
protected $request;
@ -219,14 +219,14 @@ class APIRequestBuilder {
/**
* Return the promise for the current request
*
* @return Request
* @throws \Throwable
* @return \Amp\Artax\Request
*/
public function getFullRequest(): Request
{
$this->buildUri();
if ($this->logger)
if ($this->logger !== NULL)
{
$this->logger->debug('API Request', [
'request_url' => $this->request->getUri(),

View File

@ -25,6 +25,8 @@ use Aviat\AnimeClient\API\Anilist;
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Json;
use Aviat\Ion\Di\Exception\ContainerException;
use Aviat\Ion\Di\Exception\NotFoundException;
/**
* Anilist API Model
@ -92,8 +94,8 @@ final class Model
*
* @param string $type
* @return array
* @throws \Aviat\Ion\Di\Exception\ContainerException
* @throws \Aviat\Ion\Di\Exception\NotFoundException
* @throws ContainerException
* @throws NotFoundException
*/
public function getSyncList(string $type = 'anime'): array
{
@ -144,7 +146,7 @@ final class Model
];
}
return $this->listItem->create($createData, $type);
return $this->listItem->create($createData);
}
/**

View File

@ -16,6 +16,8 @@
namespace Aviat\AnimeClient\API\Kitsu;
use Aura\Session\Segment;
use const Aviat\AnimeClient\SESSION_SEGMENT;
use Aviat\AnimeClient\API\{
@ -23,7 +25,6 @@ use Aviat\AnimeClient\API\{
Kitsu as K
};
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Exception;
/**
* Kitsu API Authentication
@ -42,7 +43,7 @@ final class Auth {
/**
* Session object
*
* @var \Aura\Session\Segment
* @var Segment
*/
private $segment;

View File

@ -137,6 +137,9 @@ final class ListItem implements ListItemInterface {
return $request->getFullRequest();
}
/**
* @return false|string
*/
private function getAuthHeader()
{
$cache = $this->getContainer()->get('cache');

View File

@ -142,23 +142,24 @@ final class CharacterTransformer extends AbstractTransformer {
foreach ($role['relationships']['person']['people'] as $pid => $peoples)
{
$p = $peoples;
$person = $p['attributes'];
$person['id'] = $pid;
$person['image'] = $person['image']['original'];
uasort($role['relationships']['media']['anime'], static function ($a, $b) {
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
});
$item = [
'person' => $person,
'series' => $role['relationships']['media']['anime']
];
$output[$roleName][$language][] = $item;
}
$person = $p['attributes'];
$person['id'] = $pid;
$person['image'] = $person['image']['original'];
uasort($role['relationships']['media']['anime'], function ($a, $b) {
return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle'];
});
$item = [
'person' => $person,
'series' => $role['relationships']['media']['anime']
];
$output[$roleName][$language][] = $item;
} else
}
else
{
foreach ($role['relationships']['person']['people'] as $pid => $person)
{

View File

@ -130,6 +130,9 @@ final class MangaTransformer extends AbstractTransformer {
]);
}
/**
* @return int|null|string
*/
private function count(int $value = NULL)
{
return ((int)$value === 0)

View File

@ -62,7 +62,12 @@ final class UpdateThumbnails extends ClearThumbnails {
$this->echoBox('Finished regenerating all thumbnails');
}
public function getImageList()
/**
* @return array-key[][]
*
* @psalm-return array{anime: list<array-key>, manga: list<array-key>}
*/
public function getImageList(): array
{
$mangaList = $this->kitsuModel->getFullRawMangaList();
$includes = JsonAPI::organizeIncludes($mangaList['included']);

View File

@ -16,6 +16,8 @@
namespace Aviat\AnimeClient\Controller;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
use function Amp\Promise\wait;
use function Aviat\AnimeClient\getResponse;
use function Aviat\AnimeClient\createPlaceholderImage;
@ -32,17 +34,14 @@ final class Images extends BaseController {
* @param string $type The category of image
* @param string $file The filename to look for
* @param bool $display Whether to output the image to the server
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @throws \TypeError
* @throws \Error
* @throws \Throwable
* @return void
* @throws NotFoundException
* @throws \Throwable
* @throws ContainerException
*/
public function cache(string $type, string $file, $display = TRUE): void
{
$currentUrl = $this->request->getUri()->__toString();
$currentUrl = (string)$this->request->getUri();
$kitsuUrl = 'https://media.kitsu.io/';
$fileName = str_replace('-original', '', $file);

View File

@ -37,7 +37,7 @@ abstract class AbstractType implements ArrayAccess, Countable {
*
* @param mixed $data
*/
public function __construct($data = [])
final public function __construct($data = [])
{
$typeKeys = array_keys((array)$this);
$dataKeys = array_keys((array)$data);
@ -187,7 +187,7 @@ abstract class AbstractType implements ArrayAccess, Countable {
{
$object = $parent ?? $this;
if (is_scalar($object) || empty($object))
if (is_scalar($object) || $object === NULL)
{
return $object;
}

View File

@ -16,7 +16,8 @@
namespace Aviat\AnimeClient;
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Utility method class
@ -45,8 +46,8 @@ class Util {
* Set up the Util class
*
* @param ContainerInterface $container
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws ContainerException
* @throws NotFoundException
*/
public function __construct(ContainerInterface $container)
{
@ -80,8 +81,8 @@ class Util {
/**
* Determine whether to show the sub-menu
*
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws ContainerException
* @throws NotFoundException
* @return bool
*/
public function isViewPage(): bool
@ -98,8 +99,8 @@ class Util {
* Determine whether the page is a page with a form, and
* not suitable for redirection
*
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws ContainerException
* @throws NotFoundException
* @return bool
*/
public function isFormPage(): bool

View File

@ -36,10 +36,10 @@
1 => '小林さんちのメイドラゴン',
),
)),
'watching_status' => 'current',
'notes' => NULL,
'private' => false,
'rewatching' => false,
'rewatched' => 0,
'user_rating' => '-',
'private' => false,
'watching_status' => 'current',
));

View File

@ -1,15 +0,0 @@
<?php return Aviat\AnimeClient\Types\FormItem::__set_state(array(
'id' => 14047981,
'anilist_item_id' => NULL,
'mal_id' => NULL,
'data' =>
Aviat\AnimeClient\Types\FormItemData::__set_state(array(
'notes' => 'Very formulaic.',
'private' => false,
'progress' => 38,
'ratingTwenty' => 16,
'reconsumeCount' => 0,
'reconsuming' => false,
'status' => 'current',
)),
));

View File

@ -1,15 +0,0 @@
<?php return Aviat\AnimeClient\Types\FormItem::__set_state(array(
'id' => 14047981,
'anilist_item_id' => NULL,
'mal_id' => '12345',
'data' =>
Aviat\AnimeClient\Types\FormItemData::__set_state(array(
'notes' => 'Very formulaic.',
'private' => true,
'progress' => 38,
'ratingTwenty' => 16,
'reconsumeCount' => 0,
'reconsuming' => true,
'status' => 'current',
)),
));

View File

@ -1,14 +0,0 @@
<?php return Aviat\AnimeClient\Types\FormItem::__set_state(array(
'id' => 14047983,
'anilist_item_id' => NULL,
'mal_id' => '12347',
'data' =>
Aviat\AnimeClient\Types\FormItemData::__set_state(array(
'notes' => '',
'private' => true,
'progress' => 12,
'reconsumeCount' => 0,
'reconsuming' => true,
'status' => 'current',
)),
));

View File

@ -1,201 +0,0 @@
<?php return array (
0 =>
Aviat\AnimeClient\Types\MangaListItem::__set_state(array(
'id' => '15084773',
'mal_id' => '26769',
'chapters' =>
array (
'read' => 67,
'total' => '-',
),
'volumes' =>
array (
'read' => '-',
'total' => '-',
),
'manga' =>
Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array(
'genres' =>
array (
0 => 'Comedy',
1 => 'Romance',
2 => 'School',
3 => 'Slice of Life',
4 => 'Thriller',
),
'id' => '20286',
'image' => 'https://media.kitsu.io/manga/poster_images/20286/small.jpg?1434293999',
'slug' => 'bokura-wa-minna-kawaisou',
'title' => 'Bokura wa Minna Kawaisou',
'titles' =>
array (
),
'type' => 'Manga',
'url' => 'https://kitsu.io/manga/bokura-wa-minna-kawaisou',
)),
'reading_status' => 'current',
'notes' => '',
'rereading' => false,
'reread' => 0,
'user_rating' => 9,
)),
1 =>
Aviat\AnimeClient\Types\MangaListItem::__set_state(array(
'id' => '15085607',
'mal_id' => '16',
'chapters' =>
array (
'read' => 17,
'total' => 120,
),
'volumes' =>
array (
'read' => '-',
'total' => 14,
),
'manga' =>
Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array(
'genres' =>
array (
0 => 'Comedy',
1 => 'Ecchi',
2 => 'Harem',
3 => 'Romance',
4 => 'Sports',
),
'id' => '47',
'image' => 'https://media.kitsu.io/manga/poster_images/47/small.jpg?1434249493',
'slug' => 'love-hina',
'title' => 'Love Hina',
'titles' =>
array (
),
'type' => 'Manga',
'url' => 'https://kitsu.io/manga/love-hina',
)),
'reading_status' => 'current',
'notes' => '',
'rereading' => false,
'reread' => 0,
'user_rating' => 7,
)),
2 =>
Aviat\AnimeClient\Types\MangaListItem::__set_state(array(
'id' => '15084529',
'mal_id' => '35003',
'chapters' =>
array (
'read' => 16,
'total' => '-',
),
'volumes' =>
array (
'read' => '-',
'total' => '-',
),
'manga' =>
Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array(
'genres' =>
array (
0 => 'Comedy',
1 => 'Ecchi',
2 => 'Gender Bender',
3 => 'Romance',
4 => 'School',
5 => 'Sports',
6 => 'Supernatural',
),
'id' => '11777',
'image' => 'https://media.kitsu.io/manga/poster_images/11777/small.jpg?1438784325',
'slug' => 'yamada-kun-to-7-nin-no-majo',
'title' => 'Yamada-kun to 7-nin no Majo',
'titles' =>
array (
0 => 'Yamada-kun and the Seven Witches',
),
'type' => 'Manga',
'url' => 'https://kitsu.io/manga/yamada-kun-to-7-nin-no-majo',
)),
'reading_status' => 'current',
'notes' => '',
'rereading' => false,
'reread' => 0,
'user_rating' => 9,
)),
3 =>
Aviat\AnimeClient\Types\MangaListItem::__set_state(array(
'id' => '15312827',
'mal_id' => '78523',
'chapters' =>
array (
'read' => 68,
'total' => '-',
),
'volumes' =>
array (
'read' => '-',
'total' => '-',
),
'manga' =>
Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array(
'genres' =>
array (
0 => 'Romance',
1 => 'School',
2 => 'Slice of Life',
),
'id' => '27175',
'image' => 'https://media.kitsu.io/manga/poster_images/27175/small.jpg?1464379411',
'slug' => 'relife',
'title' => 'ReLIFE',
'titles' =>
array (
),
'type' => 'Manga',
'url' => 'https://kitsu.io/manga/relife',
)),
'reading_status' => 'current',
'notes' => '',
'rereading' => false,
'reread' => 0,
'user_rating' => '-',
)),
4 =>
Aviat\AnimeClient\Types\MangaListItem::__set_state(array(
'id' => '15084769',
'mal_id' => '60815',
'chapters' =>
array (
'read' => 43,
'total' => '-',
),
'volumes' =>
array (
'read' => '-',
'total' => '-',
),
'manga' =>
Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array(
'genres' =>
array (
0 => 'Comedy',
1 => 'School',
2 => 'Slice of Life',
),
'id' => '25491',
'image' => 'https://media.kitsu.io/manga/poster_images/25491/small.jpg?1434305043',
'slug' => 'joshikausei',
'title' => 'Joshikausei',
'titles' =>
array (
),
'type' => 'Manga',
'url' => 'https://kitsu.io/manga/joshikausei',
)),
'reading_status' => 'current',
'notes' => '',
'rereading' => false,
'reread' => 0,
'user_rating' => 8,
)),
);

View File

@ -1,5 +0,0 @@
- null
- null
- null
- null
- null