Version 5.1 - All the GraphQL #32
@ -20,6 +20,7 @@ use Aura\Html\HelperLocatorFactory;
|
|||||||
use Aura\Router\RouterContainer;
|
use Aura\Router\RouterContainer;
|
||||||
use Aura\Session\SessionFactory;
|
use Aura\Session\SessionFactory;
|
||||||
use Aviat\AnimeClient\API\Kitsu\Auth as KitsuAuth;
|
use Aviat\AnimeClient\API\Kitsu\Auth as KitsuAuth;
|
||||||
|
use Aviat\AnimeClient\API\Kitsu\ListItem as KitsuListItem;
|
||||||
use Aviat\AnimeClient\API\Kitsu\KitsuModel;
|
use Aviat\AnimeClient\API\Kitsu\KitsuModel;
|
||||||
use Aviat\AnimeClient\Model;
|
use Aviat\AnimeClient\Model;
|
||||||
use Aviat\Banker\Pool;
|
use Aviat\Banker\Pool;
|
||||||
@ -41,7 +42,10 @@ return function(array $config_array = []) {
|
|||||||
|
|
||||||
$app_logger = new Logger('animeclient');
|
$app_logger = new Logger('animeclient');
|
||||||
$app_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/app.log', Logger::NOTICE));
|
$app_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/app.log', Logger::NOTICE));
|
||||||
|
$request_logger = new Logger('request');
|
||||||
|
$request_logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/request.log', Logger::NOTICE));
|
||||||
$container->setLogger($app_logger, 'default');
|
$container->setLogger($app_logger, 'default');
|
||||||
|
$container->setLogger($request_logger, 'request');
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Injected Objects
|
// Injected Objects
|
||||||
@ -103,7 +107,9 @@ return function(array $config_array = []) {
|
|||||||
|
|
||||||
// Models
|
// Models
|
||||||
$container->set('kitsu-model', function($container) {
|
$container->set('kitsu-model', function($container) {
|
||||||
$model = new KitsuModel();
|
$listItem = new KitsuListItem();
|
||||||
|
$listItem->setContainer($container);
|
||||||
|
$model = new KitsuModel($listItem);
|
||||||
$model->setContainer($container);
|
$model->setContainer($container);
|
||||||
return $model;
|
return $model;
|
||||||
});
|
});
|
||||||
|
@ -203,7 +203,7 @@ return [
|
|||||||
'index_redirect' => [
|
'index_redirect' => [
|
||||||
'path' => '/',
|
'path' => '/',
|
||||||
'controller' => AnimeClient::DEFAULT_CONTROLLER_NAMESPACE,
|
'controller' => AnimeClient::DEFAULT_CONTROLLER_NAMESPACE,
|
||||||
'action' => 'redirect_to_default',
|
'action' => 'redirectToDefaultRoute',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
@ -11,17 +11,17 @@
|
|||||||
<section class="media-wrap">
|
<section class="media-wrap">
|
||||||
<?php foreach($items as $item): ?>
|
<?php foreach($items as $item): ?>
|
||||||
<?php if ($item['private'] && ! $auth->is_authenticated()) continue; ?>
|
<?php if ($item['private'] && ! $auth->is_authenticated()) continue; ?>
|
||||||
<article class="media" id="<?= $item['anime']['slug'] ?>">
|
<article class="media" id="<?= $item['id'] ?>">
|
||||||
<?php if ($auth->is_authenticated()): ?>
|
<?php if ($auth->is_authenticated()): ?>
|
||||||
<button title="Increment episode count" class="plus_one" hidden>+1 Episode</button>
|
<button title="Increment episode count" class="plus_one" hidden>+1 Episode</button>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?= $helper->img($item['anime']['image']); ?>
|
<?= $helper->img($item['anime']['image']); ?>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<a href="<?= $url->generate('anime.details', ['id' => $item['anime']['slug']]); ?>">
|
<a href="<?= $url->generate('anime.details', ['id' => $item['anime']['slug']]); ?>">
|
||||||
<?= array_shift($item['anime']['titles']) ?>
|
<?= array_shift($item['anime']['titles']) ?>
|
||||||
<?php foreach ($item['anime']['titles'] as $title): ?>
|
<?php foreach ($item['anime']['titles'] as $title): ?>
|
||||||
<br /><small><?= $title ?></small>
|
<br /><small><?= $title ?></small>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="table">
|
<div class="table">
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td>
|
<td>
|
||||||
<input type="hidden" value="<?= $item['anime']['slug'] ?>" name="id" />
|
<input type="hidden" value="<?= $item['id'] ?>" name="id" />
|
||||||
<input type="hidden" value="true" name="edit" />
|
<input type="hidden" value="true" name="edit" />
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
</td>
|
</td>
|
||||||
@ -92,7 +92,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td>
|
<td>
|
||||||
<input type="hidden" value="<?= $item['anime']['slug'] ?>" name="id" />
|
<input type="hidden" value="<?= $item['id'] ?>" name="id" />
|
||||||
<button type="submit" class="danger">Delete Entry</button>
|
<button type="submit" class="danger">Delete Entry</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
12
public/js/anime_edit.js
Executable file → Normal file
12
public/js/anime_edit.js
Executable file → Normal file
@ -15,19 +15,20 @@
|
|||||||
// Setup the update data
|
// Setup the update data
|
||||||
let data = {
|
let data = {
|
||||||
id: parent_sel.id,
|
id: parent_sel.id,
|
||||||
increment_episodes: true
|
data: {
|
||||||
|
progress: watched_count + 1
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the episode count is 0, and incremented,
|
// If the episode count is 0, and incremented,
|
||||||
// change status to currently watching
|
// change status to currently watching
|
||||||
if (isNaN(watched_count) || watched_count === 0) {
|
if (isNaN(watched_count) || watched_count === 0) {
|
||||||
data.status = 'currently-watching';
|
data.data.status = 'current';
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you increment at the last episode, mark as completed
|
// If you increment at the last episode, mark as completed
|
||||||
if (( ! isNaN(watched_count)) && (watched_count + 1) == total_count) {
|
if (( ! isNaN(watched_count)) && (watched_count + 1) == total_count) {
|
||||||
delete data.increment_episodes;
|
data.data.status = 'completed';
|
||||||
data.status = 'completed';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// okay, lets actually make some changes!
|
// okay, lets actually make some changes!
|
||||||
@ -35,7 +36,6 @@
|
|||||||
data: data,
|
data: data,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
mimeType: 'application/json',
|
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (data.status == 'completed') {
|
if (data.status == 'completed') {
|
||||||
_.hide(parent_sel);
|
_.hide(parent_sel);
|
||||||
@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
error: (xhr, errorType, error) => {
|
error: (xhr, errorType, error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
_.showMessage('error', `Failed to updated ${title}. `);
|
_.showMessage('error', `Failed to update ${title}. `);
|
||||||
_.scrollToTop();
|
_.scrollToTop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -249,6 +249,7 @@ var AnimeClient = (function(w) {
|
|||||||
config.type = config.type || 'GET';
|
config.type = config.type || 'GET';
|
||||||
config.dataType = config.dataType || '';
|
config.dataType = config.dataType || '';
|
||||||
config.success = config.success || _.noop;
|
config.success = config.success || _.noop;
|
||||||
|
config.mimeType = config.mimeType || 'application/x-www-form-urlencoded';
|
||||||
config.error = config.error || _.noop;
|
config.error = config.error || _.noop;
|
||||||
|
|
||||||
let request = new XMLHttpRequest();
|
let request = new XMLHttpRequest();
|
||||||
@ -280,14 +281,22 @@ var AnimeClient = (function(w) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (config.dataType === 'json') {
|
||||||
|
config.data = JSON.stringify(config.data);
|
||||||
|
config.mimeType = 'application/json';
|
||||||
|
} else {
|
||||||
|
config.data = ajaxSerialize(config.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', config.mimeType);
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case "GET":
|
case "GET":
|
||||||
request.send(null);
|
request.send(null);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
request.send(config.data);
|
||||||
request.send(ajaxSerialize(config.data));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,8 @@ use Aviat\AnimeClient\API\Kitsu\Transformer\{
|
|||||||
AnimeTransformer, AnimeListTransformer, MangaTransformer, MangaListTransformer
|
AnimeTransformer, AnimeListTransformer, MangaTransformer, MangaListTransformer
|
||||||
};
|
};
|
||||||
use Aviat\Ion\Di\ContainerAware;
|
use Aviat\Ion\Di\ContainerAware;
|
||||||
|
use Aviat\Ion\Json;
|
||||||
|
use GuzzleHttp\Exception\ClientException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kitsu API Model
|
* Kitsu API Model
|
||||||
@ -47,6 +49,11 @@ class KitsuModel {
|
|||||||
*/
|
*/
|
||||||
protected $animeTransformer;
|
protected $animeTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ListItem
|
||||||
|
*/
|
||||||
|
protected $listItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var MangaTransformer
|
* @var MangaTransformer
|
||||||
*/
|
*/
|
||||||
@ -60,13 +67,14 @@ class KitsuModel {
|
|||||||
/**
|
/**
|
||||||
* KitsuModel constructor.
|
* KitsuModel constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(ListItem $listItem)
|
||||||
{
|
{
|
||||||
// Set up Guzzle trait
|
// Set up Guzzle trait
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
$this->animeTransformer = new AnimeTransformer();
|
$this->animeTransformer = new AnimeTransformer();
|
||||||
$this->animeListTransformer = new AnimeListTransformer();
|
$this->animeListTransformer = new AnimeListTransformer();
|
||||||
|
$this->listItem = $listItem;
|
||||||
$this->mangaTransformer = new MangaTransformer();
|
$this->mangaTransformer = new MangaTransformer();
|
||||||
$this->mangaListTransformer = new MangaListTransformer();
|
$this->mangaListTransformer = new MangaListTransformer();
|
||||||
}
|
}
|
||||||
@ -124,7 +132,7 @@ class KitsuModel {
|
|||||||
/**
|
/**
|
||||||
* Get information about a particular manga
|
* Get information about a particular manga
|
||||||
*
|
*
|
||||||
* @param string $animeId
|
* @param string $mangaId
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getManga(string $mangaId): array
|
public function getManga(string $mangaId): array
|
||||||
@ -133,29 +141,6 @@ class KitsuModel {
|
|||||||
return $this->mangaTransformer->transform($baseData);
|
return $this->mangaTransformer->transform($baseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getListItem(string $listId): array
|
|
||||||
{
|
|
||||||
$baseData = $this->getRequest("library-entries/{$listId}", [
|
|
||||||
'query' => [
|
|
||||||
'include' => 'media'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
switch ($baseData['included'][0]['type'])
|
|
||||||
{
|
|
||||||
case 'anime':
|
|
||||||
$baseData['data']['anime'] = $baseData['included'][0];
|
|
||||||
return $this->animeListTransformer->transform($baseData['data']);
|
|
||||||
|
|
||||||
case 'manga':
|
|
||||||
$baseData['data']['manga'] = $baseData['included'][0];
|
|
||||||
return $this->mangaListTransformer->transform($baseData['data']);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return $baseData['data']['attributes'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAnimeList($status): array
|
public function getAnimeList($status): array
|
||||||
{
|
{
|
||||||
$options = [
|
$options = [
|
||||||
@ -185,9 +170,9 @@ class KitsuModel {
|
|||||||
$animeGenres = $item['anime']['relationships']['genres'];
|
$animeGenres = $item['anime']['relationships']['genres'];
|
||||||
|
|
||||||
foreach($animeGenres as $id)
|
foreach($animeGenres as $id)
|
||||||
{
|
{
|
||||||
$item['genres'][] = $included['genres'][$id]['name'];
|
$item['genres'][] = $included['genres'][$id]['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// $item['genres'] = array_pluck($genres, 'name');
|
// $item['genres'] = array_pluck($genres, 'name');
|
||||||
}
|
}
|
||||||
@ -238,10 +223,45 @@ class KitsuModel {
|
|||||||
'include' => 'media'
|
'include' => 'media'
|
||||||
];
|
];
|
||||||
|
|
||||||
$data = $this->getRequest($type, $options);
|
return $this->getRequest($type, $options);
|
||||||
|
}
|
||||||
|
|
||||||
// @TODO implement search api call
|
public function getListItem(string $listId): array
|
||||||
return $data;
|
{
|
||||||
|
$baseData = $this->listItem->get($listId);
|
||||||
|
|
||||||
|
switch ($baseData['included'][0]['type'])
|
||||||
|
{
|
||||||
|
case 'anime':
|
||||||
|
$baseData['data']['anime'] = $baseData['included'][0];
|
||||||
|
return $this->animeListTransformer->transform($baseData['data']);
|
||||||
|
|
||||||
|
case 'manga':
|
||||||
|
$baseData['data']['manga'] = $baseData['included'][0];
|
||||||
|
return $this->mangaListTransformer->transform($baseData['data']);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return $baseData['data']['attributes'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateListItem(array $data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$response = $this->listItem->update($data['id'], $data['data']);
|
||||||
|
return [
|
||||||
|
'statusCode' => $response->getStatusCode(),
|
||||||
|
'body' => $response->getBody(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
catch(ClientException $e)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'statusCode' => $e->getResponse()->getStatusCode(),
|
||||||
|
'body' => Json::decode((string)$e->getResponse()->getBody())
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getUsername(): string
|
private function getUsername(): string
|
||||||
|
@ -21,7 +21,9 @@ use Aviat\AnimeClient\API\GuzzleTrait;
|
|||||||
use Aviat\Ion\Json;
|
use Aviat\Ion\Json;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Cookie\CookieJar;
|
use GuzzleHttp\Cookie\CookieJar;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use PHP_CodeSniffer\Tokenizers\JS;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
trait KitsuTrait {
|
trait KitsuTrait {
|
||||||
@ -33,6 +35,19 @@ trait KitsuTrait {
|
|||||||
*/
|
*/
|
||||||
protected $baseUrl = "https://kitsu.io/api/edge/";
|
protected $baseUrl = "https://kitsu.io/api/edge/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP headers to send with every request
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultHeaders = [
|
||||||
|
'User-Agent' => "Tim's Anime Client/4.0",
|
||||||
|
'Accept-Encoding' => 'application/vnd.api+json',
|
||||||
|
'Content-Type' => 'application/vnd.api+json; charset=utf-8',
|
||||||
|
'client_id' => 'dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd',
|
||||||
|
'client_secret' => '54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the class properties
|
* Set up the class properties
|
||||||
*
|
*
|
||||||
@ -42,11 +57,7 @@ trait KitsuTrait {
|
|||||||
{
|
{
|
||||||
$defaults = [
|
$defaults = [
|
||||||
'cookies' => $this->cookieJar,
|
'cookies' => $this->cookieJar,
|
||||||
'headers' => [
|
'headers' => $this->defaultHeaders,
|
||||||
'User-Agent' => "Tim's Anime Client/4.0",
|
|
||||||
'Accept-Encoding' => 'application/vnd.api+json',
|
|
||||||
'Content-Type' => 'application/vnd.api+json'
|
|
||||||
],
|
|
||||||
'timeout' => 25,
|
'timeout' => 25,
|
||||||
'connect_timeout' => 25
|
'connect_timeout' => 25
|
||||||
];
|
];
|
||||||
@ -66,10 +77,11 @@ trait KitsuTrait {
|
|||||||
* @param string $type
|
* @param string $type
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return array
|
* @return Response
|
||||||
*/
|
*/
|
||||||
private function request(string $type, string $url, array $options = []): array
|
private function getResponse(string $type, string $url, array $options = [])
|
||||||
{
|
{
|
||||||
|
$logger = null;
|
||||||
$validTypes = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];
|
$validTypes = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];
|
||||||
|
|
||||||
if ( ! in_array($type, $validTypes))
|
if ( ! in_array($type, $validTypes))
|
||||||
@ -77,18 +89,13 @@ trait KitsuTrait {
|
|||||||
throw new InvalidArgumentException('Invalid http request type');
|
throw new InvalidArgumentException('Invalid http request type');
|
||||||
}
|
}
|
||||||
|
|
||||||
$logger = NULL;
|
|
||||||
|
|
||||||
$defaultOptions = [
|
$defaultOptions = [
|
||||||
'headers' => [
|
'headers' => $this->defaultHeaders
|
||||||
'client_id' => 'dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd',
|
|
||||||
'client_secret' => '54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->getContainer())
|
if ($this->getContainer());
|
||||||
{
|
{
|
||||||
$logger = $this->container->getLogger('default');
|
$logger = $this->container->getLogger('request');
|
||||||
$sessionSegment = $this->getContainer()
|
$sessionSegment = $this->getContainer()
|
||||||
->get('session')
|
->get('session')
|
||||||
->getSegment(AnimeClient::SESSION_SEGMENT);
|
->getSegment(AnimeClient::SESSION_SEGMENT);
|
||||||
@ -98,11 +105,31 @@ trait KitsuTrait {
|
|||||||
$token = $sessionSegment->get('auth_token');
|
$token = $sessionSegment->get('auth_token');
|
||||||
$defaultOptions['headers']['Authorization'] = "bearer {$token}";
|
$defaultOptions['headers']['Authorization'] = "bearer {$token}";
|
||||||
}
|
}
|
||||||
|
$logger->debug(Json::encode(func_get_args()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = array_merge($defaultOptions, $options);
|
$options = array_merge($defaultOptions, $options);
|
||||||
|
|
||||||
$response = $this->client->request($type, $url, $options);
|
return $this->client->request($type, $url, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a request via Guzzle
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param string $url
|
||||||
|
* @param array $options
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function request(string $type, string $url, array $options = []): array
|
||||||
|
{
|
||||||
|
$logger = null;
|
||||||
|
if ($this->getContainer())
|
||||||
|
{
|
||||||
|
$logger = $this->container->getLogger('request');
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->getResponse($type, $url, $options);
|
||||||
|
|
||||||
if ((int) $response->getStatusCode() !== 200)
|
if ((int) $response->getStatusCode() !== 200)
|
||||||
{
|
{
|
||||||
@ -112,7 +139,7 @@ trait KitsuTrait {
|
|||||||
$logger->warning($response->getBody());
|
$logger->warning($response->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException($response);
|
// throw new RuntimeException($response->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON::decode($response->getBody(), TRUE);
|
return JSON::decode($response->getBody(), TRUE);
|
||||||
@ -129,6 +156,17 @@ trait KitsuTrait {
|
|||||||
return $this->request('GET', ...$args);
|
return $this->request('GET', ...$args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove some boilerplate for patch requests
|
||||||
|
*
|
||||||
|
* @param array $args
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function patchRequest(...$args): array
|
||||||
|
{
|
||||||
|
return $this->request('PATCH', ...$args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove some boilerplate for post requests
|
* Remove some boilerplate for post requests
|
||||||
*
|
*
|
||||||
@ -137,17 +175,38 @@ trait KitsuTrait {
|
|||||||
*/
|
*/
|
||||||
protected function postRequest(...$args): array
|
protected function postRequest(...$args): array
|
||||||
{
|
{
|
||||||
return $this->request('POST', ...$args);
|
$logger = null;
|
||||||
|
if ($this->getContainer())
|
||||||
|
{
|
||||||
|
$logger = $this->container->getLogger('request');
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->getResponse('POST', ...$args);
|
||||||
|
$validResponseCodes = [200, 201];
|
||||||
|
|
||||||
|
if ( ! in_array((int) $response->getStatusCode(), $validResponseCodes))
|
||||||
|
{
|
||||||
|
if ($logger)
|
||||||
|
{
|
||||||
|
$logger->warning('Non 201 response for POST api call');
|
||||||
|
$logger->warning($response->getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException($response->getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON::decode($response->getBody(), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove some boilerplate for delete requests
|
* Remove some boilerplate for delete requests
|
||||||
*
|
*
|
||||||
* @param array $args
|
* @param array $args
|
||||||
* @return array
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function deleteRequest(...$args): array
|
protected function deleteRequest(...$args): bool
|
||||||
{
|
{
|
||||||
return $this->request('DELETE', ...$args);
|
$response = $this->getResponse('DELETE', ...$args);
|
||||||
|
return ((int) $response->getStatusCode() === 204);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,27 +17,59 @@
|
|||||||
namespace Aviat\AnimeClient\API\Kitsu;
|
namespace Aviat\AnimeClient\API\Kitsu;
|
||||||
|
|
||||||
use Aviat\AnimeClient\API\AbstractListItem;
|
use Aviat\AnimeClient\API\AbstractListItem;
|
||||||
|
use Aviat\Ion\Di\ContainerAware;
|
||||||
|
use Aviat\Ion\Json;
|
||||||
|
use GuzzleHttp\Exception\ClientException;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
class KitsuAnimeListItem extends AbstractListItem {
|
/**
|
||||||
|
* CRUD operations for Kitsu list items
|
||||||
|
*/
|
||||||
|
class ListItem extends AbstractListItem {
|
||||||
|
use ContainerAware;
|
||||||
use KitsuTrait;
|
use KitsuTrait;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
|
||||||
public function create(array $data): bool
|
public function create(array $data): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement create() method.
|
// TODO: Implement create() method.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete(string $id): bool
|
public function delete(string $id): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement delete() method.
|
// TODO: Implement delete() method.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $id): array
|
public function get(string $id): array
|
||||||
{
|
{
|
||||||
// TODO: Implement get() method.
|
return $this->getRequest("library-entries/{$id}", [
|
||||||
|
'query' => [
|
||||||
|
'include' => 'media'
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(string $id, array $data): bool
|
public function update(string $id, array $data): Response
|
||||||
{
|
{
|
||||||
// TODO: Implement update() method.
|
$requestData = [
|
||||||
|
'data' => [
|
||||||
|
'id' => $id,
|
||||||
|
'type' => 'libraryEntries',
|
||||||
|
'attributes' => $data
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->getResponse('PATCH', "library-entries/{$id}", [
|
||||||
|
'body' => JSON::encode($requestData)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -80,15 +80,14 @@ class AnimeListTransformer extends AbstractTransformer {
|
|||||||
*
|
*
|
||||||
* @param array $item Transformed library item
|
* @param array $item Transformed library item
|
||||||
* @return array API library item
|
* @return array API library item
|
||||||
* @TODO reimplement
|
|
||||||
*/
|
*/
|
||||||
public function untransform($item)
|
public function untransform($item)
|
||||||
{
|
{
|
||||||
// Messy mapping of boolean values to their API string equivalents
|
// Messy mapping of boolean values to their API string equivalents
|
||||||
$privacy = 'public';
|
$privacy = 'false';
|
||||||
if (array_key_exists('private', $item) && $item['private'])
|
if (array_key_exists('private', $item) && $item['private'])
|
||||||
{
|
{
|
||||||
$privacy = 'private';
|
$privacy = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
$rewatching = 'false';
|
$rewatching = 'false';
|
||||||
@ -97,16 +96,25 @@ class AnimeListTransformer extends AbstractTransformer {
|
|||||||
$rewatching = 'true';
|
$rewatching = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
$untransformed = [
|
||||||
'id' => $item['id'],
|
'id' => $item['id'],
|
||||||
'status' => $item['watching_status'],
|
'data' => [
|
||||||
'sane_rating_update' => $item['user_rating'] / 2,
|
'status' => $item['watching_status'],
|
||||||
'rewatching' => $rewatching,
|
'rating' => $item['user_rating'] / 2,
|
||||||
'rewatched_times' => $item['rewatched'],
|
'reconsuming' => $rewatching,
|
||||||
'notes' => $item['notes'],
|
'reconsumeCount' => $item['rewatched'],
|
||||||
'episodes_watched' => $item['episodes_watched'],
|
'notes' => $item['notes'],
|
||||||
'privacy' => $privacy
|
'progress' => $item['episodes_watched'],
|
||||||
|
'private' => $privacy
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if ((int) $untransformed['data']['rating'] === 0)
|
||||||
|
{
|
||||||
|
unset($untransformed['data']['rating']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $untransformed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End of AnimeListTransformer.php
|
// End of AnimeListTransformer.php
|
@ -1,29 +0,0 @@
|
|||||||
<?php declare(strict_types=1);
|
|
||||||
/**
|
|
||||||
* Anime List Client
|
|
||||||
*
|
|
||||||
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
|
|
||||||
*
|
|
||||||
* PHP version 7
|
|
||||||
*
|
|
||||||
* @package AnimeListClient
|
|
||||||
* @author Timothy J. Warren <tim@timshomepage.net>
|
|
||||||
* @copyright 2015 - 2016 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\API;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common interface for anime and manga list item CRUD
|
|
||||||
*/
|
|
||||||
interface ListInterface {
|
|
||||||
/**
|
|
||||||
* Get the raw list of items
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function get(): array;
|
|
||||||
}
|
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\API;
|
namespace Aviat\AnimeClient\API;
|
||||||
|
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common interface for anime and manga list item CRUD
|
* Common interface for anime and manga list item CRUD
|
||||||
*/
|
*/
|
||||||
@ -42,9 +44,9 @@ interface ListItemInterface {
|
|||||||
*
|
*
|
||||||
* @param string $id - The id of the list item to update
|
* @param string $id - The id of the list item to update
|
||||||
* @param array $data - The data with which to update the list item
|
* @param array $data - The data with which to update the list item
|
||||||
* @return bool
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function update(string $id, array $data): bool;
|
public function update(string $id, array $data): Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a list item
|
* Delete a list item
|
||||||
|
@ -120,7 +120,7 @@ class Controller {
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function redirect_to_default()
|
public function redirectToDefaultRoute()
|
||||||
{
|
{
|
||||||
$default_type = $this->config->get(['routes', 'route_config', 'default_list']);
|
$default_type = $this->config->get(['routes', 'route_config', 'default_list']);
|
||||||
$this->redirect($this->urlGenerator->default_url($default_type), 303);
|
$this->redirect($this->urlGenerator->default_url($default_type), 303);
|
||||||
@ -317,7 +317,7 @@ class Controller {
|
|||||||
$auth = $this->container->get('auth');
|
$auth = $this->container->get('auth');
|
||||||
$auth->logout();
|
$auth->logout();
|
||||||
|
|
||||||
$this->redirect_to_default();
|
$this->redirectToDefaultRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,7 +358,7 @@ class Controller {
|
|||||||
* @param string $type
|
* @param string $type
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setFlashMessage($message, $type = "info")
|
public function set_flash_message($message, $type = "info")
|
||||||
{
|
{
|
||||||
$this->session->setFlash('message', [
|
$this->session->setFlash('message', [
|
||||||
'message_type' => $type,
|
'message_type' => $type,
|
||||||
@ -423,11 +423,12 @@ class Controller {
|
|||||||
* @param int $code - the http status code
|
* @param int $code - the http status code
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function outputJSON($data = [], $code = 200)
|
protected function outputJSON($data = 'Empty response', int $code = 200)
|
||||||
{
|
{
|
||||||
$view = new JsonView($this->container);
|
(new JsonView($this->container))
|
||||||
$view->setStatusCode($code);
|
->setStatusCode($code)
|
||||||
$view->setOutput($data);
|
->setOutput($data)
|
||||||
|
->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,6 +21,7 @@ use Aviat\AnimeClient\API\Kitsu;
|
|||||||
use Aviat\AnimeClient\API\Kitsu\Enum\AnimeWatchingStatus;
|
use Aviat\AnimeClient\API\Kitsu\Enum\AnimeWatchingStatus;
|
||||||
use Aviat\AnimeClient\API\Kitsu\Transformer\AnimeListTransformer;
|
use Aviat\AnimeClient\API\Kitsu\Transformer\AnimeListTransformer;
|
||||||
use Aviat\Ion\Di\ContainerInterface;
|
use Aviat\Ion\Di\ContainerInterface;
|
||||||
|
use Aviat\Ion\Json;
|
||||||
use Aviat\Ion\StringWrapper;
|
use Aviat\Ion\StringWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,18 +228,12 @@ class Anime extends BaseController {
|
|||||||
// large form-based updates
|
// large form-based updates
|
||||||
$transformer = new AnimeListTransformer();
|
$transformer = new AnimeListTransformer();
|
||||||
$post_data = $transformer->untransform($data);
|
$post_data = $transformer->untransform($data);
|
||||||
|
$full_result = $this->model->updateLibraryItem($post_data);
|
||||||
|
|
||||||
$full_result = $this->model->update($post_data);
|
if ($full_result['statusCode'] === 200)
|
||||||
$result = $full_result['body'];
|
|
||||||
|
|
||||||
if (array_key_exists('anime', $result))
|
|
||||||
{
|
{
|
||||||
$title = ( ! empty($result['anime']['alternate_title']))
|
$this->set_flash_message("Successfully updated.", 'success');
|
||||||
? "{$result['anime']['title']} ({$result['anime']['alternate_title']})"
|
// $this->cache->purge();
|
||||||
: "{$result['anime']['title']}";
|
|
||||||
|
|
||||||
$this->set_flash_message("Successfully updated {$title}.", 'success');
|
|
||||||
$this->cache->purge();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -255,8 +250,20 @@ class Anime extends BaseController {
|
|||||||
*/
|
*/
|
||||||
public function update()
|
public function update()
|
||||||
{
|
{
|
||||||
$response = $this->model->update($this->request->getParsedBody());
|
if ($this->request->getHeader('content-type')[0] === 'application/json')
|
||||||
$this->cache->purge();
|
{
|
||||||
|
$data = JSON::decode((string)$this->request->getBody());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$data = $this->request->getParsedBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->model->updateLibraryItem($data);
|
||||||
|
//echo JSON::encode($response);
|
||||||
|
//die();
|
||||||
|
|
||||||
|
// $this->cache->purge();
|
||||||
$this->outputJSON($response['body'], $response['statusCode']);
|
$this->outputJSON($response['body'], $response['statusCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ class Dispatcher extends RoutingBase {
|
|||||||
$raw_route = $this->request->getUri()->getPath();
|
$raw_route = $this->request->getUri()->getPath();
|
||||||
$route_path = "/" . trim($raw_route, '/');
|
$route_path = "/" . trim($raw_route, '/');
|
||||||
|
|
||||||
$logger->debug('Dispatcher - Routing data from get_route method');
|
$logger->info('Dispatcher - Routing data from get_route method');
|
||||||
$logger->debug(print_r([
|
$logger->info(print_r([
|
||||||
'route_path' => $route_path
|
'route_path' => $route_path
|
||||||
], TRUE));
|
], TRUE));
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ class Dispatcher extends RoutingBase {
|
|||||||
{
|
{
|
||||||
$route = $this->getRoute();
|
$route = $this->getRoute();
|
||||||
|
|
||||||
$logger->debug('Dispatcher - Route invoke arguments');
|
$logger->info('Dispatcher - Route invoke arguments');
|
||||||
$logger->debug(print_r($route, TRUE));
|
$logger->info(print_r($route, TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($route)
|
if ($route)
|
||||||
|
@ -81,6 +81,18 @@ class Anime extends API {
|
|||||||
return $this->kitsuModel->getAnime($anime_id);
|
return $this->kitsuModel->getAnime($anime_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for anime by name
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function search($name)
|
||||||
|
{
|
||||||
|
// $raw = $this->kitsuModel->search('anime', $name);
|
||||||
|
return $this->kitsuModel->search('anime', $name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about a specific list item
|
* Get information about a specific list item
|
||||||
* for editing/updating that item
|
* for editing/updating that item
|
||||||
@ -94,15 +106,14 @@ class Anime extends API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for anime by name
|
* Update a list entry
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param array $data
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function search($name)
|
public function updateLibraryItem(array $data): array
|
||||||
{
|
{
|
||||||
$raw = $this->kitsuModel->search('anime', $name);
|
return $this->kitsuModel->updateListItem($data);
|
||||||
return $this->kitsuModel->search('anime', $name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End of AnimeModel.php
|
// End of AnimeModel.php
|
Loading…
Reference in New Issue
Block a user