Version 5.1 - All the GraphQL #32
@ -1,7 +1,7 @@
|
||||
language: php
|
||||
|
||||
install:
|
||||
- composer install --no-dev
|
||||
- composer install
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
@ -17,7 +17,7 @@ before_script:
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
- phpunit -c build
|
||||
|
||||
|
||||
services:
|
||||
- redis
|
||||
|
||||
|
@ -67,11 +67,11 @@ class LogicalOperatorAndSniff implements Sniff
|
||||
$error_message = 'Logical operator should be in upper case;'
|
||||
. ' use "' . strtoupper($operator_string)
|
||||
. '" instead of "' . $operator_string . '"';
|
||||
$phpcsFile->addError($error_message, $stackPtr);
|
||||
$phpcsFile->addError($error_message, $stackPtr, 'LowercaseLogicalOperator');
|
||||
}
|
||||
|
||||
$warning_message = 'The symbolic form "&&" is preferred over the literal form "AND"';
|
||||
$phpcsFile->addWarning($warning_message, $stackPtr);
|
||||
$phpcsFile->addWarning($warning_message, $stackPtr, 'UseOfLiteralAndOperator');
|
||||
|
||||
}//end process()
|
||||
|
||||
|
@ -72,7 +72,7 @@ class StrictComparisonOperatorSniff implements Sniff
|
||||
$error_message = '"==" and "!=" are prohibited; use "'
|
||||
. self::$_replacements[$operator_code] . '" instead of "'
|
||||
. $operator_string . '".';
|
||||
$phpcsFile->addError($error_message, $stackPtr);
|
||||
$phpcsFile->addError($error_message, $stackPtr, 'NonStrictComparisonUsed');
|
||||
}//end process()
|
||||
|
||||
|
||||
|
@ -77,7 +77,7 @@ class DisallowSpaceIndentSniff implements Sniff
|
||||
|
||||
if (strpos($tokens[$stackPtr]['content'], " ") !== false) {
|
||||
$error = 'Tabs must be used to indent lines; spaces are not allowed for code indentation';
|
||||
$phpcsFile->addError($error, $stackPtr);
|
||||
$phpcsFile->addError($error, $stackPtr, 'SpacesUsedForIndentation');
|
||||
}
|
||||
}//end process()
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* @package HummingbirdAnimeClient
|
||||
* @author Timothy J. Warren <tim@timshomepage.net>
|
||||
* @copyright 2015 - 2016 Timothy J. Warren
|
||||
* @link https://github.com/timw4mail/HummingBirdAnimeClient
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @version 3.1
|
||||
* @license MIT
|
||||
* @link https://github.com/timw4mail/HummingBirdAnimeClient
|
||||
*/
|
@ -25,6 +25,8 @@
|
||||
<!-- One statement per line -->
|
||||
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
|
||||
|
||||
|
||||
|
||||
<!-- Classes and functions should be commented -->
|
||||
<rule ref="PEAR.Commenting.ClassComment">
|
||||
<exclude name="PEAR.Commenting.ClassComment.MissingCategoryTag" />
|
||||
@ -37,9 +39,10 @@
|
||||
<!-- Exclude this sniff because it doesn't understand multiple types -->
|
||||
<exclude name="PEAR.Commenting.FunctionComment.MissingParamComment" />
|
||||
<exclude name="PEAR.Commenting.FunctionComment.SpacingAfterParamType" />
|
||||
<exclude name="PEAR.Commenting.FunctionComment.SpacingAfterParamName" />
|
||||
</rule>
|
||||
|
||||
<!-- Use warnings for docblock comments for files and variables, since nothing is cleary explained -->
|
||||
<!-- Use warnings for docblock comments for files and variables, since nothing is clearly explained -->
|
||||
<rule ref="PEAR.Commenting.FileComment">
|
||||
<exclude name="PEAR.Commenting.FileComment.InvalidVersion" />
|
||||
<exclude name="PEAR.Commenting.FileComment.MissingCategoryTag" />
|
||||
@ -58,7 +61,9 @@
|
||||
<!-- Use Allman style indenting. With the exception of Class declarations,
|
||||
braces are always placed on a line by themselves, and indented at the same level as the control statement that "owns" them. -->
|
||||
<rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
|
||||
<rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
|
||||
<rule ref="PEAR.WhiteSpace.ScopeClosingBrace">
|
||||
<exclude name="PEAR.WhiteSpace.ScopeClosingBrace.BreakIndent" />
|
||||
</rule>
|
||||
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
|
||||
|
||||
<!-- Use only short array syntax -->
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
$animeclient_file_patterns = [
|
||||
'app/config/*.php',
|
||||
'app/booststrap.php',
|
||||
'app/bootstrap.php',
|
||||
'src/functions.php',
|
||||
'src/Aviat/AnimeClient/*.php'
|
||||
'src/*.php'
|
||||
];
|
||||
|
||||
if ( ! function_exists('glob_recursive'))
|
||||
|
10
index.php
10
index.php
@ -4,15 +4,17 @@
|
||||
*
|
||||
* An API client for Hummingbird to manage anime and manga watch lists
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @package HummingbirdAnimeClient
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2015 - 2016
|
||||
* @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 3.1
|
||||
* @link https://github.com/timw4mail/HummingBirdAnimeClient
|
||||
* @license MIT
|
||||
*/
|
||||
use Aviat\AnimeClient\AnimeClient;
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Whoops\Handler\JsonResponseHandler;
|
||||
|
||||
// Work around the silly timezone error
|
||||
$timezone = ini_get('date.timezone');
|
||||
|
@ -8,10 +8,11 @@
|
||||
<target>phpdoc</target>
|
||||
</transformer>
|
||||
<transformations>
|
||||
<template name="clean" />
|
||||
<template name="zend" />
|
||||
</transformations>
|
||||
<files>
|
||||
<directory>src</directory>
|
||||
<directory>vendor/aviat/ion</directory>
|
||||
<directory>vendor/aviat/ion/src</directory>
|
||||
<directory>vendor/container-interop/container-interop/src</directory>
|
||||
</files>
|
||||
</phpdoc>
|
@ -22,14 +22,32 @@ use Aviat\AnimeClient\Util;
|
||||
*/
|
||||
class CacheImages extends BaseCommand {
|
||||
|
||||
/**
|
||||
* Manga Model
|
||||
*
|
||||
* @var Aviat\AnimeClient\Model\Manga
|
||||
*/
|
||||
protected $mangaModel;
|
||||
|
||||
/**
|
||||
* Anime Model
|
||||
*
|
||||
* @var Aviat\AnimeClient\Model\Anime
|
||||
*/
|
||||
protected $animeModel;
|
||||
|
||||
/**
|
||||
* Miscellaneous helper methods
|
||||
*
|
||||
* @var Aviat\AnimeClient\Util
|
||||
*/
|
||||
protected $util;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Convert manga images
|
||||
*
|
||||
* @throws \ConsoleKit\ConsoleException
|
||||
* @return void
|
||||
*/
|
||||
protected function getMangaImages()
|
||||
{
|
||||
@ -51,6 +69,7 @@ class CacheImages extends BaseCommand {
|
||||
* Convert anime images
|
||||
*
|
||||
* @throws \ConsoleKit\ConsoleException
|
||||
* @return void
|
||||
*/
|
||||
protected function getAnimeImages()
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ use Aviat\Ion\Di\ContainerInterface;
|
||||
use Aviat\Ion\View\HttpView;
|
||||
use Aviat\Ion\View\HtmlView;
|
||||
use Aviat\Ion\View\JsonView;
|
||||
use Doctrine\Instantiator\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Controller base, defines output methods
|
||||
@ -60,7 +61,7 @@ class Controller {
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Url generatation class
|
||||
* Url generation class
|
||||
* @var UrlGenerator
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
@ -117,6 +118,8 @@ class Controller {
|
||||
|
||||
/**
|
||||
* Redirect to the default controller/url from an empty path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function redirect_to_default()
|
||||
{
|
||||
@ -151,7 +154,7 @@ class Controller {
|
||||
}
|
||||
|
||||
$util = $this->container->get('util');
|
||||
$double_form_page = $server_params['HTTP_REFERER'] == $this->request->getUri();
|
||||
$double_form_page = $server_params['HTTP_REFERER'] === $this->request->getUri();
|
||||
|
||||
// Don't attempt to set the redirect url if
|
||||
// the page is one of the form type pages,
|
||||
@ -214,6 +217,7 @@ class Controller {
|
||||
* @param HtmlView $view
|
||||
* @param string $template
|
||||
* @param array $data
|
||||
* @throws \InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
protected function load_partial($view, $template, array $data = [])
|
||||
@ -273,7 +277,7 @@ class Controller {
|
||||
|
||||
$view = new HtmlView($this->container);
|
||||
|
||||
if ($status != "")
|
||||
if ($status !== "")
|
||||
{
|
||||
$message = $this->show_message($view, 'error', $status);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ class Anime extends BaseController {
|
||||
|
||||
/**
|
||||
* Data cache
|
||||
* @var Aviat\Ion\Cache\CacheInterface
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
@ -103,7 +104,7 @@ class Anime extends BaseController {
|
||||
'list' => 'list'
|
||||
];
|
||||
|
||||
$data = ($type != 'all')
|
||||
$data = ($type !== 'all')
|
||||
? $this->cache->get($this->model, 'get_list', ['status' => $model_map[$type]])
|
||||
: $this->cache->get($this->model, 'get_all_lists', []);
|
||||
|
||||
@ -251,6 +252,8 @@ class Anime extends BaseController {
|
||||
|
||||
/**
|
||||
* Update an anime item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
@ -261,12 +264,14 @@ class Anime extends BaseController {
|
||||
|
||||
/**
|
||||
* Remove an anime from the list
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$response = $this->model->delete($this->request->getParsedBody());
|
||||
|
||||
if ($response['body'] == TRUE)
|
||||
if ((bool)$response['body'] === TRUE)
|
||||
{
|
||||
$this->set_flash_message("Successfully deleted anime.", 'success');
|
||||
$this->cache->purge();
|
||||
|
@ -177,11 +177,11 @@ class Manga extends Controller {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function search()
|
||||
{
|
||||
public function search()
|
||||
{
|
||||
$query_data = $this->request->getQueryParams();
|
||||
$this->outputJSON($this->model->search($query_data['query']));
|
||||
}
|
||||
$this->outputJSON($this->model->search($query_data['query']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an anime item via a form submission
|
||||
@ -200,7 +200,7 @@ class Manga extends Controller {
|
||||
|
||||
$result = Json::decode((string)$full_result['body']);
|
||||
|
||||
if ($full_result['statusCode'] == 200)
|
||||
if ((int)$full_result['statusCode'] === 200)
|
||||
{
|
||||
$m =& $result['manga'][0];
|
||||
$title = ( ! empty($m['english_title']))
|
||||
@ -232,12 +232,14 @@ class Manga extends Controller {
|
||||
|
||||
/**
|
||||
* Remove an manga from the list
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$response = $this->model->delete($this->request->getParsedBody());
|
||||
|
||||
if ($response['body'] == TRUE)
|
||||
if ((bool)$response['body'] === TRUE)
|
||||
{
|
||||
$this->set_flash_message("Successfully deleted manga.", 'success');
|
||||
$this->cache->purge();
|
||||
|
@ -138,6 +138,7 @@ class Dispatcher extends RoutingBase {
|
||||
* the current route
|
||||
*
|
||||
* @param \Aura\Router\Route $route
|
||||
* @throws \LogicException
|
||||
* @return array
|
||||
*/
|
||||
protected function process_route($route)
|
||||
|
@ -17,13 +17,9 @@ namespace Aviat\AnimeClient\Model;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\ResponseInterface;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
use Aviat\Ion\Di\ContainerInterface;
|
||||
use Aviat\Ion\Cache\CacheInterface;
|
||||
|
||||
use Aviat\Ion\Model;
|
||||
use Aviat\AnimeClient\AnimeClient;
|
||||
|
||||
@ -166,7 +162,7 @@ class API extends Model {
|
||||
*/
|
||||
protected function sort_by_name(&$array, $sort_key)
|
||||
{
|
||||
$sort = array();
|
||||
$sort = [];
|
||||
|
||||
foreach ($array as $key => $item)
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ class Anime extends API {
|
||||
public function update($data)
|
||||
{
|
||||
$auth = $this->container->get('auth');
|
||||
if ( ! $auth->is_authenticated() || ! array_key_exists('id', $data))
|
||||
if ( ! $auth->is_authenticated() OR ! array_key_exists('id', $data))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -86,7 +86,7 @@ class Anime extends API {
|
||||
public function delete($data)
|
||||
{
|
||||
$auth = $this->container->get('auth');
|
||||
if ( ! $auth->is_authenticated() || ! array_key_exists('id', $data))
|
||||
if ( ! $auth->is_authenticated() OR ! array_key_exists('id', $data))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -176,7 +176,7 @@ class Anime extends API {
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
* @throws RuntimeException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function search($name)
|
||||
{
|
||||
@ -190,12 +190,12 @@ class Anime extends API {
|
||||
|
||||
$response = $this->get('search/anime', $config);
|
||||
|
||||
if ($response->getStatusCode() != 200)
|
||||
if ((int) $response->getStatusCode() !== 200)
|
||||
{
|
||||
$logger->warning("Non 200 response for search api call");
|
||||
$logger->warning($response->getBody());
|
||||
|
||||
throw new RuntimeException($response->getEffectiveUrl());
|
||||
throw new \RuntimeException($response->getEffectiveUrl());
|
||||
}
|
||||
|
||||
return Json::decode($response->getBody(), TRUE);
|
||||
@ -214,7 +214,7 @@ class Anime extends API {
|
||||
'allow_redirects' => FALSE
|
||||
];
|
||||
|
||||
if ($status != "all")
|
||||
if ($status !== "all")
|
||||
{
|
||||
$config['query']['status'] = $status;
|
||||
}
|
||||
@ -250,11 +250,6 @@ class Anime extends API {
|
||||
];
|
||||
|
||||
$username = $this->config->get('hummingbird_username');
|
||||
/*$auth = $this->container->get('auth');
|
||||
if ($auth->is_authenticated())
|
||||
{
|
||||
$config['query']['auth_token'] = $auth->get_auth_token();
|
||||
}*/
|
||||
|
||||
$response = $this->get("users/{$username}/library", $config);
|
||||
return Json::decode($response->getBody(), TRUE);
|
||||
@ -264,7 +259,7 @@ class Anime extends API {
|
||||
* Handle transforming of api data
|
||||
*
|
||||
* @param string $status
|
||||
* @param \GuzzleHttp\Message\Response
|
||||
* @param \GuzzleHttp\Message\Response $response
|
||||
* @return array
|
||||
*/
|
||||
protected function transform($status, $response)
|
||||
|
@ -218,7 +218,7 @@ class AnimeCollection extends Collection {
|
||||
*/
|
||||
private function json_import()
|
||||
{
|
||||
if ( ! file_exists('import.json') || ! $this->valid_database)
|
||||
if ( ! file_exists('import.json') OR ! $this->valid_database)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class Collection extends DB {
|
||||
|
||||
/**
|
||||
* Whether the database is valid for querying
|
||||
* @var bool
|
||||
* @var boolean
|
||||
*/
|
||||
protected $valid_database = FALSE;
|
||||
|
||||
|
@ -144,7 +144,7 @@ class Manga extends API {
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
* @throws RuntimeException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function search($name)
|
||||
{
|
||||
@ -160,7 +160,7 @@ class Manga extends API {
|
||||
|
||||
$response = $this->get('search.json', $config);
|
||||
|
||||
if ($response->getStatusCode() != 200)
|
||||
if ((int) $response->getStatusCode() !== 200)
|
||||
{
|
||||
$logger->warning("Non 200 response for search api call");
|
||||
$logger->warning($response->getBody());
|
||||
|
@ -24,6 +24,7 @@ class UrlGenerator extends RoutingBase {
|
||||
|
||||
/**
|
||||
* The current HTTP host
|
||||
* @var string
|
||||
*/
|
||||
protected $host;
|
||||
|
||||
@ -43,7 +44,7 @@ class UrlGenerator extends RoutingBase {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asset_url(/*...*/)
|
||||
public function asset_url()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$base_url = rtrim($this->url(""), '/');
|
||||
@ -106,6 +107,7 @@ class UrlGenerator extends RoutingBase {
|
||||
* Full default path for the list pages
|
||||
*
|
||||
* @param string $type
|
||||
* @throws \InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
public function default_url($type)
|
||||
|
397
src/Util.php
397
src/Util.php
@ -1,195 +1,204 @@
|
||||
<?php
|
||||
/**
|
||||
* Hummingbird Anime Client
|
||||
*
|
||||
* An API client for Hummingbird to manage anime and manga watch lists
|
||||
*
|
||||
* @package HummingbirdAnimeClient
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2015 - 2016
|
||||
* @link https://github.com/timw4mail/HummingBirdAnimeClient
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Aviat\AnimeClient;
|
||||
|
||||
use abeautifulsite\SimpleImage;
|
||||
use Aviat\Ion\ConfigInterface;
|
||||
use Aviat\Ion\Di\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Utility method class
|
||||
*/
|
||||
class Util {
|
||||
|
||||
use \Aviat\Ion\Di\ContainerAware;
|
||||
|
||||
private static $form_pages = [
|
||||
'edit',
|
||||
'add',
|
||||
'update',
|
||||
'update_form',
|
||||
'login',
|
||||
'logout',
|
||||
'details'
|
||||
];
|
||||
|
||||
/**
|
||||
* The config manager
|
||||
* @var ConfigInterface
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Set up the Util class
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->setContainer($container);
|
||||
$this->config = $container->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML selection helper function
|
||||
*
|
||||
* @param string $a - First item to compare
|
||||
* @param string $b - Second item to compare
|
||||
* @return string
|
||||
*/
|
||||
public static function is_selected($a, $b)
|
||||
{
|
||||
return ($a === $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of selected helper function
|
||||
*
|
||||
* @param string $a - First item to compare
|
||||
* @param string $b - Second item to compare
|
||||
* @return string
|
||||
*/
|
||||
public static function is_not_selected($a, $b)
|
||||
{
|
||||
return ($a !== $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to show the sub-menu
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_view_page()
|
||||
{
|
||||
$url = $this->container->get('request')
|
||||
->getUri();
|
||||
$page_segments = explode("/", $url);
|
||||
|
||||
$intersect = array_intersect($page_segments, self::$form_pages);
|
||||
|
||||
return empty($intersect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the page is a page with a form, and
|
||||
* not suitable for redirection
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_form_page()
|
||||
{
|
||||
return ! $this->is_view_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of the cached version of the image. Create the cached image
|
||||
* if the file does not already exist
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $api_path - The original image url
|
||||
* @param string $series_slug - The part of the url with the series name, becomes the image name
|
||||
* @param string $type - Anime or Manga, controls cache path
|
||||
* @return string - the frontend path for the cached image
|
||||
* @throws DomainException
|
||||
*/
|
||||
public function get_cached_image($api_path, $series_slug, $type = "anime")
|
||||
{
|
||||
$path_parts = explode('?', basename($api_path));
|
||||
$path = current($path_parts);
|
||||
$ext_parts = explode('.', $path);
|
||||
$ext = end($ext_parts);
|
||||
|
||||
// Workaround for some broken file extensions
|
||||
if ($ext == "jjpg")
|
||||
{
|
||||
$ext = "jpg";
|
||||
}
|
||||
|
||||
// Failsafe for weird urls
|
||||
if (strlen($ext) > 3)
|
||||
{
|
||||
return $api_path;
|
||||
}
|
||||
|
||||
$img_cache_path = $this->config->get('img_cache_path');
|
||||
$cached_image = "{$series_slug}.{$ext}";
|
||||
$cached_path = "{$img_cache_path}/{$type}/{$cached_image}";
|
||||
|
||||
// Cache the file if it doesn't already exist
|
||||
if ( ! file_exists($cached_path))
|
||||
{
|
||||
if (function_exists('curl_init'))
|
||||
{
|
||||
$ch = curl_init($api_path);
|
||||
$fp = fopen($cached_path, 'wb');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_FILE => $fp,
|
||||
CURLOPT_HEADER => 0
|
||||
]);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
}
|
||||
else if (ini_get('allow_url_fopen'))
|
||||
{
|
||||
copy($api_path, $cached_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \DomainException("Couldn't cache images because they couldn't be downloaded.");
|
||||
}
|
||||
|
||||
// Resize the image
|
||||
if ($type == 'anime')
|
||||
{
|
||||
$resize_width = 220;
|
||||
$resize_height = 319;
|
||||
$this->_resize($cached_path, $resize_width, $resize_height);
|
||||
}
|
||||
}
|
||||
|
||||
return "/public/images/{$type}/{$cached_image}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize an image
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $path
|
||||
* @param string $width
|
||||
* @param string $height
|
||||
*/
|
||||
private function _resize($path, $width, $height)
|
||||
{
|
||||
try
|
||||
{
|
||||
$img = new SimpleImage($path);
|
||||
$img->resize($width, $height)->save();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Catch image errors, since they don't otherwise affect
|
||||
// functionality
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* Hummingbird Anime Client
|
||||
*
|
||||
* An API client for Hummingbird to manage anime and manga watch lists
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @package HummingbirdAnimeClient
|
||||
* @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 3.1
|
||||
* @link https://github.com/timw4mail/HummingBirdAnimeClient
|
||||
*/
|
||||
|
||||
namespace Aviat\AnimeClient;
|
||||
|
||||
use abeautifulsite\SimpleImage;
|
||||
use Aviat\Ion\ConfigInterface;
|
||||
use Aviat\Ion\Di\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Utility method class
|
||||
*/
|
||||
class Util {
|
||||
|
||||
use \Aviat\Ion\Di\ContainerAware;
|
||||
|
||||
/**
|
||||
* Routes that don't require a second navigation level
|
||||
* @var array
|
||||
*/
|
||||
private static $form_pages = [
|
||||
'edit',
|
||||
'add',
|
||||
'update',
|
||||
'update_form',
|
||||
'login',
|
||||
'logout',
|
||||
'details'
|
||||
];
|
||||
|
||||
/**
|
||||
* The config manager
|
||||
* @var ConfigInterface
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Set up the Util class
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->setContainer($container);
|
||||
$this->config = $container->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML selection helper function
|
||||
*
|
||||
* @param string $a - First item to compare
|
||||
* @param string $b - Second item to compare
|
||||
* @return string
|
||||
*/
|
||||
public static function is_selected($a, $b)
|
||||
{
|
||||
return ($a === $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of selected helper function
|
||||
*
|
||||
* @param string $a - First item to compare
|
||||
* @param string $b - Second item to compare
|
||||
* @return string
|
||||
*/
|
||||
public static function is_not_selected($a, $b)
|
||||
{
|
||||
return ($a !== $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to show the sub-menu
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_view_page()
|
||||
{
|
||||
$url = $this->container->get('request')
|
||||
->getUri();
|
||||
$page_segments = explode("/", $url);
|
||||
|
||||
$intersect = array_intersect($page_segments, self::$form_pages);
|
||||
|
||||
return empty($intersect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the page is a page with a form, and
|
||||
* not suitable for redirection
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_form_page()
|
||||
{
|
||||
return ! $this->is_view_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of the cached version of the image. Create the cached image
|
||||
* if the file does not already exist
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $api_path - The original image url
|
||||
* @param string $series_slug - The part of the url with the series name, becomes the image name
|
||||
* @param string $type - Anime or Manga, controls cache path
|
||||
* @return string - the frontend path for the cached image
|
||||
* @throws \DomainException
|
||||
*/
|
||||
public function get_cached_image($api_path, $series_slug, $type = "anime")
|
||||
{
|
||||
$path_parts = explode('?', basename($api_path));
|
||||
$path = current($path_parts);
|
||||
$ext_parts = explode('.', $path);
|
||||
$ext = end($ext_parts);
|
||||
|
||||
// Workaround for some broken file extensions
|
||||
if ($ext === "jjpg")
|
||||
{
|
||||
$ext = "jpg";
|
||||
}
|
||||
|
||||
// Failsafe for weird urls
|
||||
if (strlen($ext) > 3)
|
||||
{
|
||||
return $api_path;
|
||||
}
|
||||
|
||||
$img_cache_path = $this->config->get('img_cache_path');
|
||||
$cached_image = "{$series_slug}.{$ext}";
|
||||
$cached_path = "{$img_cache_path}/{$type}/{$cached_image}";
|
||||
|
||||
// Cache the file if it doesn't already exist
|
||||
if ( ! file_exists($cached_path))
|
||||
{
|
||||
if (function_exists('curl_init'))
|
||||
{
|
||||
$ch = curl_init($api_path);
|
||||
$fp = fopen($cached_path, 'wb');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_FILE => $fp,
|
||||
CURLOPT_HEADER => 0
|
||||
]);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
}
|
||||
else if (ini_get('allow_url_fopen'))
|
||||
{
|
||||
copy($api_path, $cached_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \DomainException("Couldn't cache images because they couldn't be downloaded.");
|
||||
}
|
||||
|
||||
// Resize the image
|
||||
if ($type === 'anime')
|
||||
{
|
||||
$resize_width = 220;
|
||||
$resize_height = 319;
|
||||
$this->_resize($cached_path, $resize_width, $resize_height);
|
||||
}
|
||||
}
|
||||
|
||||
return "/public/images/{$type}/{$cached_image}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize an image
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $path
|
||||
* @param string $width
|
||||
* @param string $height
|
||||
* @return void
|
||||
*/
|
||||
private function _resize($path, $width, $height)
|
||||
{
|
||||
try
|
||||
{
|
||||
$img = new SimpleImage($path);
|
||||
$img->resize($width, $height)->save();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Catch image errors, since they don't otherwise affect
|
||||
// functionality
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user