diff --git a/app/views/main-menu.php b/app/views/main-menu.php index dc5d86a5..f8bd6c78 100644 --- a/app/views/main-menu.php +++ b/app/views/main-menu.php @@ -25,6 +25,7 @@ + [= $helper->a($url->generate('user_info'), 'About '. $config->get('whose_list')) ?>] isAuthenticated()): ?> Logout diff --git a/app/views/me.php b/app/views/me.php index 508d28b4..09a9a37a 100644 --- a/app/views/me.php +++ b/app/views/me.php @@ -10,12 +10,31 @@
= json_encode($attributes, \JSON_PRETTY_PRINT) ?>
= json_encode($relationships, \JSON_PRETTY_PRINT) ?>diff --git a/src/API/JsonAPI.php b/src/API/JsonAPI.php index af4472f6..445edfe6 100644 --- a/src/API/JsonAPI.php +++ b/src/API/JsonAPI.php @@ -112,6 +112,12 @@ class JsonAPI { return $organized; } + /** + * Reorganize 'included' data + * + * @param array $includes + * @return array + */ public static function lightlyOrganizeIncludes(array $includes): array { $organized = []; @@ -167,4 +173,19 @@ class JsonAPI { return $organized; } + + public static function fillRelationshipsFromIncludes(array $relationships, array $includes): array + { + $output = []; + + foreach ($relationships as $key => $block) + { + if (array_key_exists('data', $block) && is_array($block['data']) && ! empty($block['data'])) + { + $output[$key] = $block['data']; + } + } + + return $output; + } } \ No newline at end of file diff --git a/src/Controller.php b/src/Controller.php index f2a86ff1..0ff3a783 100644 --- a/src/Controller.php +++ b/src/Controller.php @@ -31,60 +31,7 @@ use InvalidArgumentException; * @property Response object $response */ class Controller { - - use ContainerAware; - - /** - * Cache manager - * @var \Psr\Cache\CacheItemPoolInterface - */ - protected $cache; - - /** - * The global configuration object - * @var \Aviat\Ion\ConfigInterface $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; - - /** - * Url generation class - * @var UrlGenerator - */ - protected $urlGenerator; - - /** - * Session segment - * @var \Aura\Session\Segment - */ - protected $session; - - /** - * Common data to be sent to views - * @var array - */ - protected $baseData = [ - 'url_type' => 'anime', - 'other_type' => 'manga', - 'menu_name' => '' - ]; + use ControllerTrait; /** * Constructor @@ -130,162 +77,15 @@ class Controller { $model = $this->container->get('kitsu-model'); $data = $model->getUserData($username); $included = JsonAPI::lightlyOrganizeIncludes($data['included']); + $relationships = JsonAPI::fillRelationshipsFromIncludes($data['data']['relationships'], $included); $this->outputHTML('me', [ 'title' => 'About' . $this->config->get('whose_list'), 'attributes' => $data['data']['attributes'], - 'relationships' => $data['data']['relationships'], + 'relationships' => $relationships, 'included' => $included ]); } - /** - * Redirect to the default controller/url from an empty path - * - * @return void - */ - public function redirectToDefaultRoute() - { - $defaultType = $this->config->get(['routes', 'route_config', 'default_list']); - $this->redirect($this->urlGenerator->defaultUrl($defaultType), 303); - } - - /** - * Redirect to the previous page - * - * @return void - */ - public function redirectToPrevious() - { - $previous = $this->session->getFlash('previous'); - $this->redirect($previous, 303); - } - - /** - * Set the current url in the session as the target of a future redirect - * - * @param string|null $url - * @return void - */ - public function setSessionRedirect($url = NULL) - { - $serverParams = $this->request->getServerParams(); - - if ( ! array_key_exists('HTTP_REFERER', $serverParams)) - { - return; - } - - $util = $this->container->get('util'); - $doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri(); - - // Don't attempt to set the redirect url if - // the page is one of the form type pages, - // and the previous page is also a form type page_segments - if ($doubleFormPage) - { - return; - } - - if (is_null($url)) - { - $url = $util->isViewPage() - ? $this->request->url->get() - : $serverParams['HTTP_REFERER']; - } - - $this->session->set('redirect_url', $url); - } - - /** - * Redirect to the url previously set in the session - * - * @return void - */ - public function sessionRedirect() - { - $target = $this->session->get('redirect_url'); - if (empty($target)) - { - $this->notFound(); - } - else - { - $this->redirect($target, 303); - $this->session->set('redirect_url', NULL); - } - } - - /** - * Get a class member - * - * @param string $key - * @return mixed - */ - public function __get(string $key) - { - $allowed = ['response', 'config']; - - if (in_array($key, $allowed)) - { - return $this->$key; - } - - return NULL; - } - - /** - * Get the string output of a partial template - * - * @param HtmlView $view - * @param string $template - * @param array $data - * @throws InvalidArgumentException - * @return string - */ - protected function loadPartial($view, $template, array $data = []) - { - $router = $this->container->get('dispatcher'); - - if (isset($this->baseData)) - { - $data = array_merge($this->baseData, $data); - } - - $route = $router->getRoute(); - $data['route_path'] = $route ? $router->getRoute()->path : ''; - - - $templatePath = _dir($this->config->get('view_path'), "{$template}.php"); - - if ( ! is_file($templatePath)) - { - throw new InvalidArgumentException("Invalid template : {$template}"); - } - - return $view->renderTemplate($templatePath, (array)$data); - } - - /** - * Render a template with header and footer - * - * @param HtmlView $view - * @param string $template - * @param array $data - * @return void - */ - protected function renderFullPage($view, $template, array $data) - { - $view->appendOutput($this->loadPartial($view, 'header', $data)); - - if (array_key_exists('message', $data) && is_array($data['message'])) - { - $view->appendOutput($this->loadPartial($view, 'message', $data['message'])); - } - - $view->appendOutput($this->loadPartial($view, $template, $data)); - $view->appendOutput($this->loadPartial($view, 'footer', $data)); - } - /** * Show the login form * @@ -344,138 +144,5 @@ class Controller { $this->redirectToDefaultRoute(); } - - /** - * 404 action - * - * @return void - */ - public function notFound() - { - $this->outputHTML('404', [ - 'title' => 'Sorry, page not found' - ], NULL, 404); - } - - /** - * Display a generic error page - * - * @param int $httpCode - * @param string $title - * @param string $message - * @param string $long_message - * @return void - */ - public function errorPage($httpCode, $title, $message, $long_message = "") - { - $this->outputHTML('error', [ - 'title' => $title, - 'message' => $message, - 'long_message' => $long_message - ], NULL, $httpCode); - } - - /** - * Set a session flash variable to display a message on - * next page load - * - * @param string $message - * @param string $type - * @return void - */ - public function setFlashMessage($message, $type = "info") - { - static $messages; - - if ( ! $messages) - { - $messages = []; - } - - $messages[] = [ - 'message_type' => $type, - 'message' => $message - ]; - - $this->session->setFlash('message', $messages); - } - - /** - * Purges the API cache - * - * @return void - */ - public function clearCache() - { - $this->cache->clear(); - $this->outputHTML('blank', [ - 'title' => 'Cache cleared' - ], NULL, 200); - } - - /** - * Add a message box to the page - * - * @codeCoverageIgnore - * @param HtmlView $view - * @param string $type - * @param string $message - * @return string - */ - protected function showMessage($view, $type, $message) - { - return $this->loadPartial($view, 'message', [ - 'message_type' => $type, - 'message' => $message - ]); - } - - /** - * Output a template to HTML, using the provided data - * - * @param string $template - * @param array $data - * @param HtmlView|null $view - * @param int $code - * @return void - */ - protected function outputHTML($template, array $data = [], $view = NULL, $code = 200) - { - if (is_null($view)) - { - $view = new HtmlView($this->container); - } - - $view->setStatusCode($code); - $this->renderFullPage($view, $template, $data); - } - - /** - * Output a JSON Response - * - * @param mixed $data - * @param int $code - the http status code - * @return void - */ - protected function outputJSON($data = 'Empty response', int $code = 200) - { - (new JsonView($this->container)) - ->setStatusCode($code) - ->setOutput($data) - ->send(); - } - - /** - * Redirect to the selected page - * - * @param string $url - * @param int $code - * @return void - */ - protected function redirect($url, $code) - { - $http = new HttpView($this->container); - $http->redirect($url, $code); - } } // End of BaseController.php \ No newline at end of file diff --git a/src/ControllerTrait.php b/src/ControllerTrait.php new file mode 100644 index 00000000..01acddd1 --- /dev/null +++ b/src/ControllerTrait.php @@ -0,0 +1,364 @@ + + * @copyright 2015 - 2017 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.0 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient; + +use const Aviat\AnimeClient\SESSION_SEGMENT; + +use function Aviat\AnimeClient\_dir; + +use Aviat\AnimeClient\API\JsonAPI; +use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; +use Aviat\Ion\View\{HtmlView, HttpView, JsonView}; +use InvalidArgumentException; + +trait ControllerTrait { + + use ContainerAware; + + /** + * Cache manager + * @var \Psr\Cache\CacheItemPoolInterface + */ + protected $cache; + + /** + * The global configuration object + * @var \Aviat\Ion\ConfigInterface $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; + + /** + * Url generation class + * @var UrlGenerator + */ + protected $urlGenerator; + + /** + * Session segment + * @var \Aura\Session\Segment + */ + protected $session; + + /** + * Common data to be sent to views + * @var array + */ + protected $baseData = [ + 'url_type' => 'anime', + 'other_type' => 'manga', + 'menu_name' => '' + ]; + + /** + * Redirect to the default controller/url from an empty path + * + * @return void + */ + public function redirectToDefaultRoute() + { + $defaultType = $this->config->get(['routes', 'route_config', 'default_list']); + $this->redirect($this->urlGenerator->defaultUrl($defaultType), 303); + } + + /** + * Redirect to the previous page + * + * @return void + */ + public function redirectToPrevious() + { + $previous = $this->session->getFlash('previous'); + $this->redirect($previous, 303); + } + + /** + * Set the current url in the session as the target of a future redirect + * + * @param string|null $url + * @return void + */ + public function setSessionRedirect($url = NULL) + { + $serverParams = $this->request->getServerParams(); + + if ( ! array_key_exists('HTTP_REFERER', $serverParams)) + { + return; + } + + $util = $this->container->get('util'); + $doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri(); + + // Don't attempt to set the redirect url if + // the page is one of the form type pages, + // and the previous page is also a form type page_segments + if ($doubleFormPage) + { + return; + } + + if (is_null($url)) + { + $url = $util->isViewPage() + ? $this->request->url->get() + : $serverParams['HTTP_REFERER']; + } + + $this->session->set('redirect_url', $url); + } + + /** + * Redirect to the url previously set in the session + * + * @return void + */ + public function sessionRedirect() + { + $target = $this->session->get('redirect_url'); + if (empty($target)) + { + $this->notFound(); + } + else + { + $this->redirect($target, 303); + $this->session->set('redirect_url', NULL); + } + } + + /** + * Get a class member + * + * @param string $key + * @return mixed + */ + public function __get(string $key) + { + $allowed = ['response', 'config']; + + if (in_array($key, $allowed)) + { + return $this->$key; + } + + return NULL; + } + + /** + * Get the string output of a partial template + * + * @param HtmlView $view + * @param string $template + * @param array $data + * @throws InvalidArgumentException + * @return string + */ + protected function loadPartial($view, $template, array $data = []) + { + $router = $this->container->get('dispatcher'); + + if (isset($this->baseData)) + { + $data = array_merge($this->baseData, $data); + } + + $route = $router->getRoute(); + $data['route_path'] = $route ? $router->getRoute()->path : ''; + + + $templatePath = _dir($this->config->get('view_path'), "{$template}.php"); + + if ( ! is_file($templatePath)) + { + throw new InvalidArgumentException("Invalid template : {$template}"); + } + + return $view->renderTemplate($templatePath, (array)$data); + } + + /** + * Render a template with header and footer + * + * @param HtmlView $view + * @param string $template + * @param array $data + * @return void + */ + protected function renderFullPage($view, $template, array $data) + { + $view->appendOutput($this->loadPartial($view, 'header', $data)); + + if (array_key_exists('message', $data) && is_array($data['message'])) + { + $view->appendOutput($this->loadPartial($view, 'message', $data['message'])); + } + + $view->appendOutput($this->loadPartial($view, $template, $data)); + $view->appendOutput($this->loadPartial($view, 'footer', $data)); + } + + /** + * 404 action + * + * @return void + */ + public function notFound() + { + $this->outputHTML('404', [ + 'title' => 'Sorry, page not found' + ], NULL, 404); + } + + /** + * Display a generic error page + * + * @param int $httpCode + * @param string $title + * @param string $message + * @param string $long_message + * @return void + */ + public function errorPage($httpCode, $title, $message, $long_message = "") + { + $this->outputHTML('error', [ + 'title' => $title, + 'message' => $message, + 'long_message' => $long_message + ], NULL, $httpCode); + } + + /** + * Set a session flash variable to display a message on + * next page load + * + * @param string $message + * @param string $type + * @return void + */ + public function setFlashMessage($message, $type = "info") + { + static $messages; + + if ( ! $messages) + { + $messages = []; + } + + $messages[] = [ + 'message_type' => $type, + 'message' => $message + ]; + + $this->session->setFlash('message', $messages); + } + + /** + * Purges the API cache + * + * @return void + */ + public function clearCache() + { + $this->cache->clear(); + $this->outputHTML('blank', [ + 'title' => 'Cache cleared' + ], NULL, 200); + } + + /** + * Add a message box to the page + * + * @codeCoverageIgnore + * @param HtmlView $view + * @param string $type + * @param string $message + * @return string + */ + protected function showMessage($view, $type, $message) + { + return $this->loadPartial($view, 'message', [ + 'message_type' => $type, + 'message' => $message + ]); + } + + /** + * Output a template to HTML, using the provided data + * + * @param string $template + * @param array $data + * @param HtmlView|null $view + * @param int $code + * @return void + */ + protected function outputHTML($template, array $data = [], $view = NULL, $code = 200) + { + if (is_null($view)) + { + $view = new HtmlView($this->container); + } + + $view->setStatusCode($code); + $this->renderFullPage($view, $template, $data); + } + + /** + * Output a JSON Response + * + * @param mixed $data + * @param int $code - the http status code + * @return void + */ + protected function outputJSON($data = 'Empty response', int $code = 200) + { + (new JsonView($this->container)) + ->setStatusCode($code) + ->setOutput($data) + ->send(); + } + + /** + * Redirect to the selected page + * + * @param string $url + * @param int $code + * @return void + */ + protected function redirect($url, $code) + { + $http = new HttpView($this->container); + $http->redirect($url, $code); + } +} \ No newline at end of file