From c100105fbc43e4a2631c9c669d51f365b5416baa Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Thu, 11 Feb 2021 19:54:22 -0500 Subject: [PATCH] Yet more PHPStan fixes --- index.php | 2 +- phpstan.neon | 1 + src/AnimeClient/AnimeClient.php | 4 +- src/AnimeClient/Controller.php | 13 +++---- src/AnimeClient/Controller/Anime.php | 8 ++-- .../Controller/AnimeCollection.php | 10 ++--- src/AnimeClient/Controller/Images.php | 13 +++++-- src/AnimeClient/Controller/Manga.php | 16 +++----- src/AnimeClient/Controller/Misc.php | 8 +++- src/AnimeClient/Controller/Settings.php | 12 ++++-- src/AnimeClient/Dispatcher.php | 37 ++++++++++++------- src/AnimeClient/FormGenerator.php | 2 +- src/AnimeClient/MenuGenerator.php | 6 +-- src/AnimeClient/Model/MediaTrait.php | 2 +- src/AnimeClient/RoutingBase.php | 19 ++++------ src/Ion/HttpViewInterface.php | 32 ++++++++++++++++ src/Ion/View/HtmlView.php | 9 +---- src/Ion/View/HttpView.php | 12 +++--- src/Ion/View/JsonView.php | 6 +-- 19 files changed, 126 insertions(+), 86 deletions(-) create mode 100644 src/Ion/HttpViewInterface.php diff --git a/index.php b/index.php index 2e72e99e..ca9a24a5 100644 --- a/index.php +++ b/index.php @@ -64,7 +64,7 @@ if (array_key_exists('timezone', $checkedConfig) && ! empty($checkedConfig['time { date_default_timezone_set($checkedConfig['timezone']); } -else if ($timezone !== '') +else if (is_string($timezone) && $timezone !== '') { date_default_timezone_set($timezone); } diff --git a/phpstan.neon b/phpstan.neon index 8390c43c..a5bf6603 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -8,6 +8,7 @@ parameters: - ./console - index.php ignoreErrors: + - '#Access to an undefined property Aviat\\Ion\\Friend#' - "#Offset 'fields' does not exist on array#" - '#Call to an undefined method Aura\\\Html\\\HelperLocator::[a-zA-Z0-9_]+\(\)#' - '#Call to an undefined method Query\\QueryBuilderInterface::[a-zA-Z0-9_]+\(\)#' diff --git a/src/AnimeClient/AnimeClient.php b/src/AnimeClient/AnimeClient.php index df1ce722..481e34c2 100644 --- a/src/AnimeClient/AnimeClient.php +++ b/src/AnimeClient/AnimeClient.php @@ -91,7 +91,7 @@ function loadTomlFile(string $filename): array return Toml::parseFile($filename); } -function _iterateToml(TomlBuilder $builder, iterable $data, $parentKey = NULL): void +function _iterateToml(TomlBuilder $builder, iterable $data, mixed $parentKey = NULL): void { foreach ($data as $key => $value) { @@ -359,7 +359,7 @@ function colNotEmpty(array $search, string $key): bool * * @param CacheInterface $cache * @return bool - * @throws InvalidArgumentException + * @throws Throwable */ function clearCache(CacheInterface $cache): bool { diff --git a/src/AnimeClient/Controller.php b/src/AnimeClient/Controller.php index c0827ee4..3f6a1cc3 100644 --- a/src/AnimeClient/Controller.php +++ b/src/AnimeClient/Controller.php @@ -203,7 +203,7 @@ class Controller { * @throws NotFoundException * @return string */ - protected function loadPartial($view, string $template, array $data = []): string + protected function loadPartial(HtmlView $view, string $template, array $data = []): string { $router = $this->container->get('dispatcher'); @@ -236,7 +236,7 @@ class Controller { * @throws ContainerException * @throws NotFoundException */ - protected function renderFullPage($view, string $template, array $data): HtmlView + protected function renderFullPage(HtmlView $view, string $template, array $data): HtmlView { $csp = [ "default-src 'self'", @@ -360,7 +360,7 @@ class Controller { * @throws NotFoundException * @return string */ - protected function showMessage($view, string $type, string $message): string + protected function showMessage(HtmlView $view, string $type, string $message): string { return $this->loadPartial($view, 'message', [ 'message_type' => $type, @@ -399,7 +399,7 @@ class Controller { * @throws DoubleRenderException * @return void */ - protected function outputJSON($data, int $code): void + protected function outputJSON(mixed $data, int $code): void { (new JsonView()) ->setOutput($data) @@ -420,10 +420,7 @@ class Controller { { (new HttpView())->redirect($url, $code)->send(); } - catch (\Throwable $e) - { - - } + catch (\Throwable) {} } } // End of BaseController.php \ No newline at end of file diff --git a/src/AnimeClient/Controller/Anime.php b/src/AnimeClient/Controller/Anime.php index 04bd7862..e011e426 100644 --- a/src/AnimeClient/Controller/Anime.php +++ b/src/AnimeClient/Controller/Anime.php @@ -145,7 +145,7 @@ final class Anime extends BaseController { { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); if (empty($data['mal_id'])) { @@ -220,7 +220,7 @@ final class Anime extends BaseController { { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); // Do some minor data manipulation for // large form-based updates @@ -257,7 +257,7 @@ final class Anime extends BaseController { } else { - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); } if (empty($data)) @@ -282,7 +282,7 @@ final class Anime extends BaseController { { $this->checkAuth(); - $body = $this->request->getParsedBody(); + $body = (array)$this->request->getParsedBody(); $response = $this->model->deleteLibraryItem($body['id'], $body['mal_id']); if ($response === TRUE) diff --git a/src/AnimeClient/Controller/AnimeCollection.php b/src/AnimeClient/Controller/AnimeCollection.php index 0935d181..97de11d4 100644 --- a/src/AnimeClient/Controller/AnimeCollection.php +++ b/src/AnimeClient/Controller/AnimeCollection.php @@ -154,7 +154,7 @@ final class AnimeCollection extends BaseController { public function edit(): void { $this->checkAuth(); - $this->update($this->request->getParsedBody()); + $this->update((array)$this->request->getParsedBody()); } /** @@ -169,7 +169,7 @@ final class AnimeCollection extends BaseController { { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); if (array_key_exists('id', $data)) { // Check for existing entry @@ -218,7 +218,7 @@ final class AnimeCollection extends BaseController { { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); if ( ! array_key_exists('hummingbird_id', $data)) { $this->setFlashMessage("Can't delete item that doesn't exist", 'error'); @@ -238,11 +238,11 @@ final class AnimeCollection extends BaseController { /** * Update a collection item * - * @param $data + * @param array $data * @throws ContainerException * @throws NotFoundException */ - protected function update($data): void + protected function update(array $data): void { if (array_key_exists('hummingbird_id', $data)) { diff --git a/src/AnimeClient/Controller/Images.php b/src/AnimeClient/Controller/Images.php index dbceec27..1f526d7a 100644 --- a/src/AnimeClient/Controller/Images.php +++ b/src/AnimeClient/Controller/Images.php @@ -37,9 +37,7 @@ final class Images extends BaseController { * @param string $file The filename to look for * @param bool $display Whether to output the image to the server * @return void - * @throws NotFoundException * @throws Throwable - * @throws ContainerException */ public function cache(string $type, string $file, $display = TRUE): void { @@ -134,7 +132,16 @@ final class Images extends BaseController { [$origWidth] = getimagesizefromstring($data); $gdImg = imagecreatefromstring($data); + if ($gdImg === FALSE) + { + return; + } + $resizedImg = imagescale($gdImg, $width ?? $origWidth); + if ($resizedImg === FALSE) + { + return; + } if ($ext === 'gif') { @@ -161,7 +168,7 @@ final class Images extends BaseController { ? 'image/webp' : $response->getHeader('content-type')[0]; - $outputFile = (strpos($file, '-original') !== FALSE) + $outputFile = (str_contains($file, '-original')) ? "{$filePrefix}-original.{$ext}" : "{$filePrefix}.{$ext}"; diff --git a/src/AnimeClient/Controller/Manga.php b/src/AnimeClient/Controller/Manga.php index fd26aded..049be5a1 100644 --- a/src/AnimeClient/Controller/Manga.php +++ b/src/AnimeClient/Controller/Manga.php @@ -135,15 +135,13 @@ final class Manga extends Controller { * Add an manga to the list * * @return void - * @throws NotFoundException * @throws Throwable - * @throws ContainerException */ public function add(): void { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); if ( ! array_key_exists('id', $data)) { $this->redirect('manga/add', 303); @@ -163,7 +161,7 @@ final class Manga extends Controller { } else { - $this->setFlashMessage('Failed to add new manga to list' . $result['body'], 'error'); + $this->setFlashMessage('Failed to add new manga to list:' . print_r($data, TRUE), 'error'); } $this->sessionRedirect(); @@ -180,7 +178,7 @@ final class Manga extends Controller { * @throws InvalidArgumentException * @return void */ - public function edit($id, $status = 'All'): void + public function edit(string $id, string $status = 'All'): void { $this->checkAuth(); @@ -218,14 +216,12 @@ final class Manga extends Controller { * * @return void * @throws Throwable - * @throws NotFoundException - * @throws ContainerException */ public function formUpdate(): void { $this->checkAuth(); - $data = $this->request->getParsedBody(); + $data = (array)$this->request->getParsedBody(); // Do some minor data manipulation for // large form-based updates @@ -275,8 +271,6 @@ final class Manga extends Controller { /** * Remove an manga from the list * - * @throws ContainerException - * @throws NotFoundException * @throws Throwable * @return void */ @@ -284,7 +278,7 @@ final class Manga extends Controller { { $this->checkAuth(); - $body = $this->request->getParsedBody(); + $body = (array)$this->request->getParsedBody(); $response = $this->model->deleteLibraryItem($body['id'], $body['mal_id']); if ($response) diff --git a/src/AnimeClient/Controller/Misc.php b/src/AnimeClient/Controller/Misc.php index 208bb29a..6d4a72b7 100644 --- a/src/AnimeClient/Controller/Misc.php +++ b/src/AnimeClient/Controller/Misc.php @@ -74,7 +74,7 @@ final class Misc extends BaseController { */ public function loginAction(): void { - $post = $this->request->getParsedBody(); + $post = (array)$this->request->getParsedBody(); if ($this->auth->authenticate($post['password'])) { @@ -83,7 +83,11 @@ final class Misc extends BaseController { } $this->setFlashMessage('Invalid username or password.'); - $this->redirect($this->url->generate('login'), 303); + + $redirectUrl = $this->url->generate('login'); + $redirectUrl = ($redirectUrl !== FALSE) ? $redirectUrl : ''; + + $this->redirect($redirectUrl, 303); } /** diff --git a/src/AnimeClient/Controller/Settings.php b/src/AnimeClient/Controller/Settings.php index c564e9db..2e78e9f5 100644 --- a/src/AnimeClient/Controller/Settings.php +++ b/src/AnimeClient/Controller/Settings.php @@ -84,7 +84,7 @@ final class Settings extends BaseController { */ public function update(): void { - $post = $this->request->getParsedBody(); + $post = (array)$this->request->getParsedBody(); unset($post['settings-tabs']); $saved = $this->settingsModel->saveSettingsFile($post); @@ -93,7 +93,10 @@ final class Settings extends BaseController { ? $this->setFlashMessage('Saved config settings.', 'success') : $this->setFlashMessage('Failed to save config file.', 'error'); - $this->redirect($this->url->generate('settings'), 303); + $redirectUrl = $this->url->generate('settings'); + $redirectUrl = ($redirectUrl !== FALSE) ? $redirectUrl : ''; + + $this->redirect($redirectUrl, 303); } /** @@ -152,6 +155,9 @@ final class Settings extends BaseController { ? $this->setFlashMessage('Linked Anilist Account', 'success') : $this->setFlashMessage('Error Linking Anilist Account', 'error'); - $this->redirect($this->url->generate('settings'), 303); + $redirectUrl = $this->url->generate('settings'); + $redirectUrl = ($redirectUrl !== FALSE) ? $redirectUrl : ''; + + $this->redirect($redirectUrl, 303); } } \ No newline at end of file diff --git a/src/AnimeClient/Dispatcher.php b/src/AnimeClient/Dispatcher.php index 6a6d53f3..0be584fb 100644 --- a/src/AnimeClient/Dispatcher.php +++ b/src/AnimeClient/Dispatcher.php @@ -16,19 +16,23 @@ namespace Aviat\AnimeClient; -use Aviat\AnimeClient\Enum\EventType; -use function Aviat\Ion\_dir; - -use Aura\Router\{Map, Matcher, Route, Rule}; - +use Aviat\Ion\Json; +use Aura\Router\{ + Map, + Matcher, + Route, + Rule, +}; use Aviat\AnimeClient\API\FailedResponseException; use Aviat\Ion\Di\ContainerInterface; -use Aviat\Ion\Event; use Aviat\Ion\Friend; use Aviat\Ion\Type\StringType; +use JetBrains\PhpStorm\ArrayShape; use LogicException; use ReflectionException; +use function Aviat\Ion\_dir; + /** * Basic routing/ dispatch */ @@ -78,7 +82,7 @@ final class Dispatcher extends RoutingBase { * * @return Route|false */ - public function getRoute() + public function getRoute(): Route | false { $logger = $this->container->getLogger(); @@ -132,7 +136,7 @@ final class Dispatcher extends RoutingBase { { // If not route was matched, return an appropriate http // error message - $errorRoute = $this->getErrorParams(); + $errorRoute = (array)$this->getErrorParams(); $controllerName = DEFAULT_CONTROLLER; $actionMethod = $errorRoute['action_method']; $params = $errorRoute['params']; @@ -152,11 +156,11 @@ final class Dispatcher extends RoutingBase { * Parse out the arguments for the appropriate controller for * the current route * - * @param Route $route + * @param Friend $route * @throws LogicException * @return array */ - protected function processRoute($route): array + protected function processRoute(Friend $route): array { if ( ! array_key_exists('controller', $route->attributes)) { @@ -166,7 +170,7 @@ final class Dispatcher extends RoutingBase { $controllerName = $route->attributes['controller']; // Get the full namespace for a controller if a short name is given - if (strpos($controllerName, '\\') === FALSE) + if ( ! str_contains($controllerName, '\\')) { $map = $this->getControllerList(); $controllerName = $map[$controllerName]; @@ -191,7 +195,7 @@ final class Dispatcher extends RoutingBase { $logger = $this->container->getLogger(); if ($logger !== NULL) { - $logger->info(json_encode($params)); + $logger->info(Json::encode($params)); } return [ @@ -244,6 +248,10 @@ final class Dispatcher extends RoutingBase { $path = trim($path, '/'); $actualPath = realpath(_dir(SRC_DIR, $path)); $classFiles = glob("{$actualPath}/*.php"); + if ($classFiles === FALSE) + { + return []; + } $controllers = []; @@ -282,9 +290,10 @@ final class Dispatcher extends RoutingBase { $logger->debug('Dispatcher - controller arguments', $params); } - call_user_func_array([$controller, $method], array_values($params)); + $params = array_values($params); + $controller->$method(...$params); } - catch (FailedResponseException $e) + catch (FailedResponseException) { $controllerName = DEFAULT_CONTROLLER; $controller = new $controllerName($this->container); diff --git a/src/AnimeClient/FormGenerator.php b/src/AnimeClient/FormGenerator.php index c0a50ce3..a659e119 100644 --- a/src/AnimeClient/FormGenerator.php +++ b/src/AnimeClient/FormGenerator.php @@ -48,7 +48,7 @@ final class FormGenerator { * Create a new FormGenerator * * @param ContainerInterface $container - * @return $this + * @return self */ public static function new(ContainerInterface $container): self { diff --git a/src/AnimeClient/MenuGenerator.php b/src/AnimeClient/MenuGenerator.php index d8dfd23d..98e27f72 100644 --- a/src/AnimeClient/MenuGenerator.php +++ b/src/AnimeClient/MenuGenerator.php @@ -22,7 +22,7 @@ use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Exception\ConfigException; use Aviat\Ion\Type\ArrayType; use Aviat\Ion\Type\StringType; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; /** * Helper object to manage menu creation and selection @@ -39,9 +39,9 @@ final class MenuGenerator extends UrlGenerator { /** * Request object * - * @var RequestInterface + * @var ServerRequestInterface */ - protected RequestInterface $request; + protected ServerRequestInterface $request; /** * @param ContainerInterface $container diff --git a/src/AnimeClient/Model/MediaTrait.php b/src/AnimeClient/Model/MediaTrait.php index aac8fabe..a844115c 100644 --- a/src/AnimeClient/Model/MediaTrait.php +++ b/src/AnimeClient/Model/MediaTrait.php @@ -85,7 +85,7 @@ trait MediaTrait { * @param string $itemId * @return AnimeListItem|MangaListItem */ - public function getLibraryItem(string $itemId) + public function getLibraryItem(string $itemId): AnimeListItem|MangaListItem { return $this->kitsuModel->getListItem($itemId); } diff --git a/src/AnimeClient/RoutingBase.php b/src/AnimeClient/RoutingBase.php index 1d91fd6d..e4cd80f7 100644 --- a/src/AnimeClient/RoutingBase.php +++ b/src/AnimeClient/RoutingBase.php @@ -22,7 +22,7 @@ use Aviat\Ion\Di\Exception\ContainerException; use Aviat\Ion\Di\Exception\NotFoundException; use Aviat\Ion\Exception\ConfigException; use Aviat\Ion\Type\StringType; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; /** * Base for routing/url classes @@ -43,9 +43,9 @@ class RoutingBase { /** * Class wrapper for input superglobals - * @var RequestInterface + * @var ServerRequestInterface */ - protected RequestInterface $request; + protected ServerRequestInterface $request; /** * Constructor @@ -64,8 +64,7 @@ class RoutingBase { /** * Get the current url path - * @throws ContainerException - * @throws NotFoundException + * * @return string */ public function path(): string @@ -82,8 +81,7 @@ class RoutingBase { /** * Get the url segments - * @throws ContainerException - * @throws NotFoundException + * * @return array */ public function segments(): array @@ -96,11 +94,10 @@ class RoutingBase { * Get a segment of the current url * * @param int $num - * @throws ContainerException - * @throws NotFoundException + * * @return string|null */ - public function getSegment($num): ?string + public function getSegment(int $num): ?string { $segments = $this->segments(); return $segments[$num] ?? NULL; @@ -109,8 +106,6 @@ class RoutingBase { /** * Retrieve the last url segment * - * @throws ContainerException - * @throws NotFoundException * @return string */ public function lastSegment(): string diff --git a/src/Ion/HttpViewInterface.php b/src/Ion/HttpViewInterface.php new file mode 100644 index 00000000..e817b3c7 --- /dev/null +++ b/src/Ion/HttpViewInterface.php @@ -0,0 +1,32 @@ + + * @copyright 2015 - 2021 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 5.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +/** + * View Interface abstracting an HTTP Response + */ +interface HttpViewInterface extends ViewInterface { + + /** + * Set the status code of the request + * + * @param int $code + * @throws \InvalidArgumentException + * @return self + */ + public function setStatusCode(int $code): self; +} \ No newline at end of file diff --git a/src/Ion/View/HtmlView.php b/src/Ion/View/HtmlView.php index bfd1eb05..541089a1 100644 --- a/src/Ion/View/HtmlView.php +++ b/src/Ion/View/HtmlView.php @@ -18,8 +18,6 @@ namespace Aviat\Ion\View; use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Di\ContainerInterface; -use Aviat\Ion\Di\Exception\ContainerException; -use Aviat\Ion\Di\Exception\NotFoundException; use Laminas\Diactoros\Response\HtmlResponse; use const EXTR_OVERWRITE; @@ -40,8 +38,6 @@ class HtmlView extends HttpView { * Create the Html View * * @param ContainerInterface $container - * @throws ContainerException - * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -57,6 +53,7 @@ class HtmlView extends HttpView { * @param string $path * @param array $data * @return string + * @throws \Throwable */ public function renderTemplate(string $path, array $data): string { @@ -74,9 +71,7 @@ class HtmlView extends HttpView { // Very basic html minify, that won't affect content between html tags - $buffer = preg_replace('/>\s+ <', $buffer); - - return $buffer; + return preg_replace('/>\s+ <', $buffer); } } // End of HtmlView.php \ No newline at end of file diff --git a/src/Ion/View/HttpView.php b/src/Ion/View/HttpView.php index dd683a3b..c0b65913 100644 --- a/src/Ion/View/HttpView.php +++ b/src/Ion/View/HttpView.php @@ -16,7 +16,7 @@ namespace Aviat\Ion\View; -use Aviat\Ion\ViewInterface; +use Aviat\Ion\HttpViewInterface; use Laminas\Diactoros\Response; use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; @@ -26,7 +26,7 @@ use Psr\Http\Message\ResponseInterface; /** * Base view class for Http output */ -class HttpView implements ViewInterface{ +class HttpView implements HttpViewInterface{ /** * HTTP response Object @@ -103,9 +103,9 @@ class HttpView implements ViewInterface{ * Set the output string * * @param mixed $string - * @return ViewInterface + * @return HttpViewInterface */ - public function setOutput($string): ViewInterface + public function setOutput($string): HttpViewInterface { $this->response->getBody()->write($string); @@ -117,9 +117,9 @@ class HttpView implements ViewInterface{ * Append additional output. * * @param string $string - * @return ViewInterface + * @return HttpViewInterface */ - public function appendOutput(string $string): ViewInterface + public function appendOutput(string $string): HttpViewInterface { return $this->setOutput($string); } diff --git a/src/Ion/View/JsonView.php b/src/Ion/View/JsonView.php index 09856d47..470076d4 100644 --- a/src/Ion/View/JsonView.php +++ b/src/Ion/View/JsonView.php @@ -17,7 +17,7 @@ namespace Aviat\Ion\View; use Aviat\Ion\Json; -use Aviat\Ion\ViewInterface; +use Aviat\Ion\HttpViewInterface; /** * View class to serialize Json @@ -35,9 +35,9 @@ class JsonView extends HttpView { * Set the output string * * @param mixed $string - * @return ViewInterface + * @return HttpViewInterface */ - public function setOutput($string): ViewInterface + public function setOutput(mixed $string): HttpViewInterface { if ( ! is_string($string)) {