Version 5.1 - All the GraphQL #32
@ -10,6 +10,7 @@ use Aura\Web\WebFactory;
|
|||||||
use Aura\Router\RouterFactory;
|
use Aura\Router\RouterFactory;
|
||||||
use Aura\Session\SessionFactory;
|
use Aura\Session\SessionFactory;
|
||||||
use Aviat\Ion\Di\Container;
|
use Aviat\Ion\Di\Container;
|
||||||
|
use Aviat\AnimeClient\Auth\HummingbirdAuth;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Setup DI container
|
// Setup DI container
|
||||||
@ -54,6 +55,7 @@ return function(array $config_array = []) {
|
|||||||
$container->set('session', $session);
|
$container->set('session', $session);
|
||||||
|
|
||||||
$container->set('url-generator', new UrlGenerator($container));
|
$container->set('url-generator', new UrlGenerator($container));
|
||||||
|
$container->set('auth', new HummingbirdAuth($container));
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Dispatcher
|
// Dispatcher
|
||||||
|
@ -10,6 +10,8 @@ namespace Aviat\AnimeClient;
|
|||||||
*/
|
*/
|
||||||
class Config {
|
class Config {
|
||||||
|
|
||||||
|
use \Aviat\Ion\ArrayWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config object
|
* Config object
|
||||||
*
|
*
|
||||||
@ -30,11 +32,16 @@ class Config {
|
|||||||
/**
|
/**
|
||||||
* Get a config value
|
* Get a config value
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param array|string $key
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get($key)
|
public function get($key)
|
||||||
{
|
{
|
||||||
|
if (is_array($key))
|
||||||
|
{
|
||||||
|
return $this->get_deep_key($key, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists($key, $this->map))
|
if (array_key_exists($key, $this->map))
|
||||||
{
|
{
|
||||||
return $this->map[$key];
|
return $this->map[$key];
|
||||||
@ -43,16 +50,84 @@ class Config {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a reference to an arbitrary key on the config map
|
||||||
|
* @param array $key
|
||||||
|
* @param bool $create Whether to create the missing array keys
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function &get_deep_key(array $key, $create = TRUE)
|
||||||
|
{
|
||||||
|
$pos =& $this->map;
|
||||||
|
|
||||||
|
// Create the start of the array if it doesn't exist
|
||||||
|
if ($create && ! is_array($pos))
|
||||||
|
{
|
||||||
|
$pos = [];
|
||||||
|
}
|
||||||
|
elseif ( ! is_array($pos))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through the levels of the array,
|
||||||
|
// create the levels if they don't exist
|
||||||
|
foreach($key as $level)
|
||||||
|
{
|
||||||
|
if ($create && empty($pos) && ! is_array($pos))
|
||||||
|
{
|
||||||
|
$pos = [];
|
||||||
|
$pos[$level] = [];
|
||||||
|
}
|
||||||
|
$pos =& $pos[$level];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a config value
|
||||||
|
*
|
||||||
|
* @param string|array $key
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function delete($key)
|
||||||
|
{
|
||||||
|
$pos =& $this->map;
|
||||||
|
|
||||||
|
if (is_array($key))
|
||||||
|
{
|
||||||
|
$pos =& $this->arr($this->map)->get_deep_key($key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$pos =& $this->map[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($pos);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a config value
|
* Set a config value
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param string|array $key
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return Config
|
* @return Config
|
||||||
*/
|
*/
|
||||||
public function set($key, $value)
|
public function set($key, $value)
|
||||||
{
|
{
|
||||||
$this->map[$key] = $value;
|
$pos =& $this->map;
|
||||||
|
|
||||||
|
if (is_array($key))
|
||||||
|
{
|
||||||
|
$pos =& $this->get_deep_key($key);
|
||||||
|
$pos = $value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$pos[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,11 +43,6 @@ class Anime extends BaseController {
|
|||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
|
|
||||||
if ($this->config->get('show_anime_collection') === FALSE)
|
|
||||||
{
|
|
||||||
unset($this->nav_routes['Collection']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->model = new AnimeModel($container);
|
$this->model = new AnimeModel($container);
|
||||||
$this->collection_model = new AnimeCollectionModel($container);
|
$this->collection_model = new AnimeCollectionModel($container);
|
||||||
$this->base_data = array_merge($this->base_data, [
|
$this->base_data = array_merge($this->base_data, [
|
||||||
@ -109,7 +104,8 @@ class Anime extends BaseController {
|
|||||||
'completed' => AnimeWatchingStatus::COMPLETED
|
'completed' => AnimeWatchingStatus::COMPLETED
|
||||||
];
|
];
|
||||||
|
|
||||||
$title = $this->config->get('whose_list') . "'s Anime List · {$type_title_map[$type]}";
|
$title = $this->config->get('whose_list') .
|
||||||
|
"'s Anime List · {$type_title_map[$type]}";
|
||||||
|
|
||||||
$view_map = [
|
$view_map = [
|
||||||
'' => 'cover',
|
'' => 'cover',
|
||||||
|
@ -19,13 +19,6 @@ class MenuGenerator extends UrlGenerator {
|
|||||||
*/
|
*/
|
||||||
protected $helper;
|
protected $helper;
|
||||||
|
|
||||||
/**
|
|
||||||
* Menu config array
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $menus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request object
|
* Request object
|
||||||
*
|
*
|
||||||
@ -41,7 +34,6 @@ class MenuGenerator extends UrlGenerator {
|
|||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container)
|
||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
$this->menus = $this->config->get('menus');
|
|
||||||
$this->helper = $container->get('html-helper');
|
$this->helper = $container->get('html-helper');
|
||||||
$this->request = $container->get('request');
|
$this->request = $container->get('request');
|
||||||
}
|
}
|
||||||
@ -51,11 +43,11 @@ class MenuGenerator extends UrlGenerator {
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function parse_config()
|
protected function parse_config(array $menus)
|
||||||
{
|
{
|
||||||
$parsed = [];
|
$parsed = [];
|
||||||
|
|
||||||
foreach ($this->menus as $name => $menu)
|
foreach ($menus as $name => $menu)
|
||||||
{
|
{
|
||||||
$parsed[$name] = [];
|
$parsed[$name] = [];
|
||||||
foreach ($menu['items'] as $path_name => $partial_path)
|
foreach ($menu['items'] as $path_name => $partial_path)
|
||||||
@ -76,7 +68,8 @@ class MenuGenerator extends UrlGenerator {
|
|||||||
*/
|
*/
|
||||||
public function generate($menu)
|
public function generate($menu)
|
||||||
{
|
{
|
||||||
$parsed_config = $this->parse_config();
|
$menus = $this->config->get('menus');
|
||||||
|
$parsed_config = $this->parse_config($menus);
|
||||||
|
|
||||||
// Bail out early on invalid menu
|
// Bail out early on invalid menu
|
||||||
if ( ! $this->arr($parsed_config)->has_key($menu))
|
if ( ! $this->arr($parsed_config)->has_key($menu))
|
||||||
|
@ -7,12 +7,21 @@ namespace Aviat\AnimeClient\Model;
|
|||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Cookie\CookieJar;
|
use GuzzleHttp\Cookie\CookieJar;
|
||||||
use GuzzleHttp\Psr7\Request;
|
use GuzzleHttp\Psr7\Request;
|
||||||
|
use GuzzleHttp\Psr7\ResponseInterface;
|
||||||
|
|
||||||
use Aviat\Ion\Di\ContainerInterface;
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
use Aviat\AnimeClient\Model as BaseModel;
|
use Aviat\AnimeClient\Model as BaseModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base model for api interaction
|
* Base model for api interaction
|
||||||
|
*
|
||||||
|
* @method ResponseInterface get(string $uri, array $options);
|
||||||
|
* @method ResponseInterface delete(string $uri, array $options);
|
||||||
|
* @method ResponseInterface head(string $uri, array $options);
|
||||||
|
* @method ResponseInterface options(string $uri, array $options);
|
||||||
|
* @method ResponseInterface patch(string $uri, array $options);
|
||||||
|
* @method ResponseInterface post(string $uri, array $options);
|
||||||
|
* @method ResponseInterface put(string $uri, array $options);
|
||||||
*/
|
*/
|
||||||
class API extends BaseModel {
|
class API extends BaseModel {
|
||||||
|
|
||||||
@ -58,6 +67,35 @@ class API extends BaseModel {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic methods to call guzzle api client
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $args
|
||||||
|
* @return ResponseInterface|null
|
||||||
|
*/
|
||||||
|
public function __call($method, $args)
|
||||||
|
{
|
||||||
|
$valid_methods = [
|
||||||
|
'get',
|
||||||
|
'delete',
|
||||||
|
'head',
|
||||||
|
'options',
|
||||||
|
'patch',
|
||||||
|
'post',
|
||||||
|
'put'
|
||||||
|
];
|
||||||
|
|
||||||
|
if ( ! in_array($method, $valid_methods))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_unshift($args, strtoupper($method));
|
||||||
|
$response = call_user_func_array([$this->client, 'request'], $args);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt login via the api
|
* Attempt login via the api
|
||||||
*
|
*
|
||||||
@ -68,7 +106,7 @@ class API extends BaseModel {
|
|||||||
*/
|
*/
|
||||||
public function authenticate($username, $password)
|
public function authenticate($username, $password)
|
||||||
{
|
{
|
||||||
$result = $this->client->post('https://hummingbird.me/api/v1/users/authenticate', [
|
$result = $this->post('https://hummingbird.me/api/v1/users/authenticate', [
|
||||||
'body' => [
|
'body' => [
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'password' => $password
|
'password' => $password
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\Model;
|
namespace Aviat\AnimeClient\Model;
|
||||||
|
|
||||||
use Aviat\AnimeClient\Model\API;
|
|
||||||
use Aviat\AnimeClient\Hummingbird\Enum\AnimeWatchingStatus;
|
use Aviat\AnimeClient\Hummingbird\Enum\AnimeWatchingStatus;
|
||||||
use Aviat\AnimeClient\Hummingbird\Transformer\AnimeListTransformer;
|
use Aviat\AnimeClient\Hummingbird\Transformer\AnimeListTransformer;
|
||||||
|
|
||||||
@ -50,11 +49,11 @@ class Anime extends API {
|
|||||||
// @TODO use Hummingbird Auth class
|
// @TODO use Hummingbird Auth class
|
||||||
$data['auth_token'] = '';
|
$data['auth_token'] = '';
|
||||||
|
|
||||||
$result = $this->client->post("libraries/{$data['id']}", [
|
$response = $this->client->post("libraries/{$data['id']}", [
|
||||||
'body' => $data
|
'body' => $data
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result->json();
|
return json_decode($result->getBody(), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,7 +139,7 @@ class Anime extends API {
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->client->get('search/anime', $config);
|
$response = $this->get('search/anime', $config);
|
||||||
$errorHandler->addDataTable('anime_search_response', (array)$response);
|
$errorHandler->addDataTable('anime_search_response', (array)$response);
|
||||||
|
|
||||||
if ($response->getStatusCode() != 200)
|
if ($response->getStatusCode() != 200)
|
||||||
@ -148,7 +147,7 @@ class Anime extends API {
|
|||||||
throw new RuntimeException($response->getEffectiveUrl());
|
throw new RuntimeException($response->getEffectiveUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response->json();
|
return json_decode($response->getBody(), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,7 +169,7 @@ class Anime extends API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$username = $this->config->get('hummingbird_username');
|
$username = $this->config->get('hummingbird_username');
|
||||||
$response = $this->client->get("users/{$username}/library", $config);
|
$response = $this->get("users/{$username}/library", $config);
|
||||||
$output = $this->_check_cache($status, $response);
|
$output = $this->_check_cache($status, $response);
|
||||||
|
|
||||||
foreach ($output as &$row)
|
foreach ($output as &$row)
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
namespace Aviat\AnimeClient\Model;
|
namespace Aviat\AnimeClient\Model;
|
||||||
|
|
||||||
use Aviat\Ion\Di\ContainerInterface;
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
use Aviat\AnimeClient\Model\DB;
|
|
||||||
use Aviat\AnimeClient\Model\Anime as AnimeModel;
|
use Aviat\AnimeClient\Model\Anime as AnimeModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,8 +42,15 @@ class AnimeCollection extends DB {
|
|||||||
$db_file_name = $this->db_config['collection']['file'];
|
$db_file_name = $this->db_config['collection']['file'];
|
||||||
if ($db_file_name !== ':memory:')
|
if ($db_file_name !== ':memory:')
|
||||||
{
|
{
|
||||||
$db_file = file_get_contents($db_file_name);
|
if ( ! file_exists($db_file_name))
|
||||||
$this->valid_database = (strpos($db_file, 'SQLite format 3') === 0);
|
{
|
||||||
|
$this->valid_data = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$db_file = file_get_contents($db_file_name);
|
||||||
|
$this->valid_database = (strpos($db_file, 'SQLite format 3') === 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -49,12 +49,12 @@ class Manga extends API {
|
|||||||
unset($data['id']);
|
unset($data['id']);
|
||||||
|
|
||||||
// @TODO update with auth key from auth class
|
// @TODO update with auth key from auth class
|
||||||
$result = $this->client->put("manga_library_entries/{$id}", [
|
$result = $this->put("manga_library_entries/{$id}", [
|
||||||
'cookies' => ['token' => ''],
|
'cookies' => ['token' => ''],
|
||||||
'json' => ['manga_library_entry' => $data]
|
'json' => ['manga_library_entry' => $data]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result->json();
|
return json_decode($result->getBody(), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +104,7 @@ class Manga extends API {
|
|||||||
'allow_redirects' => FALSE
|
'allow_redirects' => FALSE
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->client->get('manga_library_entries', $config);
|
$response = $this->get('manga_library_entries', $config);
|
||||||
$data = $this->_check_cache($response);
|
$data = $this->_check_cache($response);
|
||||||
$output = $this->map_by_status($data);
|
$output = $this->map_by_status($data);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class ArrayType {
|
|||||||
*
|
*
|
||||||
* @param array $arr
|
* @param array $arr
|
||||||
*/
|
*/
|
||||||
public function __construct(array $arr)
|
public function __construct(array &$arr)
|
||||||
{
|
{
|
||||||
$this->arr =& $arr;
|
$this->arr =& $arr;
|
||||||
}
|
}
|
||||||
@ -154,5 +154,41 @@ class ArrayType {
|
|||||||
{
|
{
|
||||||
return in_array($value, $this->arr, $strict);
|
return in_array($value, $this->arr, $strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
return $this->arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a reference to the value of an arbitrary key on the array
|
||||||
|
*
|
||||||
|
* @param array $key
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function &get_deep_key(array $key)
|
||||||
|
{
|
||||||
|
$pos =& $this->arr;
|
||||||
|
|
||||||
|
// Create the start of the array if it doesn't exist
|
||||||
|
if ( ! is_array($pos))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through the levels of the array,
|
||||||
|
// create the levels if they don't exist
|
||||||
|
foreach($key as $level)
|
||||||
|
{
|
||||||
|
$pos =& $pos[$level];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// End of ArrayType.php
|
// End of ArrayType.php
|
@ -26,6 +26,7 @@ class HttpView extends BaseView {
|
|||||||
/**
|
/**
|
||||||
* Send the appropriate response
|
* Send the appropriate response
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function output()
|
protected function output()
|
||||||
|
@ -20,6 +20,83 @@ class ConfigTest extends AnimeClient_TestCase {
|
|||||||
$this->assertNull($this->config->get('baz'));
|
$this->assertNull($this->config->get('baz'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testConfigSet()
|
||||||
|
{
|
||||||
|
$this->config->set('foo', 'foobar');
|
||||||
|
$this->assertEquals('foobar', $this->config->get('foo'));
|
||||||
|
|
||||||
|
$this->config->set(['apple', 'sauce', 'is'], 'great');
|
||||||
|
$this->assertEquals('great', $this->config->get(['apple', 'sauce', 'is']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataConfigDelete()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'top level delete' => [
|
||||||
|
'key' => 'apple',
|
||||||
|
'assertKeys' => [
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce', 'is'],
|
||||||
|
'expected' => NULL
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce'],
|
||||||
|
'expected' => NULL
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'path' => 'apple',
|
||||||
|
'expected' => NULL
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'mid level delete' => [
|
||||||
|
'key' => ['apple', 'sauce'],
|
||||||
|
'assertKeys' => [
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce', 'is'],
|
||||||
|
'expected' => NULL
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce'],
|
||||||
|
'expected' => NULL
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'path' => 'apple',
|
||||||
|
'expected' => []
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'deep delete' => [
|
||||||
|
'key' => ['apple', 'sauce', 'is'],
|
||||||
|
'assertKeys' => [
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce', 'is'],
|
||||||
|
'expected' => NULL
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'path' => ['apple', 'sauce'],
|
||||||
|
'expected' => NULL
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataConfigDelete
|
||||||
|
*/
|
||||||
|
public function testConfigDelete($key, $assertKeys)
|
||||||
|
{
|
||||||
|
$this->markTestIncomplete();
|
||||||
|
$this->config->set(['apple', 'sauce', 'is'], 'great');
|
||||||
|
$this->config->delete($key);
|
||||||
|
|
||||||
|
foreach($assertKeys as $pair)
|
||||||
|
{
|
||||||
|
$this->assertEquals($pair['expected'], $this->config->get($pair['path']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetNonExistentConfigItem()
|
public function testGetNonExistentConfigItem()
|
||||||
{
|
{
|
||||||
$this->assertNull($this->config->get('foobar'));
|
$this->assertNull($this->config->get('foobar'));
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
use \Aviat\AnimeClient\Controller;
|
use \Aviat\AnimeClient\Controller;
|
||||||
|
use Aviat\AnimeClient\Controller\Anime as AnimeController;
|
||||||
|
use Aviat\AnimeClient\Controller\Manga as MangaController;
|
||||||
|
use Aviat\AnimeClient\Controller\Collection as CollectionController;
|
||||||
use \Aura\Web\WebFactory;
|
use \Aura\Web\WebFactory;
|
||||||
use \Aura\Router\RouterFactory;
|
use \Aura\Router\RouterFactory;
|
||||||
|
|
||||||
@ -20,9 +23,34 @@ class ControllerTest extends AnimeClient_TestCase {
|
|||||||
$this->container->set('request', $web_factory->newRequest());
|
$this->container->set('request', $web_factory->newRequest());
|
||||||
$this->container->set('response', $web_factory->newResponse());
|
$this->container->set('response', $web_factory->newResponse());
|
||||||
|
|
||||||
|
|
||||||
$this->BaseController = new Controller($this->container);
|
$this->BaseController = new Controller($this->container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testControllersSanity()
|
||||||
|
{
|
||||||
|
$config = $this->container->get('config');
|
||||||
|
$config->set(['database', 'collection'], [
|
||||||
|
'type' => 'sqlite',
|
||||||
|
'database' => '',
|
||||||
|
'file' => ":memory:"
|
||||||
|
]);
|
||||||
|
$this->container->set('config', $config);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
'Aviat\AnimeClient\Controller',
|
||||||
|
new AnimeController($this->container)
|
||||||
|
);
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
'Aviat\AnimeClient\Controller',
|
||||||
|
new MangaController($this->container)
|
||||||
|
);
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
'Aviat\AnimeClient\Controller',
|
||||||
|
new CollectionController($this->container)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testBaseControllerSanity()
|
public function testBaseControllerSanity()
|
||||||
{
|
{
|
||||||
$this->assertTrue(is_object($this->BaseController));
|
$this->assertTrue(is_object($this->BaseController));
|
||||||
|
@ -16,23 +16,7 @@ class MenuGeneratorTest extends AnimeClient_TestCase {
|
|||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$config = $this->container->get('config');
|
|
||||||
$config->set('menus', [
|
|
||||||
'anime_list' => [
|
|
||||||
'route_prefix' => '/anime',
|
|
||||||
'items' => [
|
|
||||||
'watching' => '/watching',
|
|
||||||
'plan_to_watch' => '/plan_to_watch',
|
|
||||||
'on_hold' => '/on_hold',
|
|
||||||
'dropped' => '/dropped',
|
|
||||||
'completed' => '/completed',
|
|
||||||
'all' => '/all'
|
|
||||||
]
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->generator = new MenuGenerator($this->container);
|
$this->generator = new MenuGenerator($this->container);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSanity()
|
public function testSanity()
|
||||||
@ -44,6 +28,19 @@ class MenuGeneratorTest extends AnimeClient_TestCase {
|
|||||||
public function testParseConfig()
|
public function testParseConfig()
|
||||||
{
|
{
|
||||||
$friend = new Friend($this->generator);
|
$friend = new Friend($this->generator);
|
||||||
|
$menus = [
|
||||||
|
'anime_list' => [
|
||||||
|
'route_prefix' => '/anime',
|
||||||
|
'items' => [
|
||||||
|
'watching' => '/watching',
|
||||||
|
'plan_to_watch' => '/plan_to_watch',
|
||||||
|
'on_hold' => '/on_hold',
|
||||||
|
'dropped' => '/dropped',
|
||||||
|
'completed' => '/completed',
|
||||||
|
'all' => '/all'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
$expected = [
|
$expected = [
|
||||||
'anime_list' => [
|
'anime_list' => [
|
||||||
'Watching' => '/anime/watching',
|
'Watching' => '/anime/watching',
|
||||||
@ -54,6 +51,6 @@ class MenuGeneratorTest extends AnimeClient_TestCase {
|
|||||||
'All' => '/anime/all'
|
'All' => '/anime/all'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
$this->assertEquals($expected, $friend->parse_config());
|
$this->assertEquals($expected, $friend->parse_config($menus));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,8 @@ use Aviat\AnimeClient\Model\API as BaseApiModel;
|
|||||||
|
|
||||||
class MockBaseApiModel extends BaseApiModel {
|
class MockBaseApiModel extends BaseApiModel {
|
||||||
|
|
||||||
|
protected $base_url = 'https://httpbin.org/';
|
||||||
|
|
||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container)
|
||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
@ -19,9 +21,15 @@ class MockBaseApiModel extends BaseApiModel {
|
|||||||
|
|
||||||
class BaseApiModelTest extends AnimeClient_TestCase {
|
class BaseApiModelTest extends AnimeClient_TestCase {
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->model = new MockBaseApiModel($this->container);
|
||||||
|
}
|
||||||
|
|
||||||
public function testBaseApiModelSanity()
|
public function testBaseApiModelSanity()
|
||||||
{
|
{
|
||||||
$baseApiModel = new MockBaseApiModel($this->container);
|
$baseApiModel = $this->model;
|
||||||
|
|
||||||
// Some basic type checks for class memebers
|
// Some basic type checks for class memebers
|
||||||
$this->assertInstanceOf('\Aviat\AnimeClient\Model', $baseApiModel);
|
$this->assertInstanceOf('\Aviat\AnimeClient\Model', $baseApiModel);
|
||||||
@ -34,4 +42,186 @@ class BaseApiModelTest extends AnimeClient_TestCase {
|
|||||||
$this->assertTrue(empty($baseApiModel->base_url));
|
$this->assertTrue(empty($baseApiModel->base_url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dataClient()
|
||||||
|
{
|
||||||
|
$host = gethostname();
|
||||||
|
$ip = gethostbyname($host);
|
||||||
|
$user_agent = "Tim's Anime Client/2.0";
|
||||||
|
$headers = [
|
||||||
|
'User-Agent' => $user_agent
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'invalid' => [
|
||||||
|
'method' => 'foo',
|
||||||
|
'uri' => '',
|
||||||
|
'options' => [],
|
||||||
|
'expected' => NULL,
|
||||||
|
'is_json' => FALSE,
|
||||||
|
],
|
||||||
|
'get' => [
|
||||||
|
'method' => 'get',
|
||||||
|
'uri' => '/get',
|
||||||
|
'options' => [
|
||||||
|
'query' => [
|
||||||
|
'foo' => 'bar'
|
||||||
|
],
|
||||||
|
'headers' => $headers
|
||||||
|
],
|
||||||
|
'expected' => [
|
||||||
|
'args' => [
|
||||||
|
'foo' => 'bar'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'Host' => 'httpbin.org',
|
||||||
|
'User-Agent' => $user_agent
|
||||||
|
],
|
||||||
|
'origin' => $ip,
|
||||||
|
'url' => 'https://httpbin.org/get?foo=bar'
|
||||||
|
],
|
||||||
|
'is_json' => TRUE
|
||||||
|
],
|
||||||
|
'post' => [
|
||||||
|
'method' => 'post',
|
||||||
|
'uri' => '/post',
|
||||||
|
'options' => [
|
||||||
|
'form_params' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => $headers
|
||||||
|
],
|
||||||
|
'expected' => [
|
||||||
|
'args' => [],
|
||||||
|
'data' => '',
|
||||||
|
'files' => [],
|
||||||
|
'form' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'Host' => 'httpbin.org',
|
||||||
|
'User-Agent' => $user_agent,
|
||||||
|
'Content-Length' => '18',
|
||||||
|
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||||
|
],
|
||||||
|
'json' => NULL,
|
||||||
|
'origin' => $ip,
|
||||||
|
'url' => 'https://httpbin.org/post'
|
||||||
|
],
|
||||||
|
'is_json' => TRUE
|
||||||
|
],
|
||||||
|
'put' => [
|
||||||
|
'method' => 'put',
|
||||||
|
'uri' => '/put',
|
||||||
|
'options' => [
|
||||||
|
'form_params' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => $headers
|
||||||
|
],
|
||||||
|
'expected' => [
|
||||||
|
'args' => [],
|
||||||
|
'data' => '',
|
||||||
|
'files' => [],
|
||||||
|
'form' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'Host' => 'httpbin.org',
|
||||||
|
'User-Agent' => $user_agent,
|
||||||
|
'Content-Length' => '18',
|
||||||
|
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||||
|
],
|
||||||
|
'json' => NULL,
|
||||||
|
'origin' => $ip,
|
||||||
|
'url' => 'https://httpbin.org/put'
|
||||||
|
],
|
||||||
|
'is_json' => TRUE
|
||||||
|
],
|
||||||
|
'patch' => [
|
||||||
|
'method' => 'patch',
|
||||||
|
'uri' => '/patch',
|
||||||
|
'options' => [
|
||||||
|
'form_params' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => $headers
|
||||||
|
],
|
||||||
|
'expected' => [
|
||||||
|
'args' => [],
|
||||||
|
'data' => '',
|
||||||
|
'files' => [],
|
||||||
|
'form' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'Host' => 'httpbin.org',
|
||||||
|
'User-Agent' => $user_agent,
|
||||||
|
'Content-Length' => '18',
|
||||||
|
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||||
|
],
|
||||||
|
'json' => NULL,
|
||||||
|
'origin' => $ip,
|
||||||
|
'url' => 'https://httpbin.org/patch'
|
||||||
|
],
|
||||||
|
'is_json' => TRUE
|
||||||
|
],
|
||||||
|
'delete' => [
|
||||||
|
'method' => 'delete',
|
||||||
|
'uri' => '/delete',
|
||||||
|
'options' => [
|
||||||
|
'form_params' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => $headers
|
||||||
|
],
|
||||||
|
'expected' => [
|
||||||
|
'args' => [],
|
||||||
|
'data' => '',
|
||||||
|
'files' => [],
|
||||||
|
'form' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => 'foobar'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'Host' => 'httpbin.org',
|
||||||
|
'User-Agent' => $user_agent,
|
||||||
|
'Content-Length' => '18',
|
||||||
|
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||||
|
],
|
||||||
|
'json' => NULL,
|
||||||
|
'origin' => $ip,
|
||||||
|
'url' => 'https://httpbin.org/delete'
|
||||||
|
],
|
||||||
|
'is_json' => TRUE
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataClient
|
||||||
|
*/
|
||||||
|
public function testClient($method, $uri, $options, $expected, $is_json)
|
||||||
|
{
|
||||||
|
$result = $this->model->$method($uri, $options);
|
||||||
|
|
||||||
|
if (is_null($result))
|
||||||
|
{
|
||||||
|
$this->assertNull($expected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$actual = ($is_json)
|
||||||
|
? json_decode($result->getBody(), TRUE)
|
||||||
|
: (string) $result->getBody();
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
52
tests/Ion/View/HtmlViewTest.php
Normal file
52
tests/Ion/View/HtmlViewTest.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__ . "/../ViewTest.php";
|
||||||
|
|
||||||
|
use Aviat\Ion\Friend;
|
||||||
|
use Aviat\Ion\View;
|
||||||
|
use Aviat\Ion\View\HtmlView;
|
||||||
|
|
||||||
|
class TestHtmlView extends HtmlView {
|
||||||
|
protected function output() {
|
||||||
|
$reflect = new ReflectionClass($this);
|
||||||
|
$properties = $reflect->getProperties();
|
||||||
|
$props = [];
|
||||||
|
|
||||||
|
foreach($properties as $reflectProp)
|
||||||
|
{
|
||||||
|
$reflectProp->setAccessible(TRUE);
|
||||||
|
$props[$reflectProp->getName()] = $reflectProp->getValue($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view = new TestView($this->container);
|
||||||
|
$friend = new Friend($view);
|
||||||
|
foreach($props as $name => $val)
|
||||||
|
{
|
||||||
|
$friend->__set($name, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$friend->output();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HtmlViewTest extends ViewTest {
|
||||||
|
|
||||||
|
protected $template_path = __DIR__ . "/../../test_views/";
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->view = new TestHtmlView($this->container);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRenderTemplate()
|
||||||
|
{
|
||||||
|
$path = $this->template_path . 'test_view.php';
|
||||||
|
$expected = '<tag>foo</tag>';
|
||||||
|
$actual = $this->view->render_template($path, [
|
||||||
|
'var' => 'foo'
|
||||||
|
]);
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
tests/Ion/View/HttpViewTest.php
Normal file
46
tests/Ion/View/HttpViewTest.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__ . "/../ViewTest.php";
|
||||||
|
|
||||||
|
use Aviat\Ion\Friend;
|
||||||
|
use Aviat\Ion\View\HttpView;
|
||||||
|
|
||||||
|
class TestHttpView extends HttpView {
|
||||||
|
protected function output() {
|
||||||
|
$reflect = new ReflectionClass($this);
|
||||||
|
$properties = $reflect->getProperties();
|
||||||
|
$props = [];
|
||||||
|
|
||||||
|
foreach($properties as $reflectProp)
|
||||||
|
{
|
||||||
|
$reflectProp->setAccessible(TRUE);
|
||||||
|
$props[$reflectProp->getName()] = $reflectProp->getValue($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view = new TestView($this->container);
|
||||||
|
$friend = new Friend($view);
|
||||||
|
foreach($props as $name => $val)
|
||||||
|
{
|
||||||
|
$friend->__set($name, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$friend->output();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HttpViewTest extends ViewTest {
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->view = new TestHttpView($this->container);
|
||||||
|
$this->friend = new Friend($this->view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRedirect()
|
||||||
|
{
|
||||||
|
$this->friend->redirect('/foo', 303);
|
||||||
|
$this->assertEquals('/foo', $this->friend->response->headers->get('Location'));
|
||||||
|
$this->assertEquals(303, $this->friend->response->status->getCode());
|
||||||
|
}
|
||||||
|
}
|
44
tests/Ion/View/JsonViewTest.php
Normal file
44
tests/Ion/View/JsonViewTest.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Aviat\Ion\Friend;
|
||||||
|
use Aviat\Ion\View\JsonView;
|
||||||
|
|
||||||
|
include_once __DIR__ . "/../ViewTest.php";
|
||||||
|
|
||||||
|
class TestJsonView extends JsonView {
|
||||||
|
public function __destruct() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsonViewTest extends ViewTest {
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->view = new TestJsonView($this->container);
|
||||||
|
$this->friend = new Friend($this->view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetOutput()
|
||||||
|
{
|
||||||
|
// Extend view class to remove destructor which does output
|
||||||
|
$view = new TestJsonView($this->container);
|
||||||
|
|
||||||
|
// Json encode non-string
|
||||||
|
$content = ['foo' => 'bar'];
|
||||||
|
$expected = json_encode($content);
|
||||||
|
$this->view->setOutput($content);
|
||||||
|
$this->assertEquals($expected, $this->view->getOutput());
|
||||||
|
|
||||||
|
// Directly set string
|
||||||
|
$content = '{}';
|
||||||
|
$expected = '{}';
|
||||||
|
$this->view->setOutput($content);
|
||||||
|
$this->assertEquals($expected, $this->view->getOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOutput()
|
||||||
|
{
|
||||||
|
$this->assertEquals('application/json', $this->friend->contentType);
|
||||||
|
}
|
||||||
|
}
|
@ -3,8 +3,6 @@
|
|||||||
use Aura\Web\WebFactory;
|
use Aura\Web\WebFactory;
|
||||||
use Aviat\Ion\Friend;
|
use Aviat\Ion\Friend;
|
||||||
use Aviat\Ion\View;
|
use Aviat\Ion\View;
|
||||||
use Aviat\Ion\Di\Container;
|
|
||||||
|
|
||||||
|
|
||||||
class TestView extends View {
|
class TestView extends View {
|
||||||
|
|
||||||
@ -16,16 +14,6 @@ class ViewTest extends AnimeClient_TestCase {
|
|||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$web_factory = new WebFactory([
|
|
||||||
'_GET' => $_GET,
|
|
||||||
'_POST' => $_POST,
|
|
||||||
'_COOKIE' => $_COOKIE,
|
|
||||||
'_SERVER' => $_SERVER,
|
|
||||||
'_FILES' => $_FILES
|
|
||||||
]);
|
|
||||||
$this->container->set('request', $web_factory->newRequest());
|
|
||||||
$this->container->set('response', $web_factory->newResponse());
|
|
||||||
|
|
||||||
$this->view = new TestView($this->container);
|
$this->view = new TestView($this->container);
|
||||||
$this->friend = new Friend($this->view);
|
$this->friend = new Friend($this->view);
|
||||||
}
|
}
|
||||||
@ -54,8 +42,9 @@ class ViewTest extends AnimeClient_TestCase {
|
|||||||
{
|
{
|
||||||
$this->friend->contentType = 'text/html';
|
$this->friend->contentType = 'text/html';
|
||||||
$this->friend->__destruct();
|
$this->friend->__destruct();
|
||||||
$this->assertEquals($this->friend->response->content->getType(), $this->friend->contentType);
|
$content =& $this->friend->response->content;
|
||||||
$this->assertEquals($this->friend->response->content->getCharset(), 'utf-8');
|
$this->assertEquals($content->getType(), $this->friend->contentType);
|
||||||
$this->assertEquals($this->friend->response->content->get(), $this->friend->getOutput());
|
$this->assertEquals($content->getCharset(), 'utf-8');
|
||||||
|
$this->assertEquals($content->get(), $this->friend->getOutput());
|
||||||
}
|
}
|
||||||
}
|
}
|
1
tests/test_views/test_view.php
Normal file
1
tests/test_views/test_view.php
Normal file
@ -0,0 +1 @@
|
|||||||
|
<tag><?= $var ?></tag>
|
Loading…
Reference in New Issue
Block a user