Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
17 changed files with 498 additions and 332 deletions
Showing only changes of commit 789af166ae - Show all commits

View File

@ -198,7 +198,7 @@ final class Model
* this way is more accurate than getting the list item id * this way is more accurate than getting the list item id
* directly from the MAL id * directly from the MAL id
*/ */
private function getListIdFromMediaId(string $mediaId) private function getListIdFromMediaId(string $mediaId): string
{ {
$config = $this->container->get('config'); $config = $this->container->get('config');
$anilistUser = $config->get(['anilist', 'username']); $anilistUser = $config->get(['anilist', 'username']);

File diff suppressed because it is too large Load Diff

View File

@ -70,17 +70,9 @@ final class Auth {
public function authenticate(string $password): bool public function authenticate(string $password): bool
{ {
$config = $this->container->get('config'); $config = $this->container->get('config');
$username = $config->get(['kitsu_username']); $username = $config->get('kitsu_username');
// try
{
$auth = $this->model->authenticate($username, $password); $auth = $this->model->authenticate($username, $password);
}
/* catch (Exception $e)
{
return FALSE;
}*/
if (FALSE !== $auth) if (FALSE !== $auth)
{ {
@ -104,6 +96,7 @@ final class Auth {
$this->segment->set('auth_token', $auth['access_token']); $this->segment->set('auth_token', $auth['access_token']);
$this->segment->set('auth_token_expires', $expire_time); $this->segment->set('auth_token_expires', $expire_time);
$this->segment->set('refresh_token', $auth['refresh_token']); $this->segment->set('refresh_token', $auth['refresh_token']);
return TRUE; return TRUE;
} }
@ -118,15 +111,8 @@ final class Auth {
* @return boolean * @return boolean
*/ */
public function reAuthenticate(string $token): bool public function reAuthenticate(string $token): bool
{
try
{ {
$auth = $this->model->reAuthenticate($token); $auth = $this->model->reAuthenticate($token);
}
catch (Exception $e)
{
return FALSE;
}
if (FALSE !== $auth) if (FALSE !== $auth)
{ {
@ -186,7 +172,7 @@ final class Auth {
{ {
$token = $this->segment->get('auth_token', FALSE); $token = $this->segment->get('auth_token', FALSE);
$refreshToken = $this->segment->get('refresh_token', FALSE); $refreshToken = $this->segment->get('refresh_token', FALSE);
$isExpired = time() > $this->segment->get('auth_token_expires', 0); $isExpired = time() >= $this->segment->get('auth_token_expires', 0);
// Attempt to re-authenticate with refresh token // Attempt to re-authenticate with refresh token
if ($isExpired && $refreshToken) if ($isExpired && $refreshToken)

View File

@ -121,11 +121,6 @@ final class Model {
]); ]);
$data = Json::decode(wait($response->getBody())); $data = Json::decode(wait($response->getBody()));
if (array_key_exists('access_token', $data))
{
return $data;
}
if (array_key_exists('error', $data)) if (array_key_exists('error', $data))
{ {
dump($data['error']); dump($data['error']);
@ -133,6 +128,11 @@ final class Model {
die(); die();
} }
if (array_key_exists('access_token', $data))
{
return $data;
}
return FALSE; return FALSE;
} }
@ -376,9 +376,7 @@ final class Model {
// Bail out on no data // Bail out on no data
if (empty($data)) if (empty($data))
{ {
$cacheItem->set([]); return [];
$cacheItem->save();
return $cacheItem->get();
} }
$included = JsonAPI::organizeIncludes($data['included']); $included = JsonAPI::organizeIncludes($data['included']);
@ -638,9 +636,7 @@ final class Model {
// Bail out on no data // Bail out on no data
if (empty($data) || ( ! array_key_exists('included', $data))) if (empty($data) || ( ! array_key_exists('included', $data)))
{ {
$cacheItem->set([]); return [];
$cacheItem->save();
return $cacheItem->get();
} }
$included = JsonAPI::organizeIncludes($data['included']); $included = JsonAPI::organizeIncludes($data['included']);

View File

@ -79,7 +79,7 @@ final class Index extends BaseController {
{ {
$redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' . $redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' .
http_build_query([ http_build_query([
'client_id' => 271, 'client_id' => $this->config->get(['anilist', 'client_id']),
'response_type' => 'code', 'response_type' => 'code',
]); ]);
@ -109,6 +109,7 @@ final class Index extends BaseController {
{ {
$auth = $this->container->get('auth'); $auth = $this->container->get('auth');
$post = $this->request->getParsedBody(); $post = $this->request->getParsedBody();
if ($auth->authenticate($post['password'])) if ($auth->authenticate($post['password']))
{ {
$this->sessionRedirect(); $this->sessionRedirect();

View File

@ -18,7 +18,7 @@ namespace Aviat\AnimeClient;
use function Aviat\Ion\_dir; use function Aviat\Ion\_dir;
use Aura\Router\Matcher; use Aura\Router\{Matcher, Rule};
use Aviat\AnimeClient\API\FailedResponseException; use Aviat\AnimeClient\API\FailedResponseException;
use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Di\ContainerInterface;
@ -314,7 +314,7 @@ final class Dispatcher extends RoutingBase {
$params = []; $params = [];
switch($failure->failedRule) { switch($failure->failedRule) {
case 'Aura\Router\Rule\Allows': case Rule\Allows::class:
$params = [ $params = [
'http_code' => 405, 'http_code' => 405,
'title' => '405 Method Not Allowed', 'title' => '405 Method Not Allowed',
@ -322,7 +322,7 @@ final class Dispatcher extends RoutingBase {
]; ];
break; break;
case 'Aura\Router\Rule\Accepts': case Rule\Accepts::class:
$params = [ $params = [
'http_code' => 406, 'http_code' => 406,
'title' => '406 Not Acceptable', 'title' => '406 Not Acceptable',

View File

@ -42,15 +42,15 @@ class Collection extends DB {
try try
{ {
$this->db = \Query($this->dbConfig['collection']); $this->db = \Query($this->dbConfig);
} }
catch (PDOException $e) {} catch (PDOException $e) {}
// Is database valid? If not, set a flag so the // Is database valid? If not, set a flag so the
// app can be run without a valid database // app can be run without a valid database
if ($this->dbConfig['collection']['type'] === 'sqlite') if ($this->dbConfig['type'] === 'sqlite')
{ {
$dbFileName = $this->dbConfig['collection']['file']; $dbFileName = $this->dbConfig['file'];
if ($dbFileName !== ':memory:' && file_exists($dbFileName)) if ($dbFileName !== ':memory:' && file_exists($dbFileName))
{ {

View File

@ -44,12 +44,6 @@ class RoutingBase {
*/ */
protected $routes; protected $routes;
/**
* Route configuration options
* @var array
*/
protected $routeConfig;
/** /**
* Constructor * Constructor
* *
@ -63,20 +57,19 @@ class RoutingBase {
$this->container = $container; $this->container = $container;
$this->config = $container->get('config'); $this->config = $container->get('config');
$this->routes = $this->config->get('routes'); $this->routes = $this->config->get('routes');
$this->routeConfig = $this->config->get('route_config');
} }
/** /**
* Retrieve the appropriate value for the routing key * Retrieve the appropriate value for the routing key
* *
* @param string $key * @param string|int|array $key
* @return mixed * @return mixed
*/ */
public function __get($key) public function __get($key)
{ {
if (array_key_exists($key, $this->routeConfig)) if ($this->config->has($key))
{ {
return $this->routeConfig[$key]; return $this->config->get($key);
} }
} }

View File

@ -17,11 +17,10 @@
namespace Aviat\AnimeClient\Types; namespace Aviat\AnimeClient\Types;
use ArrayAccess; use ArrayAccess;
use LogicException;
abstract class AbstractType implements ArrayAccess { abstract class AbstractType implements ArrayAccess {
/** /**
* Populate values for unserializing data * Populate values for un-serializing data
* *
* @param $properties * @param $properties
* @return mixed * @return mixed
@ -87,7 +86,7 @@ abstract class AbstractType implements ArrayAccess {
{ {
$existing = json_encode($this); $existing = json_encode($this);
throw new LogicException("Trying to set non-existent property: '$name'. Existing properties: $existing"); throw new UndefinedPropertyException("Trying to set undefined property: '$name'. Existing properties: $existing");
} }
$this->$name = $value; $this->$name = $value;
@ -106,7 +105,7 @@ abstract class AbstractType implements ArrayAccess {
return $this->$name; return $this->$name;
} }
throw new LogicException("Trying to get non-existent property: '$name'"); throw new UndefinedPropertyException("Trying to get undefined property: '$name'");
} }
/** /**

View File

@ -21,9 +21,13 @@ class Config extends AbstractType {
public $anilist; public $anilist;
public $cache; public $cache;
public $database; public $database;
public $route_config;
// Settings in config.toml // Settings in config.toml
public $asset_path; // Path to public folder for urls
public $default_anime_list_path;
public $default_list;
public $default_manga_list_path;
public $default_view_type;
public $kitsu_username; public $kitsu_username;
public $show_anime_collection; public $show_anime_collection;
public $show_manga_collection; public $show_manga_collection;
@ -34,7 +38,7 @@ class Config extends AbstractType {
public $routes; public $routes;
// Generated config values // Generated config values
public $asset_dir; public $asset_dir; // Path to public folder for local files
public $base_config_dir; public $base_config_dir;
public $config_dir; public $config_dir;
public $data_cache_path; public $data_cache_path;
@ -43,57 +47,16 @@ class Config extends AbstractType {
public function setAnilist ($data): void public function setAnilist ($data): void
{ {
$this->anilist = new class($data) extends AbstractType { $this->anilist = new Config\Anilist($data);
public $enabled;
public $client_id;
public $client_secret;
public $redirect_uri;
public $access_token;
public $refresh_token;
public $user_id;
public $username;
};
} }
public function setCache ($data): void public function setCache ($data): void
{ {
$this->cache = new class($data) extends AbstractType { $this->cache = new Config\Cache($data);
public $driver;
public $connection;
public $options;
};
} }
public function setDatabase ($data): void public function setDatabase ($data): void
{ {
$this->database = new class($data) extends AbstractType { $this->database = new Config\Database($data);
public $collection;
public function setCollection ($data): void
{
$this->collection = new class($data) extends AbstractType {
public $type;
public $host;
public $user;
public $pass;
public $port;
public $database;
public $file;
};
}
};
}
public function setRoute_config ($data): void
{
$this->route_config = new class($data) extends AbstractType {
public $asset_path;
public $default_list;
public $default_anime_list_path;
public $default_manga_list_path;
};
} }
} }

View File

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @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.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types\Config;
use Aviat\AnimeClient\Types\AbstractType;
class Anilist extends AbstractType {
public $enabled = FALSE;
public $client_id;
public $client_secret;
public $redirect_uri;
public $access_token;
public $refresh_token;
public $user_id;
public $username;
}

View File

@ -0,0 +1,32 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @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.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types\Config;
use Aviat\AnimeClient\Types\AbstractType;
class Cache extends AbstractType {
public $driver;
public $connection = [];
public $options = [];
/* public function setConnection($data): void
{
$this->connection = new class($data) extends AbstractType {
};
} */
}

View File

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @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.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types\Config;
use Aviat\AnimeClient\Types\AbstractType;
class Database extends AbstractType {
public $type;
public $host;
public $user;
public $pass;
public $port;
public $database;
public $file;
}

View File

@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.1
*
* @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.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
use LogicException;
class UndefinedPropertyException extends LogicException {}

View File

@ -70,7 +70,7 @@ class AnimeClientTestCase extends TestCase {
$APP_DIR = _dir($ROOT_DIR, 'app'); $APP_DIR = _dir($ROOT_DIR, 'app');
$config_array = [ $config_array = [
'asset_path' => '//localhost/assets/', 'asset_path' => '/assets',
'img_cache_path' => _dir(ROOT_DIR, 'public/images'), 'img_cache_path' => _dir(ROOT_DIR, 'public/images'),
'data_cache_path' => _dir(TEST_DATA_DIR, 'cache'), 'data_cache_path' => _dir(TEST_DATA_DIR, 'cache'),
'cache' => [ 'cache' => [
@ -99,16 +99,9 @@ class AnimeClientTestCase extends TestCase {
'file' => ':memory:', 'file' => ':memory:',
] ]
], ],
'route_config' => [
'asset_path' => '/assets'
],
'routes' => [ 'routes' => [
], ],
'mal' => [
'username' => 'foo',
'password' => 'bar'
]
]; ];
// Set up DI container // Set up DI container

View File

@ -51,7 +51,7 @@ class ControllerTest extends AnimeClientTestCase {
public function testControllersSanity() public function testControllersSanity()
{ {
$config = $this->container->get('config'); $config = $this->container->get('config');
$config->set(['database', 'collection'], [ $config->set('database', [
'type' => 'sqlite', 'type' => 'sqlite',
'database' => '', 'database' => '',
'file' => ":memory:" 'file' => ":memory:"

View File

@ -98,7 +98,7 @@ class DispatcherTest extends AnimeClientTestCase {
] ]
], ],
], ],
'route_config' => [ 'config' => [
'anime_path' => 'anime', 'anime_path' => 'anime',
'manga_path' => 'manga', 'manga_path' => 'manga',
'default_list' => 'anime' 'default_list' => 'anime'
@ -132,8 +132,8 @@ class DispatcherTest extends AnimeClientTestCase {
] ]
]; ];
$data['manga_default_routing_anime']['config']['route_config']['default_list'] = 'manga'; $data['manga_default_routing_anime']['config']['default_list'] = 'manga';
$data['manga_default_routing_manga']['config']['route_config']['default_list'] = 'manga'; $data['manga_default_routing_manga']['config']['default_list'] = 'manga';
return $data; return $data;
} }
@ -167,7 +167,7 @@ class DispatcherTest extends AnimeClientTestCase {
public function testDefaultRoute() public function testDefaultRoute()
{ {
$config = [ $config = [
'route_config' => [ 'config' => [
'anime_path' => 'anime', 'anime_path' => 'anime',
'manga_path' => 'manga', 'manga_path' => 'manga',
'default_anime_list_path' => "watching", 'default_anime_list_path' => "watching",
@ -192,11 +192,12 @@ class DispatcherTest extends AnimeClientTestCase {
] ]
]; ];
$this->expectException(\InvalidArgumentException::class);
$this->doSetUp($config, "/", "localhost"); $this->doSetUp($config, "/", "localhost");
$this->assertEquals('//localhost/manga/all', $this->urlGenerator->defaultUrl('manga'), "Incorrect default url"); $this->assertEquals('//localhost/manga/all', $this->urlGenerator->defaultUrl('manga'), "Incorrect default url");
$this->assertEquals('//localhost/anime/watching', $this->urlGenerator->defaultUrl('anime'), "Incorrect default url"); $this->assertEquals('//localhost/anime/watching', $this->urlGenerator->defaultUrl('anime'), "Incorrect default url");
$this->expectException(\InvalidArgumentException::class);
$this->urlGenerator->defaultUrl('foo'); $this->urlGenerator->defaultUrl('foo');
} }
@ -205,16 +206,12 @@ class DispatcherTest extends AnimeClientTestCase {
return [ return [
'controller_list_sanity_check' => [ 'controller_list_sanity_check' => [
'config' => [ 'config' => [
'routes' => [
],
'route_config' => [
'anime_path' => 'anime', 'anime_path' => 'anime',
'manga_path' => 'manga', 'manga_path' => 'manga',
'default_anime_list_path' => "watching", 'default_anime_list_path' => "watching",
'default_manga_list_path' => 'all', 'default_manga_list_path' => 'all',
'default_list' => 'manga' 'default_list' => 'manga',
], 'routes' => [],
], ],
'expected' => [ 'expected' => [
'anime' => 'Aviat\AnimeClient\Controller\Anime', 'anime' => 'Aviat\AnimeClient\Controller\Anime',
@ -230,14 +227,12 @@ class DispatcherTest extends AnimeClientTestCase {
'routes' => [ 'routes' => [
], ],
'route_config' => [
'anime_path' => 'anime', 'anime_path' => 'anime',
'manga_path' => 'manga', 'manga_path' => 'manga',
'default_anime_path' => "/anime/watching", 'default_anime_path' => "/anime/watching",
'default_manga_path' => '/manga/all', 'default_manga_path' => '/manga/all',
'default_list' => 'manga' 'default_list' => 'manga'
], ],
],
'expected' => [ 'expected' => [
'anime' => 'Aviat\AnimeClient\Controller\Anime', 'anime' => 'Aviat\AnimeClient\Controller\Anime',
'manga' => 'Aviat\AnimeClient\Controller\Manga', 'manga' => 'Aviat\AnimeClient\Controller\Manga',