parent
8904054212
commit
cee211621c
@ -0,0 +1,20 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = false
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cpp,c,h,hpp,cxx}]
|
||||
insert_final_newline = true
|
||||
|
||||
# Yaml files
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
@ -1,11 +1,17 @@
|
||||
{
|
||||
"name": "timw4mail/hummingbird-anime-client",
|
||||
"description": "A self-hosted anime/manga client for hummingbird.",
|
||||
"license":"MIT",
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "5.3.*",
|
||||
"filp/whoops": "1.1.*",
|
||||
"filp/whoops": "dev-php7#fe32a402b086b21360e82013e8a0355575c7c6f4",
|
||||
"aura/router": "2.2.*",
|
||||
"aura/web": "2.0.*",
|
||||
"aviat4ion/query": "2.0.*",
|
||||
"robmorgan/phinx": "*",
|
||||
"abeautifulsite/simpleimage": "*"
|
||||
"aura/html": "2.*",
|
||||
"aura/session": "2.*",
|
||||
"aviat4ion/query": "2.5.*",
|
||||
"robmorgan/phinx": "0.4.*",
|
||||
"abeautifulsite/simpleimage": "2.5.*",
|
||||
"szymach/c-pchart": "1.*"
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* Base Configuration class
|
||||
*/
|
||||
|
||||
namespace AnimeClient\Base;
|
||||
|
||||
/**
|
||||
* Wrapper for configuration values
|
||||
*/
|
||||
class Config {
|
||||
|
||||
/**
|
||||
* Config object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $config_files
|
||||
*/
|
||||
public function __construct(Array $config_files=[])
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (empty($config_files))
|
||||
{
|
||||
require_once \_dir(CONF_DIR, 'config.php'); // $config
|
||||
require_once \_dir(CONF_DIR, 'base_config.php'); // $base_config
|
||||
|
||||
$this->config = array_merge($config, $base_config);
|
||||
}
|
||||
else // @codeCoverageIgnoreEnd
|
||||
{
|
||||
$this->config = $config_files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for config values
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
if (isset($this->config[$key]))
|
||||
{
|
||||
return $this->config[$key];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base url for css/js/images
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asset_url(/*...*/)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$base_url = rtrim($this->url(""), '/');
|
||||
|
||||
$routing_config = $this->__get("routing");
|
||||
|
||||
|
||||
$base_url = "{$base_url}" . $routing_config['asset_path'];
|
||||
|
||||
array_unshift($args, $base_url);
|
||||
|
||||
return implode("/", $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base url from the config
|
||||
*
|
||||
* @param string $type - (optional) The controller
|
||||
* @return string
|
||||
*/
|
||||
public function base_url($type="anime")
|
||||
{
|
||||
$config_path = trim($this->__get("{$type}_path"), "/");
|
||||
|
||||
// Set the appropriate HTTP host
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$path = ($config_path !== '') ? $config_path : "";
|
||||
|
||||
return implode("/", ['/', $host, $path]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a proper url from the path
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public function url($path)
|
||||
{
|
||||
$path = trim($path, '/');
|
||||
|
||||
// Remove any optional parameters from the route
|
||||
$path = preg_replace('`{/.*?}`i', '', $path);
|
||||
|
||||
// Set the appropriate HTTP host
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
return "//{$host}/{$path}";
|
||||
}
|
||||
|
||||
public function default_url($type)
|
||||
{
|
||||
$type = trim($type);
|
||||
$default_path = $this->__get("default_{$type}_path");
|
||||
|
||||
if ( ! is_null($default_path))
|
||||
{
|
||||
return $this->url($default_path);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate full url path from the route path based on config
|
||||
*
|
||||
* @param string $path - (optional) The route path
|
||||
* @param string $type - (optional) The controller (anime or manga), defaults to anime
|
||||
* @return string
|
||||
*/
|
||||
public function full_url($path="", $type="anime")
|
||||
{
|
||||
$config_path = trim($this->__get("{$type}_path"), "/");
|
||||
$config_default_route = $this->__get("default_{$type}_path");
|
||||
|
||||
// Remove beginning/trailing slashes
|
||||
$config_path = trim($config_path, '/');
|
||||
$path = trim($path, '/');
|
||||
|
||||
// Remove any optional parameters from the route
|
||||
$path = preg_replace('`{/.*?}`i', '', $path);
|
||||
|
||||
// Set the appropriate HTTP host
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
// Set the default view
|
||||
if ($path === '')
|
||||
{
|
||||
$path .= trim($config_default_route, '/');
|
||||
if ($this->__get('default_to_list_view')) $path .= '/list';
|
||||
}
|
||||
|
||||
// Set an leading folder
|
||||
/*if ($config_path !== '')
|
||||
{
|
||||
$path = "{$config_path}/{$path}";
|
||||
}*/
|
||||
|
||||
return "//{$host}/{$path}";
|
||||
}
|
||||
}
|
||||
// End of config.php
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Animeclient\Base;
|
||||
|
||||
/**
|
||||
* Wrapper of Aura container to be in the anime client namespace
|
||||
*/
|
||||
class Container {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $container = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct(array $values = [])
|
||||
{
|
||||
$this->container = $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value
|
||||
*
|
||||
* @param string $key
|
||||
* @retun mixed
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->container))
|
||||
{
|
||||
return $this->container[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to the container
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return Container
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->container[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
// End of Container.php
|
@ -0,0 +1,283 @@
|
||||
<?php
|
||||
/**
|
||||
* Base Controller
|
||||
*/
|
||||
namespace AnimeClient\Base;
|
||||
|
||||
/**
|
||||
* Base class for controllers, defines output methods
|
||||
*/
|
||||
class Controller {
|
||||
|
||||
/**
|
||||
* The global configuration object
|
||||
* @var object $config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Request object
|
||||
* @var object $request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Response object
|
||||
* @var object $response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* The api model for the current controller
|
||||
* @var object
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Common data to be sent to views
|
||||
* @var array
|
||||
*/
|
||||
protected $base_data = [
|
||||
'url_type' => 'anime',
|
||||
'other_type' => 'manga',
|
||||
'nav_routes' => []
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Config $config
|
||||
* @param array $web
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->config = $container->get('config');
|
||||
$this->base_data['config'] = $this->config;
|
||||
|
||||
$this->request = $container->get('request');
|
||||
$this->response = $container->get('response');
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a class member
|
||||
*
|
||||
* @param string $key
|
||||
* @return object
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
$allowed = ['request', 'response', 'config'];
|
||||
|
||||
if (in_array($key, $allowed))
|
||||
{
|
||||
return $this->$key;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string output of a partial template
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $template
|
||||
* @param array|object $data
|
||||
* @return string
|
||||
*/
|
||||
public function load_partial($template, $data=[])
|
||||
{
|
||||
if (isset($this->base_data))
|
||||
{
|
||||
$data = array_merge($this->base_data, $data);
|
||||
}
|
||||
|
||||
global $router, $defaultHandler;
|
||||
$route = $router->get_route();
|
||||
$data['route_path'] = ($route) ? $router->get_route()->path : "";
|
||||
|
||||
$defaultHandler->addDataTable('Template Data', $data);
|
||||
|
||||
$template_path = _dir(SRC_DIR, 'views', "{$template}.php");
|
||||
|
||||
if ( ! is_file($template_path))
|
||||
{
|
||||
throw new \InvalidArgumentException("Invalid template : {$path}");
|
||||
}
|
||||
|
||||
ob_start();
|
||||
extract($data);
|
||||
include _dir(SRC_DIR, 'views', 'header.php');
|
||||
include $template_path;
|
||||
include _dir(SRC_DIR, 'views', 'footer.php');
|
||||
$buffer = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a template to HTML, using the provided data
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $template
|
||||
* @param array|object $data
|
||||
* @return void
|
||||
*/
|
||||
public function outputHTML($template, $data=[])
|
||||
{
|
||||
$buffer = $this->load_partial($template, $data);
|
||||
|
||||
$this->response->content->setType('text/html');
|
||||
$this->response->content->set($buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output json with the proper content type
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
public function outputJSON($data)
|
||||
{
|
||||
if ( ! is_string($data))
|
||||
{
|
||||
$data = json_encode($data);
|
||||
}
|
||||
|
||||
$this->response->content->setType('application/json');
|
||||
$this->response->content->set($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the selected page
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $url
|
||||
* @param int $code
|
||||
* @param string $type
|
||||
* @return void
|
||||
*/
|
||||
public function redirect($url, $code, $type="anime")
|
||||
{
|
||||
$url = $this->config->full_url($url, $type);
|
||||
|
||||
$this->response->redirect->to($url, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a message box to the page
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $type
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function show_message($type, $message)
|
||||
{
|
||||
return $this->load_partial('message', [
|
||||
'stat_class' => $type,
|
||||
'message' => $message
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the api session
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return void
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
session_destroy();
|
||||
$this->response->redirect->seeOther($this->config->full_url(''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the login form
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $status
|
||||
* @return void
|
||||
*/
|
||||
public function login($status="")
|
||||
{
|
||||
$message = "";
|
||||
|
||||
if ($status != "")
|
||||
{
|
||||
$message = $this->show_message('error', $status);
|
||||
}
|
||||
|
||||
$this->outputHTML('login', [
|
||||
'title' => 'Api login',
|
||||
'message' => $message
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log in with the api
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function login_action()
|
||||
{
|
||||
if (
|
||||
$this->model->authenticate(
|
||||
$this->config->hummingbird_username,
|
||||
$this->request->post->get('password')
|
||||
)
|
||||
)
|
||||
{
|
||||
$this->response->redirect->afterPost($this->config->full_url('', $this->base_data['url_type']));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->login("Invalid username or password.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the appropriate response
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return void
|
||||
*/
|
||||
private function output()
|
||||
{
|
||||
// send status
|
||||
@header($this->response->status->get(), true, $this->response->status->getCode());
|
||||
|
||||
// headers
|
||||
foreach($this->response->headers->get() as $label => $value)
|
||||
{
|
||||
@header("{$label}: {$value}");
|
||||
}
|
||||
|
||||
// cookies
|
||||
foreach($this->response->cookies->get() as $name => $cookie)
|
||||
{
|
||||
@setcookie(
|
||||
$name,
|
||||
$cookie['value'],
|
||||
$cookie['expire'],
|
||||
$cookie['path'],
|
||||
$cookie['domain'],
|
||||
$cookie['secure'],
|
||||
$cookie['httponly']
|
||||
);
|
||||
}
|
||||
|
||||
// send the actual response
|
||||
echo $this->response->content->get();
|
||||
}
|
||||
}
|
||||
// End of BaseController.php
|
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/**
|
||||
* Base for base models
|
||||
*/
|
||||
namespace AnimeClient\Base;
|
||||
|
||||
use abeautifulsite\SimpleImage;
|
||||
|
||||
/**
|
||||
* Common base for all Models
|
||||
*/
|
||||
class Model {
|
||||
|
||||
/**
|
||||
* The global configuration object
|
||||
* @var Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The container object
|
||||
* @var Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $container->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function get_cached_image($api_path, $series_slug, $type="anime")
|
||||
{
|
||||
$api_path = str_replace("jjpg", "jpg", $api_path);
|
||||
$path_parts = explode('?', basename($api_path));
|
||||
$path = current($path_parts);
|
||||
$ext_parts = explode('.', $path);
|
||||
$ext = end($ext_parts);
|
||||
|
||||
// Workaround for some broken extensions
|
||||
if ($ext == "jjpg") $ext = "jpg";
|
||||
|
||||
// Failsafe for weird urls
|
||||
if (strlen($ext) > 3) return $api_path;
|
||||
|
||||
$cached_image = "{$series_slug}.{$ext}";
|
||||
$cached_path = "{$this->config->img_cache_path}/{$type}/{$cached_image}";
|
||||
|
||||
// Cache the file if it doesn't already exist
|
||||
if ( ! file_exists($cached_path))
|
||||
{
|
||||
if (ini_get('allow_url_fopen'))
|
||||
{
|
||||
copy($api_path, $cached_path);
|
||||
}
|
||||
elseif (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($ch);
|
||||
}
|
||||
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)
|
||||
{
|
||||
$img = new SimpleImage($path);
|
||||
$img->resize($width,$height)->save();
|
||||
}
|
||||
}
|
||||
// End of BaseModel.php
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Base API Model
|
||||
*/
|
||||
namespace AnimeClient\Base\Model;
|
||||
|
||||
use \GuzzleHttp\Client;
|
||||
use \GuzzleHttp\Cookie\CookieJar;
|
||||
use \AnimeClient\Base\Container;
|
||||
|
||||
/**
|
||||
* Base model for api interaction
|
||||
*/
|
||||
class API extends \AnimeClient\Base\Model {
|
||||
|
||||
/**
|
||||
* Base url for making api requests
|
||||
* @var string
|
||||
*/
|
||||
protected $base_url = '';
|
||||
|
||||
/**
|
||||
* The Guzzle http client object
|
||||
* @var object
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* Cookie jar object for api requests
|
||||
* @var object
|
||||
*/
|
||||
protected $cookieJar;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->cookieJar = new CookieJar();
|
||||
$this->client = new Client([
|
||||
'base_url' => $this->base_url,
|
||||
'defaults' => [
|
||||
'cookies' => $this->cookieJar,
|
||||
'headers' => [
|
||||
'User-Agent' => $_SERVER['HTTP_USER_AGENT'],
|
||||
'Accept-Encoding' => 'application/json'
|
||||
],
|
||||
'timeout' => 5,
|
||||
'connect_timeout' => 5
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt login via the api
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
$result = $this->client->post('https://hummingbird.me/api/v1/users/authenticate', [
|
||||
'body' => [
|
||||
'username' => $username,
|
||||
'password' => $password
|
||||
]
|
||||
]);
|
||||
|
||||
if ($result->getStatusCode() === 201)
|
||||
{
|
||||
$_SESSION['hummingbird_anime_token'] = $result->json();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
// End of BaseApiModel.php
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Base DB model
|
||||
*/
|
||||
namespace AnimeClient\Base\Model;
|
||||
|
||||
use AnimeClient\Base\Container;
|
||||
|
||||
/**
|
||||
* Base model for database interaction
|
||||
*/
|
||||
class DB extends \AnimeClient\Base\Model {
|
||||
/**
|
||||
* The query builder object
|
||||
* @var object $db
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* The database connection information array
|
||||
* @var array $db_config
|
||||
*/
|
||||
protected $db_config;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->db_config = $this->config->database;
|
||||
}
|
||||
}
|
||||
// End of BaseDBModel.php
|
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/**
|
||||
* Routing logic
|
||||
*/
|
||||
namespace AnimeClient\Base;
|
||||
|
||||
use \Aura\Web\Request;
|
||||
use \Aura\Web\Response;
|
||||
|
||||
/**
|
||||
* Basic routing/ dispatch
|
||||
*/
|
||||
class Router {
|
||||
|
||||
/**
|
||||
* The route-matching object
|
||||
* @var object $router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* The global configuration object
|
||||
* @var object $config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Class wrapper for input superglobals
|
||||
* @var object
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Array containing request and response objects
|
||||
* @var array $web
|
||||
*/
|
||||
protected $web;
|
||||
|
||||
/**
|
||||
* Routes added to router
|
||||
* @var array $output_routes
|
||||
*/
|
||||
protected $output_routes;
|
||||
|
||||
/**
|
||||
* Injection Container
|
||||
* @var Container $container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Config $config
|
||||
* @param Router $router
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->config = $container->get('config');
|
||||
$this->router = $container->get('aura-router');
|
||||
$this->request = $container->get('request');
|
||||
$this->web = [$this->request, $container->get('response')];
|
||||
|
||||
$this->output_routes = $this->_setup_routes();
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current route object, if one matches
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function get_route()
|
||||
{
|
||||
$error_handler = $this->container->get('error-handler');
|
||||
|
||||
$raw_route = $this->request->server->get('PATH_INFO');
|
||||
$route_path = "/" . trim($raw_route, '/');
|
||||
|
||||
$error_handler->addDataTable('Route Info', [
|
||||
'route_path' => $route_path
|
||||
]);
|
||||
|
||||
$route = $this->router->match($route_path, $_SERVER);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of routes applied
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_output_routes()
|
||||
{
|
||||
return $this->output_routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the current route
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param [object] $route
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch($route = NULL)
|
||||
{
|
||||
$error_handler = $this->container->get('error-handler');
|
||||
|
||||
if (is_null($route))
|
||||
{
|
||||
$route = $this->get_route();
|
||||
$error_handler->addDataTable('route_args', (array)$route);
|
||||
}
|
||||
|
||||
if ( ! $route)
|
||||
{
|
||||
$failure = $this->router->getFailedRoute();
|
||||
$error_handler->addDataTable('failed_route', (array)$failure);
|
||||
}
|
||||
else
|
||||
{
|
||||
list($controller_name, $action_method) = $route->params['action'];
|
||||
$params = (isset($route->params['params'])) ? $route->params['params'] : [];
|
||||
|
||||
if ( ! empty($route->tokens))
|
||||
{
|
||||
foreach($route->tokens as $key => $v)
|
||||
{
|
||||
if (array_key_exists($key, $route->params))
|
||||
{
|
||||
$params[$key] = $route->params[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$controller = new $controller_name($this->container);
|
||||
|
||||
// Run the appropriate controller method
|
||||
|
||||
$error_handler->addDataTable('controller_args', $params);
|
||||
call_user_func_array([$controller, $action_method], $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of route, to select the current controller
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_controller()
|
||||
{
|
||||
$route_type = $this->config->default_list;
|
||||
|
||||
$host = $this->request->server->get("HTTP_HOST");
|
||||
$request_uri = $this->request->server->get('PATH_INFO');
|
||||
|
||||
$path = trim($request_uri, '/');
|
||||
|
||||
$route_type_map = [
|
||||
$this->config->anime_path => 'anime',
|
||||
$this->config->manga_path => 'manga',
|
||||
$this->config->collection_path => 'collection',
|
||||
$this->config->stats_path => 'stats'
|
||||
];
|
||||
|
||||
$segments = explode('/', $path);
|
||||
$controller = array_shift($segments);
|
||||
|
||||
if (array_key_exists($controller, array_keys($route_type_map)))
|
||||
{
|
||||
return $route_type_map[$controller];
|
||||