diff --git a/.gitignore b/.gitignore index 46eb891b..cab47bdd 100644 --- a/.gitignore +++ b/.gitignore @@ -145,4 +145,5 @@ public/images/avatars/** public/images/manga/** public/images/characters/** public/images/people/** -public/mal_mappings.json \ No newline at end of file +public/mal_mappings.json +.phpunit.result.cache \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 391585d3..62f82e2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,23 +4,21 @@ install: - composer install --ignore-platform-reqs php: - - 7.1 - - 7.2 - 7.3 + - 7.4 - nightly script: - mkdir -p build/logs - - phpdbg -qrr -- vendor/bin/phpunit -c build + - php vendor/bin/phpunit -c build -after_script: - - CODECLIMATE_REPO_TOKEN=2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 vendor/bin/test-reporter +#after_script: +# - CODECLIMATE_REPO_TOKEN=2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 vendor/bin/test-reporter matrix: allow_failures: - php: nightly - - php: hhvm -addons: - code_climate: - repo_token: 2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 \ No newline at end of file +#addons: +# code_climate: +# repo_token: 2cbddcebcb9256b3402867282e119dbe61de0b31039325356af3c7d72ed6d058 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3583d3e3..e18a7bc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,18 @@ # Changelog +## Version 4.2 +* Updated dependencies +* Updated PHP requirement to 7.3 + ## Version 4.1 +* Added optional dark theme * Removed MAL integration, added Anilist Integration * Now uses WebP cache images when the browser supports it * Replaces JS minifier with pre-minified scripts (Removes the need for one caching folder, too) * Updated console command to sync Kitsu and Anilist data (Kitsu can sync MAL, and MAL's API broke, so MAL sync was removed) * Added page to update settings without having to edit config files * Defaulted to secure (HTTPS) urls -* Updated Character pages to show voice actors +* Updated Character pages to show voice actors * Added People pages, showing which works they contributed to, and in what role ## Version 4 @@ -15,7 +20,7 @@ * Added streaming links to list entries from the Kitsu API * Added simple integration with MyAnimeList, so an update can cross-post to both Kitsu and MyAnimeList (anime and manga) * Added console command to sync Kitsu and MyAnimeList data -* Added character pages +* Added character pages ## Version 3 * Converted user configuration to toml files diff --git a/Jenkinsfile b/Jenkinsfile index 11dc7110..7fb02a70 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,37 +1,14 @@ pipeline { agent none stages { - stage('PHP 7.1') { - agent { - docker { - image 'php:7.1-alpine' - args '-u root --privileged' - } - } - steps { - sh 'chmod +x ./build/docker_install.sh' - sh 'sh build/docker_install.sh' - sh 'apk add --no-cache php7-phpdbg' - sh 'curl -sS https://getcomposer.org/installer | php' - sh 'php composer.phar install --ignore-platform-reqs' - sh 'phpdbg -qrr -- ./vendor/bin/phpunit --coverage-text --colors=never' - } - } - stage('PHP 7.2') { - agent { - docker { - image 'php:7.2-alpine' - args '-u root --privileged' - } - } - steps { - sh 'chmod +x ./build/docker_install.sh' - sh 'sh build/docker_install.sh' - sh 'apk add --no-cache php7-phpdbg' - sh 'curl -sS https://getcomposer.org/installer | php' - sh 'php composer.phar install --ignore-platform-reqs' - sh 'phpdbg -qrr -- ./vendor/bin/phpunit --coverage-text --colors=never' - } + stage('setup') { + agent any + steps { + sh 'curl -sS https://getcomposer.org/installer | php' + sh 'rm -rf ./vendor' + sh 'rm -f composer.lock' + sh 'php composer.phar install --ignore-platform-reqs' + } } stage('PHP 7.3') { agent { @@ -41,12 +18,43 @@ pipeline { } } steps { - sh 'chmod +x ./build/docker_install.sh' - sh 'sh build/docker_install.sh' - sh 'apk add --no-cache php7-phpdbg' - sh 'curl -sS https://getcomposer.org/installer | php' - sh 'php composer.phar install --ignore-platform-reqs' - sh 'phpdbg -qrr -- ./vendor/bin/phpunit --coverage-text --colors=never' + sh 'apk add --no-cache git' + sh 'php ./vendor/bin/phpunit --colors=never' + } + } + stage('PHP 7.4') { + agent { + docker { + image 'php:7.4-alpine' + args '-u root --privileged' + } + } + steps { + sh 'apk add --no-cache git' + sh 'php ./vendor/bin/phpunit --colors=never' + } + } + stage('Latest PHP') { + agent { + docker { + image 'php:alpine' + args '-u root --privileged' + } + } + steps { + sh 'apk add --no-cache git' + sh 'php ./vendor/bin/phpunit --colors=never' + } + } + stage('Coverage') { + agent any + steps { + sh 'php composer.phar run-script coverage' + step([ + $class: 'CloverPublisher', + cloverReportDir: '', + cloverReportFileName: 'build/logs/clover.xml', + ]) } } } diff --git a/README.md b/README.md index a70a6cd8..a43e5faa 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Update your anime/manga list on Kitsu.io and MyAnimeList.net [![Build Status](https://travis-ci.org/timw4mail/HummingBirdAnimeClient.svg?branch=master)](https://travis-ci.org/timw4mail/HummingBirdAnimeClient) -[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=aviat/HummingBirdAnimeClient/develop)](https://jenkins.timshomepage.net/job/aviat/HummingBirdAnimeClient/develop) +[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=timw4mail/HummingBirdAnimeClient/develop)](https://jenkins.timshomepage.net/job/timw4mail/HummingBirdAnimeClient/develop) [[Hosted Example](https://list.timshomepage.net)] @@ -31,7 +31,7 @@ Update your anime/manga list on Kitsu.io and MyAnimeList.net ### Requirements -* PHP 7.1+ +* PHP 7.3+ * PDO SQLite or PDO PostgreSQL (For collection tab) * GD extension for caching images diff --git a/RoboFile.php b/RoboFile.php index 3e2140c3..bb2958ef 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -1,5 +1,5 @@ prepare(); $this->lint(); $this->phploc(TRUE); $this->phpcs(TRUE); + $this->phpmd(TRUE); $this->dependencyReport(); $this->phpcpdReport(); } @@ -67,7 +68,7 @@ class RoboFile extends Tasks { /** * Run all tests, generate coverage, generate docs, generate code statistics */ - public function build() + public function build(): void { $this->analyze(); $this->coverage(); @@ -77,19 +78,19 @@ class RoboFile extends Tasks { /** * Cleanup temporary files */ - public function clean() + public function clean(): void { $cleanFiles = [ 'build/humbug.json', 'build/humbug-log.txt', ]; - array_map(function ($file) { + array_map(static function ($file) { @unlink($file); }, $cleanFiles); // So the task doesn't complain, // make any 'missing' dirs to cleanup - array_map(function ($dir) { + array_map(static function ($dir) { if ( ! is_dir($dir)) { `mkdir -p {$dir}`; @@ -103,7 +104,7 @@ class RoboFile extends Tasks { /** * Run unit tests and generate coverage reports */ - public function coverage() + public function coverage(): void { $this->_run(['phpdbg -qrr -- vendor/bin/phpunit -c build']); } @@ -111,7 +112,7 @@ class RoboFile extends Tasks { /** * Generate documentation with phpdox */ - public function docs() + public function docs(): void { $cmd_parts = [ 'vendor/bin/phpdox', @@ -122,11 +123,11 @@ class RoboFile extends Tasks { /** * Verify that source files are valid */ - public function lint() + public function lint(): void { $files = $this->getAllSourceFiles(); - $chunks = array_chunk($files, 12); + $chunks = array_chunk($files, (int)shell_exec('getconf _NPROCESSORS_ONLN')); foreach($chunks as $chunk) { @@ -139,7 +140,7 @@ class RoboFile extends Tasks { * * @param bool $report - if true, generates reports instead of direct output */ - public function phpcs($report = FALSE) + public function phpcs($report = FALSE): void { $report_cmd_parts = [ 'vendor/bin/phpcs', @@ -157,12 +158,36 @@ class RoboFile extends Tasks { $this->_run($cmd_parts); } + public function phpmd($report = FALSE): void + { + $report_cmd_parts = [ + 'vendor/bin/phpmd', + './src', + 'xml', + 'cleancode,codesize,controversial,design,naming,unusedcode', + '--exclude ParallelAPIRequest', + '--reportfile ./build/logs/phpmd.xml' + ]; + + $normal_cmd_parts = [ + 'vendor/bin/phpmd', + './src', + 'ansi', + 'cleancode,codesize,controversial,design,naming,unusedcode', + '--exclude ParallelAPIRequest' + ]; + + $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts; + + $this->_run($cmd_parts); + } + /** * Run the phploc tool * * @param bool $report - if true, generates reports instead of direct output */ - public function phploc($report = FALSE) + public function phploc($report = FALSE): void { // Command for generating reports $report_cmd_parts = [ @@ -190,7 +215,7 @@ class RoboFile extends Tasks { /** * Create temporary directories */ - public function prepare() + public function prepare(): void { array_map([$this, '_mkdir'], $this->taskDirs); } @@ -198,35 +223,17 @@ class RoboFile extends Tasks { /** * Lint php files and run unit tests */ - public function test() + public function test(): void { $this->lint(); - - $this->_run(['phpunit']); - } - /** - * Watches for file updates, and automatically runs appropriate actions - */ - public function watch() - { - $this->taskWatch() - ->monitor('composer.json', function() { - $this->taskComposerUpdate()->run(); - }) - ->monitor('src', function () { - $this->taskExec('test')->run(); - }) - ->monitor('tests', function () { - $this->taskExec('test')->run(); - }) - ->run(); + $this->_run(['phpunit']); } /** * Create pdepend reports */ - protected function dependencyReport() + protected function dependencyReport(): void { $cmd_parts = [ 'vendor/bin/pdepend', @@ -243,7 +250,7 @@ class RoboFile extends Tasks { * * @return array */ - protected function getAllSourceFiles() + protected function getAllSourceFiles(): array { $files = array_merge( glob_recursive('build/*.php'), @@ -254,6 +261,10 @@ class RoboFile extends Tasks { glob('*.php') ); + $files = array_filter($files, static function(string $value) { + return strpos($value, '__snapshots__') === FALSE; + }); + sort($files); return $files; @@ -264,7 +275,7 @@ class RoboFile extends Tasks { * * @param array $chunk */ - protected function parallelLint(array $chunk) + protected function parallelLint(array $chunk): void { $task = $this->taskParallelExec() ->timeout(5) @@ -281,7 +292,7 @@ class RoboFile extends Tasks { /** * Generate copy paste detector report */ - protected function phpcpdReport() + protected function phpcpdReport(): void { $cmd_parts = [ 'vendor/bin/phpcpd', @@ -298,7 +309,7 @@ class RoboFile extends Tasks { * @param array $cmd_parts - command arguments * @param string $join_on - what to join the command arguments with */ - protected function _run(array $cmd_parts, $join_on = ' ') + protected function _run(array $cmd_parts, $join_on = ' '): void { $this->taskExec(implode($join_on, $cmd_parts))->run(); } diff --git a/app/bootstrap.php b/app/bootstrap.php index ef9a0d57..f7638021 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -44,10 +44,13 @@ return static function ($configArray = []) { $appLogger = new Logger('animeclient'); $appLogger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/app.log', Logger::NOTICE)); + $anilistRequestLogger = new Logger('anilist-request'); $anilistRequestLogger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/anilist_request.log', Logger::NOTICE)); + $kitsuRequestLogger = new Logger('kitsu-request'); $kitsuRequestLogger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/kitsu_request.log', Logger::NOTICE)); + $container->setLogger($appLogger); $container->setLogger($anilistRequestLogger, 'anilist-request'); $container->setLogger($kitsuRequestLogger, 'kitsu-request'); @@ -62,7 +65,7 @@ return static function ($configArray = []) { }); // Create Cache Object - $container->set('cache', static function($container) { + $container->set('cache', static function($container): Pool { $logger = $container->getLogger(); $config = $container->get('config')->get('cache'); return new Pool($config, $logger); @@ -117,12 +120,12 @@ return static function ($configArray = []) { }); // Miscellaneous helper methods - $container->set('util', static function($container) { + $container->set('util', static function($container): Util { return new Util($container); }); // Models - $container->set('kitsu-model', static function($container) { + $container->set('kitsu-model', static function($container): Kitsu\Model { $requestBuilder = new KitsuRequestBuilder(); $requestBuilder->setLogger($container->getLogger('kitsu-request')); @@ -138,7 +141,7 @@ return static function ($configArray = []) { $model->setCache($cache); return $model; }); - $container->set('anilist-model', static function($container) { + $container->set('anilist-model', static function($container): Anilist\Model { $requestBuilder = new Anilist\AnilistRequestBuilder(); $requestBuilder->setLogger($container->getLogger('anilist-request')); @@ -153,9 +156,6 @@ return static function ($configArray = []) { return $model; }); - $container->set('api-model', static function($container) { - return new Model\API($container); - }); $container->set('anime-model', static function($container) { return new Model\Anime($container); }); diff --git a/app/views/anime/cover-item.php b/app/views/anime/cover-item.php index 92b2e559..d63d937e 100644 --- a/app/views/anime/cover-item.php +++ b/app/views/anime/cover-item.php @@ -9,7 +9,7 @@ picture("images/anime/{$item['anime']['id']}.webp") ?>
- +
diff --git a/app/views/setup-check.php b/app/views/setup-check.php index c22e5b0e..478d6faf 100644 --- a/app/views/setup-check.php +++ b/app/views/setup-check.php @@ -1,5 +1,8 @@ -get('config')); +get('config')); ?> diff --git a/build/CodeIgniter/Sniffs/Commenting/InlineCommentSniff.php b/build/CodeIgniter/Sniffs/Commenting/InlineCommentSniff.php index d8e51eb9..9fb43b0e 100644 --- a/build/CodeIgniter/Sniffs/Commenting/InlineCommentSniff.php +++ b/build/CodeIgniter/Sniffs/Commenting/InlineCommentSniff.php @@ -93,12 +93,12 @@ class InlineCommentSniff implements Sniff private function _checkCommentStyle(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); - if ($tokens[$stackPtr]['content']{0} === '#') { + if ($tokens[$stackPtr]['content'][0] === '#') { $error = 'Perl-style comments are not allowed; use "// Comment" or DocBlock comments instead'; $phpcsFile->addError($error, $stackPtr, 'WrongStyle'); return FALSE; } else if (substr($tokens[$stackPtr]['content'], 0, 2) === '/*' - || $tokens[$stackPtr]['content']{0} === '*' + || $tokens[$stackPtr]['content'][0] === '*' ) { $error = 'Multi lines comments are not allowed; use "// Comment" DocBlock comments instead'; $phpcsFile->addError($error, $stackPtr, 'WrongStyle'); diff --git a/build/CodeIgniter/Sniffs/Operators/LogicalOperatorAndSniff.php b/build/CodeIgniter/Sniffs/Operators/LogicalOperatorAndSniff.php deleted file mode 100644 index d7af22aa..00000000 --- a/build/CodeIgniter/Sniffs/Operators/LogicalOperatorAndSniff.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @copyright 2006 Thomas Ernest - * @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License - * @link http://pear.php.net/package/PHP_CodeSniffer - */ - -/** - * CodeIgniter_Sniffs_Operators_LogicalOperatorAndSniff. - * - * Ensures that the logical operator 'AND' is in upper case and suggest the use of its symbolic equivalent. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Thomas Ernest - * @copyright 2006 Thomas Ernest - * @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License - * @link http://pear.php.net/package/PHP_CodeSniffer - */ - -namespace CodeIgniter\Sniffs\Operators; - -use PHP_CodeSniffer\Sniffs\Sniff; -use PHP_CodeSniffer\Files\File; - -class LogicalOperatorAndSniff implements Sniff -{ - /** - * Returns an array of tokens this test wants to listen for: symbolic and literal operators and. - * - * @return array - */ - public function register() - { - return array( - T_LOGICAL_AND, - ); - - }//end register() - - - /** - * Processes this test, when one of its tokens is encountered. - * - * @param File $phpcsFile The current file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @return void - */ - public function process(File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); - - $operator_token = $tokens[$stackPtr]; - $operator_string = $operator_token['content']; - $operator_code = $operator_token['code']; - - if ($operator_string !== strtoupper($operator_string)) { - $error_message = 'Logical operator should be in upper case;' - . ' use "' . strtoupper($operator_string) - . '" instead of "' . $operator_string . '"'; - $phpcsFile->addError($error_message, $stackPtr, 'LowercaseLogicalOperator'); - } - - $warning_message = 'The symbolic form "&&" is preferred over the literal form "AND"'; - $phpcsFile->addWarning($warning_message, $stackPtr, 'UseOfLiteralAndOperator'); - - }//end process() - - -}//end class - -?> \ No newline at end of file diff --git a/build/CodeIgniter/Sniffs/Operators/UppercaseLogicalOperatorOrSniff.php b/build/CodeIgniter/Sniffs/Operators/UppercaseLogicalOperatorOrSniff.php deleted file mode 100644 index cda26c01..00000000 --- a/build/CodeIgniter/Sniffs/Operators/UppercaseLogicalOperatorOrSniff.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @copyright 2006 Thomas Ernest - * @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License - * @link http://pear.php.net/package/PHP_CodeSniffer - */ - -/** - * CodeIgniter_Sniffs_Operators_UppercaseLogicalOperatorOrSniff. - * - * Ensures that the logical operator 'OR' is in upper cases and its symbolic equivalent. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Thomas Ernest - * @copyright 2006 Thomas Ernest - * @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License - * @link http://pear.php.net/package/PHP_CodeSniffer - */ - -namespace CodeIgniter\Sniffs\Operators; - -use PHP_CodeSniffer\Sniffs\Sniff; -use PHP_CodeSniffer\Files\File; - -class UppercaseLogicalOperatorOrSniff implements Sniff -{ - /** - * Returns an array of tokens this test wants to listen for: literal and symbolic operators or. - * - * @return array - */ - public function register() - { - return array( - T_BOOLEAN_OR, - T_LOGICAL_OR, - ); - - }//end register() - - - /** - * Processes this test, when one of its tokens is encountered. - * - * @param File $phpcsFile The current file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @return void - */ - public function process(File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); - - $operator_token = $tokens[$stackPtr]; - $operator_string = $operator_token['content']; - $operator_code = $operator_token['code']; - - if ($operator_code == T_BOOLEAN_OR) { - $error_message = 'Logical operator "' . $operator_string - . '" is prohibited; use "OR" instead'; - $phpcsFile->addError($error_message, $stackPtr, 'UseOf||InsteadOfOR'); - } - // it is literal, if it is not symbolic - else if ($operator_string !== strtoupper($operator_string)) { - $error_message = 'Logical operator should be in upper case;' - . ' use "' . strtoupper($operator_string) - . '" instead of "' . $operator_string . '"'; - $phpcsFile->addError($error_message, $stackPtr, 'UseOfLowercaseOr'); - } - }//end process() - - -}//end class - -?> \ No newline at end of file diff --git a/build/CodeIgniter/ruleset.xml b/build/CodeIgniter/ruleset.xml index 83974072..43097d22 100644 --- a/build/CodeIgniter/ruleset.xml +++ b/build/CodeIgniter/ruleset.xml @@ -23,7 +23,7 @@ - + diff --git a/build/docker_install.sh b/build/docker_install.sh deleted file mode 100644 index 73163966..00000000 --- a/build/docker_install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -# We need to install dependencies only for Docker -[[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0 - -set -xe - -# Install git (the php image doesn't have it) which is required by composer -# echo -e 'http://dl-cdn.alpinelinux.org/alpine/edge/main\nhttp://dl-cdn.alpinelinux.org/alpine/edge/community\nhttp://dl-cdn.alpinelinux.org/alpine/edge/testing' > /etc/apk/repositories -apk --update add --no-cache \ - curl \ - git diff --git a/build/header_comment.txt b/build/header_comment.txt index 3f8b1752..e61c8af8 100644 --- a/build/header_comment.txt +++ b/build/header_comment.txt @@ -3,13 +3,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/build/phpunit.xml b/build/phpunit.xml index f5f4ce1e..339f7750 100644 --- a/build/phpunit.xml +++ b/build/phpunit.xml @@ -18,9 +18,6 @@ - - - diff --git a/build/update_header_comments.php b/build/update_header_comments.php index 32ec3eb5..e5bf9191 100644 --- a/build/update_header_comments.php +++ b/build/update_header_comments.php @@ -29,13 +29,13 @@ if ( ! function_exists('glob_recursive')) } } -function get_text_to_replace($tokens) +function get_text_to_replace(array $tokens): string { $output = ''; // Tokens have the follow structure if arrays: // [0] => token type constant - // [1] => raw sytax parsed to that token + // [1] => raw syntax parsed to that token // [2] => line number foreach($tokens as $token) { @@ -57,7 +57,7 @@ function get_text_to_replace($tokens) return $output; } -function get_tokens($source) +function get_tokens($source): array { return token_get_all($source); } diff --git a/composer.json b/composer.json index f94fdf6b..0e45c808 100644 --- a/composer.json +++ b/composer.json @@ -2,55 +2,75 @@ "name": "aviat/hummingbird-anime-client", "description": "A self-hosted anime/manga client for Kitsu.", "license": "MIT", + "authors": [ + { + "name": "Timothy J. Warren", + "email": "tim@timshomepage.net", + "homepage": "https://timshomepage.net", + "role": "Developer" + } + ], "autoload": { "files": [ - "src/constants.php", - "src/AnimeClient.php" + "src/Ion/functions.php", + "src/AnimeClient/constants.php", + "src/AnimeClient/AnimeClient.php" ], "psr-4": { - "Aviat\\AnimeClient\\": "src/" + "Aviat\\": "src/" } }, "autoload-dev": { "psr-4": { - "Aviat\\AnimeClient\\Tests\\": "tests/", + "Aviat\\AnimeClient\\Tests\\": "tests/AnimeClient", + "Aviat\\Ion\\Tests\\": "tests/Ion", "CodeIgniter\\": "build/CodeIgniter/" } }, + "config": { + "lock": false, + "platform": { + "php": "7.3" + } + }, "require": { - "amphp/artax": "^3.0", + "amphp/http-client": "^4.2", "aura/html": "^2.0", "aura/router": "^3.0", "aura/session": "^2.0", "aviat/banker": "^2.0.0", - "aviat/ion": "^2.4.1", + "aviat/query": "^2.5.1", + "danielstjules/stringy": "^3.1.0", + "ext-dom": "*", "ext-iconv": "*", "ext-json": "*", - "ext-gd":"*", + "ext-gd": "*", "ext-pdo": "*", + "laminas/laminas-diactoros": "^2.0.0", + "laminas/laminas-httphandlerrunner": "^1.0", "maximebf/consolekit": "^1.0", - "monolog/monolog": "^1.0", + "monolog/monolog": "^2.0.1", + "php": "^7.3", + "psr/container": "~1.0", "psr/http-message": "~1.0", "psr/log": "~1.0", - "yosymfony/toml": "^1.0", - "zendframework/zend-diactoros": "^2.0.0" + "yosymfony/toml": "^1.0" }, "require-dev": { - "consolidation/robo": "~1.0", + "consolidation/robo": "^2.0.0", "filp/whoops": "^2.1", - "henrikbjorn/lurker": "^1.1.0", "pdepend/pdepend": "^2.2", - "phploc/phploc": "^4.0", - "phpmd/phpmd": "^2.4", - "phpstan/phpstan": "^0.10.5", - "phpunit/phpunit": "^7.4.3", + "phploc/phploc": "^5.0", + "phpmd/phpmd": "^2.8", + "phpstan/phpstan": "^0.12.0", + "phpunit/phpunit": "^8.4.3", "roave/security-advisories": "dev-master", "robmorgan/phinx": "^0.10.6", "sebastian/phpcpd": "^4.1.0", - "spatie/phpunit-snapshot-assertions": "^1.2.0", + "spatie/phpunit-snapshot-assertions": "^2.2.1", "squizlabs/php_codesniffer": "^3.2.2", - "symfony/var-dumper": "^4.0.1", - "theseer/phpdox": "*" + "symfony/var-dumper": "^5", + "theseer/phpdox": "*" }, "scripts": { "build": "vendor/bin/robo build", @@ -58,10 +78,11 @@ "build:js": "cd public && npm run build:js && cd ..", "clean": "vendor/bin/robo clean", "coverage": "phpdbg -qrr -- vendor/bin/phpunit -c build", - "phpstan": "phpstan analyse -l 4 -c phpstan.neon src tests ./console index.php", + "phpstan": "phpstan analyse -c phpstan.neon", "watch:css": "cd public && npm run watch:css", "watch:js": "cd public && npm run watch:js", - "test": "vendor/bin/phpunit" + "test": "vendor/bin/phpunit -c build --no-coverage", + "test-update": "vendor/bin/phpunit -c build --no-coverage -d --update-snapshots" }, "scripts-descriptions": { "build": "Generate the api docs", diff --git a/index.php b/index.php index f122dcfd..cef4c453 100644 --- a/index.php +++ b/index.php @@ -4,19 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; use Aviat\AnimeClient\Types\Config as ConfigType; +use Whoops\Handler\PrettyPageHandler; +use Whoops\Run; use function Aviat\Ion\_dir; @@ -34,8 +36,8 @@ require_once __DIR__ . '/vendor/autoload.php'; // if (array_key_exists('ENV', $_ENV) && $_ENV['ENV'] === 'development') { - $whoops = new \Whoops\Run; - $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler); + $whoops = new Run; + $whoops->pushHandler(new PrettyPageHandler); $whoops->register(); } diff --git a/phpdox.xml b/phpdox.xml index 9b64cbd1..69ace8bb 100644 --- a/phpdox.xml +++ b/phpdox.xml @@ -78,10 +78,10 @@ - + @@ -89,24 +89,18 @@ - - - + + - - - - - + diff --git a/phpstan.neon b/phpstan.neon index 964eb301..7f460fb1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,9 +1,18 @@ parameters: + checkGenericClassInNonGenericObjectType: false + checkMissingIterableValueType: false + inferPrivatePropertyTypeFromConstructor: true + level: 7 autoload_files: - %rootDir%/../../../tests/mocks.php + paths: + - src + - ./console + - index.php ignoreErrors: - '#Access to an undefined property Aviat\\\Ion\\\Friend::\$[a-zA-Z0-9_]+#' - '#Call to an undefined method Aviat\\\Ion\\\Friend::[a-zA-Z0-9_]+\(\)#' - '#Call to an undefined method Aura\\\Html\\\HelperLocator::[a-zA-Z0-9_]+\(\)#' - - '#Undefined variable: \$var#' - '#Property Amp\\Artax\\Internal\\RequestCycle::\$[a-zA-Z0-9_]+#' + excludes_analyse: + - tests/mocks.php \ No newline at end of file diff --git a/src/API/APIRequestBuilder.php b/src/AnimeClient/API/APIRequestBuilder.php similarity index 88% rename from src/API/APIRequestBuilder.php rename to src/AnimeClient/API/APIRequestBuilder.php index 42dd350b..5639f8cb 100644 --- a/src/API/APIRequestBuilder.php +++ b/src/AnimeClient/API/APIRequestBuilder.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -22,15 +22,16 @@ use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; use Amp; -use Amp\Artax\{FormBody, Request}; +use Amp\Http\Client\Request; +use Amp\Http\Client\Body\FormBody; use Aviat\Ion\Json; use InvalidArgumentException; use Psr\Log\LoggerAwareTrait; /** - * Wrapper around Artax to make it easier to build API requests + * Wrapper around Http\Client to make it easier to build API requests */ -class APIRequestBuilder { +abstract class APIRequestBuilder { use LoggerAwareTrait; /** @@ -65,7 +66,7 @@ class APIRequestBuilder { /** * The current request - * @var \Amp\Artax\Request + * @var Request */ protected $request; @@ -78,7 +79,7 @@ class APIRequestBuilder { public static function simpleRequest(string $uri): Request { return (new Request($uri)) - ->withHeader('User-Agent', USER_AGENT); + ->setHeader('User-Agent', USER_AGENT); } /** @@ -118,7 +119,7 @@ class APIRequestBuilder { */ public function setBody($body): self { - $this->request = $this->request->withBody($body); + $this->request->setBody($body); return $this; } @@ -145,7 +146,7 @@ class APIRequestBuilder { */ public function unsetHeader(string $name): self { - $this->request = $this->request->withoutHeader($name); + $this->request->removeHeader($name); return $this; } @@ -164,7 +165,7 @@ class APIRequestBuilder { } else { - $this->request = $this->request->withHeader($name, $value); + $this->request->setHeader($name, $value); } return $this; @@ -219,14 +220,14 @@ class APIRequestBuilder { /** * Return the promise for the current request * + * @return Request * @throws \Throwable - * @return \Amp\Artax\Request */ public function getFullRequest(): Request { $this->buildUri(); - if ($this->logger) + if ($this->logger !== NULL) { $this->logger->debug('API Request', [ 'request_url' => $this->request->getUri(), @@ -254,7 +255,7 @@ class APIRequestBuilder { public function getResponseData(Request $request) { $response = getResponse($request); - return wait($response->getBody()); + return wait($response->getBody()->buffer()); } /** @@ -306,7 +307,7 @@ class APIRequestBuilder { $url .= '?' . $this->query; } - $this->request = $this->request->withUri($url); + $this->request->setUri($url); return $this->request; } @@ -324,7 +325,8 @@ class APIRequestBuilder { $this->path = ''; $this->query = ''; - $this->request = (new Request($requestUrl)) - ->withMethod($type); + $this->request = new Request($requestUrl, $type); + $this->request->setTcpConnectTimeout(300000); + $this->request->setTransferTimeout(300000); } } \ No newline at end of file diff --git a/src/API/ListItemInterface.php b/src/AnimeClient/API/AbstractListItem.php similarity index 71% rename from src/API/ListItemInterface.php rename to src/AnimeClient/API/AbstractListItem.php index 310b273b..3ff1a8af 100644 --- a/src/API/ListItemInterface.php +++ b/src/AnimeClient/API/AbstractListItem.php @@ -4,25 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\API; -use Amp\Artax\Request; +use Amp\Http\Client\Request; use Aviat\AnimeClient\Types\FormItemData; /** * Common interface for anime and manga list item CRUD */ -interface ListItemInterface { +abstract class AbstractListItem { /** * Create a list item @@ -30,7 +30,7 @@ interface ListItemInterface { * @param array $data - * @return Request */ - public function create(array $data): Request; + abstract public function create(array $data): Request; /** * Retrieve a list item @@ -38,7 +38,7 @@ interface ListItemInterface { * @param string $id - The id of the list item * @return array */ - public function get(string $id): array; + abstract public function get(string $id): array; /** * Increase progress on a list item @@ -47,7 +47,7 @@ interface ListItemInterface { * @param FormItemData $data * @return Request */ - public function increment(string $id, FormItemData $data): Request; + abstract public function increment(string $id, FormItemData $data): Request; /** * Update a list item @@ -56,7 +56,7 @@ interface ListItemInterface { * @param FormItemData $data - The data with which to update the list item * @return Request */ - public function update(string $id, FormItemData $data): Request; + abstract public function update(string $id, FormItemData $data): Request; /** * Delete a list item @@ -64,5 +64,5 @@ interface ListItemInterface { * @param string $id - The id of the list item to delete * @return Request */ - public function delete(string $id): Request; + abstract public function delete(string $id):?Request; } \ No newline at end of file diff --git a/src/API/Anilist.php b/src/AnimeClient/API/Anilist.php similarity index 97% rename from src/API/Anilist.php rename to src/AnimeClient/API/Anilist.php index bd225a60..86857ec2 100644 --- a/src/API/Anilist.php +++ b/src/AnimeClient/API/Anilist.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Anilist/AnilistRequestBuilder.php b/src/AnimeClient/API/Anilist/AnilistRequestBuilder.php similarity index 92% rename from src/API/Anilist/AnilistRequestBuilder.php rename to src/AnimeClient/API/Anilist/AnilistRequestBuilder.php index d80eaad0..f24d3d9b 100644 --- a/src/API/Anilist/AnilistRequestBuilder.php +++ b/src/AnimeClient/API/Anilist/AnilistRequestBuilder.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Anilist/AnilistTrait.php b/src/AnimeClient/API/Anilist/AnilistTrait.php similarity index 87% rename from src/API/Anilist/AnilistTrait.php rename to src/AnimeClient/API/Anilist/AnilistTrait.php index a8390e79..98f161ef 100644 --- a/src/API/Anilist/AnilistTrait.php +++ b/src/AnimeClient/API/Anilist/AnilistTrait.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -21,13 +21,16 @@ use const Aviat\AnimeClient\USER_AGENT; use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; -use Amp\Artax\Request; -use Amp\Artax\Response; +use Amp\Http\Client\Request; +use Amp\Http\Client\Response; use Aviat\AnimeClient\API\Anilist; use Aviat\Ion\Json; use Aviat\Ion\Di\ContainerAware; +use LogicException; +use Throwable; + trait AnilistTrait { use ContainerAware; @@ -69,10 +72,10 @@ trait AnilistTrait { /** * Create a request object - * @param string $url * @param array $options * @return Request + * @throws Throwable */ public function setUpRequest(string $url, array $options = []): Request { @@ -123,7 +126,7 @@ trait AnilistTrait { $file = realpath(__DIR__ . "/GraphQL/Queries/{$name}.graphql"); if ( ! file_exists($file)) { - throw new \LogicException('GraphQL query file does not exist.'); + throw new LogicException('GraphQL query file does not exist.'); } // $query = str_replace(["\t", "\n"], ' ', file_get_contents($file)); @@ -146,12 +149,18 @@ trait AnilistTrait { ]); } + /** + * @param string $name + * @param array $variables + * @return Request + * @throws Throwable + */ public function mutateRequest (string $name, array $variables = []): Request { $file = realpath(__DIR__ . "/GraphQL/Mutations/{$name}.graphql"); if (!file_exists($file)) { - throw new \LogicException('GraphQL mutation file does not exist.'); + throw new LogicException('GraphQL mutation file does not exist.'); } // $query = str_replace(["\t", "\n"], ' ', file_get_contents($file)); @@ -174,12 +183,18 @@ trait AnilistTrait { ]); } + /** + * @param string $name + * @param array $variables + * @return array + * @throws Throwable + */ public function mutate (string $name, array $variables = []): array { $request = $this->mutateRequest($name, $variables); $response = $this->getResponseFromRequest($request); - return Json::decode(wait($response->getBody())); + return Json::decode(wait($response->getBody()->buffer())); } /** @@ -188,6 +203,7 @@ trait AnilistTrait { * @param string $url * @param array $options * @return Response + * @throws Throwable */ private function getResponse(string $url, array $options = []): Response { @@ -211,6 +227,11 @@ trait AnilistTrait { return $response; } + /** + * @param Request $request + * @return Response + * @throws Throwable + */ private function getResponseFromRequest(Request $request): Response { $logger = NULL; @@ -237,6 +258,7 @@ trait AnilistTrait { * * @param array $options * @return array + * @throws Throwable */ protected function postRequest(array $options = []): array { @@ -258,14 +280,14 @@ trait AnilistTrait { if ( ! \in_array($response->getStatus(), $validResponseCodes, TRUE)) { - if ($logger) + if ($logger !== NULL) { $logger->warning('Non 200 response for POST api call', (array)$response->getBody()); } } - // dump(wait($response->getBody())); + // dump(wait($response->getBody()->buffer())); - return Json::decode(wait($response->getBody())); + return Json::decode(wait($response->getBody()->buffer())); } } \ No newline at end of file diff --git a/src/API/Anilist/GraphQL/Mutations/CreateFullMediaListEntry.graphql b/src/AnimeClient/API/Anilist/GraphQL/Mutations/CreateFullMediaListEntry.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Mutations/CreateFullMediaListEntry.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Mutations/CreateFullMediaListEntry.graphql diff --git a/src/API/Anilist/GraphQL/Mutations/CreateMediaListEntry.graphql b/src/AnimeClient/API/Anilist/GraphQL/Mutations/CreateMediaListEntry.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Mutations/CreateMediaListEntry.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Mutations/CreateMediaListEntry.graphql diff --git a/src/API/Anilist/GraphQL/Mutations/DeleteMediaListEntry.graphql b/src/AnimeClient/API/Anilist/GraphQL/Mutations/DeleteMediaListEntry.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Mutations/DeleteMediaListEntry.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Mutations/DeleteMediaListEntry.graphql diff --git a/src/API/Anilist/GraphQL/Mutations/IncrementMediaListEntry.graphql b/src/AnimeClient/API/Anilist/GraphQL/Mutations/IncrementMediaListEntry.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Mutations/IncrementMediaListEntry.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Mutations/IncrementMediaListEntry.graphql diff --git a/src/API/Anilist/GraphQL/Mutations/UpdateMediaListEntry.graphql b/src/AnimeClient/API/Anilist/GraphQL/Mutations/UpdateMediaListEntry.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Mutations/UpdateMediaListEntry.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Mutations/UpdateMediaListEntry.graphql diff --git a/src/API/Anilist/GraphQL/Queries/AnimeDetails.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/AnimeDetails.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/AnimeDetails.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/AnimeDetails.graphql diff --git a/src/API/Anilist/GraphQL/Queries/CheckLogin.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/CheckLogin.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/CheckLogin.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/CheckLogin.graphql diff --git a/src/API/Anilist/GraphQL/Queries/ListItemIdByMalId.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/ListItemIdByMalId.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/ListItemIdByMalId.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/ListItemIdByMalId.graphql diff --git a/src/API/Anilist/GraphQL/Queries/ListItemIdByMediaId.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/ListItemIdByMediaId.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/ListItemIdByMediaId.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/ListItemIdByMediaId.graphql diff --git a/src/API/Anilist/GraphQL/Queries/MangaDetails.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/MangaDetails.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/MangaDetails.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/MangaDetails.graphql diff --git a/src/API/Anilist/GraphQL/Queries/MangaIdByMalId.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/MangaIdByMalId.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/MangaIdByMalId.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/MangaIdByMalId.graphql diff --git a/src/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql diff --git a/src/API/Anilist/GraphQL/Queries/MediaListItem.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/MediaListItem.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/MediaListItem.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/MediaListItem.graphql diff --git a/src/API/Anilist/GraphQL/Queries/SyncUserList.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/SyncUserList.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/SyncUserList.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/SyncUserList.graphql diff --git a/src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/UserAnimeList.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/UserAnimeList.graphql diff --git a/src/API/Anilist/GraphQL/Queries/UserMangaList.graphql b/src/AnimeClient/API/Anilist/GraphQL/Queries/UserMangaList.graphql similarity index 100% rename from src/API/Anilist/GraphQL/Queries/UserMangaList.graphql rename to src/AnimeClient/API/Anilist/GraphQL/Queries/UserMangaList.graphql diff --git a/src/API/Anilist/ListItem.php b/src/AnimeClient/API/Anilist/ListItem.php similarity index 68% rename from src/API/Anilist/ListItem.php rename to src/AnimeClient/API/Anilist/ListItem.php index ca8d6283..e3c795c5 100644 --- a/src/API/Anilist/ListItem.php +++ b/src/AnimeClient/API/Anilist/ListItem.php @@ -4,21 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\API\Anilist; -use Amp\Artax\Request; +use Amp\Http\Client\Request; -use Aviat\AnimeClient\API\ListItemInterface; +use Aviat\AnimeClient\API\AbstractListItem; use Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Anilist as AnilistStatus; use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus; use Aviat\AnimeClient\Types\FormItemData; @@ -26,7 +26,7 @@ use Aviat\AnimeClient\Types\FormItemData; /** * CRUD operations for MAL list items */ -final class ListItem implements ListItemInterface{ +final class ListItem extends AbstractListItem { use AnilistTrait; /** @@ -37,7 +37,8 @@ final class ListItem implements ListItemInterface{ */ public function create(array $data): Request { - return $this->mutateRequest('CreateMediaListEntry', $data); + $checkedData = (new Types\MediaListEntry($data))->toArray(); + return $this->mutateRequest('CreateMediaListEntry', $checkedData); } /** @@ -48,7 +49,8 @@ final class ListItem implements ListItemInterface{ */ public function createFull(array $data): Request { - return $this->mutateRequest('CreateFullMediaListEntry', $data); + $checkedData = (new Types\MediaListEntry($data))->toArray(); + return $this->mutateRequest('CreateFullMediaListEntry', $checkedData); } /** @@ -83,10 +85,12 @@ final class ListItem implements ListItemInterface{ */ public function increment(string $id, FormItemData $data): Request { - return $this->mutateRequest('IncrementMediaListEntry', [ + $checkedData = (new Types\MediaListEntry([ 'id' => $id, - 'progress' => $data['progress'], - ]); + 'progress' => $data->progress, + ]))->toArray(); + + return $this->mutateRequest('IncrementMediaListEntry', $checkedData); } /** @@ -98,15 +102,15 @@ final class ListItem implements ListItemInterface{ */ public function update(string $id, FormItemData $data): Request { - $array = $data->toArray(); + $notes = $data->notes ?? ''; + $progress = (int)$data->progress; + $private = (bool)$data->private; + $rating = $data->ratingTwenty; + $status = ($data->reconsuming === TRUE) + ? AnilistStatus::REPEATING + : AnimeWatchingStatus::KITSU_TO_ANILIST[$data->status]; - $notes = $data['notes'] ?? ''; - $progress = array_key_exists('progress', $array) ? $data['progress'] : 0; - $private = array_key_exists('private', $array) ? (bool)$data['private'] : false; - $rating = array_key_exists('ratingTwenty', $array) ? $data['ratingTwenty'] : NULL; - $status = ($data['reconsuming'] === true) ? AnilistStatus::REPEATING : AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']]; - - $updateData = [ + $updateData = (new Types\MediaListEntry([ 'id' => (int)$id, 'status' => $status, 'score' => $rating * 5, @@ -114,7 +118,7 @@ final class ListItem implements ListItemInterface{ 'repeat' => (int)$data['reconsumeCount'], 'private' => $private, 'notes' => $notes, - ]; + ]))->toArray(); return $this->mutateRequest('UpdateMediaListEntry', $updateData); } diff --git a/src/API/Anilist/MissingIdException.php b/src/AnimeClient/API/Anilist/MissingIdException.php similarity index 85% rename from src/API/Anilist/MissingIdException.php rename to src/AnimeClient/API/Anilist/MissingIdException.php index fb116a1e..c128adee 100644 --- a/src/API/Anilist/MissingIdException.php +++ b/src/AnimeClient/API/Anilist/MissingIdException.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Anilist/Model.php b/src/AnimeClient/API/Anilist/Model.php similarity index 86% rename from src/API/Anilist/Model.php rename to src/AnimeClient/API/Anilist/Model.php index 00115399..98d74e6d 100644 --- a/src/API/Anilist/Model.php +++ b/src/AnimeClient/API/Anilist/Model.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,11 +20,15 @@ use function Amp\Promise\wait; use InvalidArgumentException; -use Amp\Artax\Request; +use Amp\Http\Client\Request; use Aviat\AnimeClient\API\Anilist; use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus}; use Aviat\AnimeClient\Types\FormItem; use Aviat\Ion\Json; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; + +use Throwable; /** * Anilist API Model @@ -57,6 +61,7 @@ final class Model * @param string $code - The request token * @param string $redirectUri - The oauth callback url * @return array + * @throws Throwable */ public function authenticate(string $code, string $redirectUri): array { @@ -74,7 +79,7 @@ final class Model $response = $this->getResponseFromRequest($request); - return Json::decode(wait($response->getBody())); + return Json::decode(wait($response->getBody()->buffer())); } /** @@ -92,8 +97,8 @@ final class Model * * @param string $type * @return array - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function getSyncList(string $type = 'anime'): array { @@ -118,16 +123,21 @@ final class Model * @param string $type * @return Request */ - public function createListItem(array $data, string $type = 'anime'): Request + public function createListItem(array $data, string $type = 'anime'): ?Request { - $createData = []; + if ($data['mal_id'] === NULL) + { + return NULL; + } $mediaId = $this->getMediaIdFromMalId($data['mal_id'], mb_strtoupper($type)); - /* if (empty($mediaId)) + if ($mediaId === NULL) { - throw new InvalidArgumentException('Media id missing'); - } */ + return NULL; + } + + $createData = []; if ($type === 'ANIME') { @@ -144,7 +154,7 @@ final class Model ]; } - return $this->listItem->create($createData, $type); + return $this->listItem->create($createData); } /** @@ -174,7 +184,8 @@ final class Model * * @param string $malId - The unique identifier of that list item * @param string $type - Them media type (anime/manga) - * @return mixed + * + * @return array */ public function getListItem(string $malId, string $type): array { @@ -194,9 +205,13 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function incrementListItem(FormItem $data, string $type): Request + public function incrementListItem(FormItem $data, string $type): ?Request { $id = $this->getListIdFromMalId($data['mal_id'], $type); + if ($id === NULL) + { + return NULL; + } return $this->listItem->increment($id, $data['data']); } @@ -208,10 +223,15 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function updateListItem(FormItem $data, string $type): Request + public function updateListItem(FormItem $data, string $type): ?Request { $id = $this->getListIdFromMalId($data['mal_id'], mb_strtoupper($type)); + if ($id === NULL) + { + return NULL; + } + return $this->listItem->update($id, $data['data']); } @@ -222,11 +242,15 @@ final class Model * @param string $type - Them media type (anime/manga) * @return Request */ - public function deleteListItem(string $malId, string $type): Request + public function deleteListItem(string $malId, string $type): ?Request { - $item_id = $this->getListIdFromMalId($malId, $type); + $id = $this->getListIdFromMalId($malId, $type); + if ($id === NULL) + { + return NULL; + } - return $this->listItem->delete($item_id); + return $this->listItem->delete($id); } /** @@ -239,6 +263,11 @@ final class Model public function getListIdFromMalId(string $malId, string $type): ?string { $mediaId = $this->getMediaIdFromMalId($malId, $type); + if ($mediaId === NULL) + { + return NULL; + } + return $this->getListIdFromMediaId($mediaId); } diff --git a/src/API/Anilist/Transformer/AnimeListTransformer.php b/src/AnimeClient/API/Anilist/Transformer/AnimeListTransformer.php similarity index 95% rename from src/API/Anilist/Transformer/AnimeListTransformer.php rename to src/AnimeClient/API/Anilist/Transformer/AnimeListTransformer.php index 4059a47e..62897dc3 100644 --- a/src/API/Anilist/Transformer/AnimeListTransformer.php +++ b/src/AnimeClient/API/Anilist/Transformer/AnimeListTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Anilist/Transformer/MangaListTransformer.php b/src/AnimeClient/API/Anilist/Transformer/MangaListTransformer.php similarity index 94% rename from src/API/Anilist/Transformer/MangaListTransformer.php rename to src/AnimeClient/API/Anilist/Transformer/MangaListTransformer.php index 9537438a..ab2eeaf5 100644 --- a/src/API/Anilist/Transformer/MangaListTransformer.php +++ b/src/AnimeClient/API/Anilist/Transformer/MangaListTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/AnimeClient/API/Anilist/Types/MediaListEntry.php b/src/AnimeClient/API/Anilist/Types/MediaListEntry.php new file mode 100644 index 00000000..4a778e77 --- /dev/null +++ b/src/AnimeClient/API/Anilist/Types/MediaListEntry.php @@ -0,0 +1,56 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\API\Anilist\Types; + +use Aviat\AnimeClient\Types\AbstractType; + +class MediaListEntry extends AbstractType { + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $notes; + + /** + * @var bool + */ + public $private; + + /** + * @var int + */ + public $progress; + + /** + * @var int + */ + public $repeat; + + /** + * @var string + */ + public $status; + + /** + * @var int + */ + public $score; +} \ No newline at end of file diff --git a/src/API/CacheTrait.php b/src/AnimeClient/API/CacheTrait.php similarity index 93% rename from src/API/CacheTrait.php rename to src/AnimeClient/API/CacheTrait.php index 92f349f0..ba786d0c 100644 --- a/src/API/CacheTrait.php +++ b/src/AnimeClient/API/CacheTrait.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/AnimeWatchingStatus/Anilist.php b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Anilist.php similarity index 90% rename from src/API/Enum/AnimeWatchingStatus/Anilist.php rename to src/AnimeClient/API/Enum/AnimeWatchingStatus/Anilist.php index 685feecc..01fd04ef 100644 --- a/src/API/Enum/AnimeWatchingStatus/Anilist.php +++ b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Anilist.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/AnimeWatchingStatus/Kitsu.php b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Kitsu.php similarity index 89% rename from src/API/Enum/AnimeWatchingStatus/Kitsu.php rename to src/AnimeClient/API/Enum/AnimeWatchingStatus/Kitsu.php index 7611548f..d8d69d32 100644 --- a/src/API/Enum/AnimeWatchingStatus/Kitsu.php +++ b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Kitsu.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/AnimeWatchingStatus/Route.php b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Route.php similarity index 90% rename from src/API/Enum/AnimeWatchingStatus/Route.php rename to src/AnimeClient/API/Enum/AnimeWatchingStatus/Route.php index 513437f3..ff77694c 100644 --- a/src/API/Enum/AnimeWatchingStatus/Route.php +++ b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Route.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/AnimeWatchingStatus/Title.php b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Title.php similarity index 90% rename from src/API/Enum/AnimeWatchingStatus/Title.php rename to src/AnimeClient/API/Enum/AnimeWatchingStatus/Title.php index 6a552147..0861a888 100644 --- a/src/API/Enum/AnimeWatchingStatus/Title.php +++ b/src/AnimeClient/API/Enum/AnimeWatchingStatus/Title.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/MangaReadingStatus/Anilist.php b/src/AnimeClient/API/Enum/MangaReadingStatus/Anilist.php similarity index 90% rename from src/API/Enum/MangaReadingStatus/Anilist.php rename to src/AnimeClient/API/Enum/MangaReadingStatus/Anilist.php index a0c48100..588d3b30 100644 --- a/src/API/Enum/MangaReadingStatus/Anilist.php +++ b/src/AnimeClient/API/Enum/MangaReadingStatus/Anilist.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/MangaReadingStatus/Kitsu.php b/src/AnimeClient/API/Enum/MangaReadingStatus/Kitsu.php similarity index 89% rename from src/API/Enum/MangaReadingStatus/Kitsu.php rename to src/AnimeClient/API/Enum/MangaReadingStatus/Kitsu.php index 2ced44f5..4eb6623e 100644 --- a/src/API/Enum/MangaReadingStatus/Kitsu.php +++ b/src/AnimeClient/API/Enum/MangaReadingStatus/Kitsu.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/MangaReadingStatus/Route.php b/src/AnimeClient/API/Enum/MangaReadingStatus/Route.php similarity index 90% rename from src/API/Enum/MangaReadingStatus/Route.php rename to src/AnimeClient/API/Enum/MangaReadingStatus/Route.php index 67a7d37d..db8f34d4 100644 --- a/src/API/Enum/MangaReadingStatus/Route.php +++ b/src/AnimeClient/API/Enum/MangaReadingStatus/Route.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Enum/MangaReadingStatus/Title.php b/src/AnimeClient/API/Enum/MangaReadingStatus/Title.php similarity index 90% rename from src/API/Enum/MangaReadingStatus/Title.php rename to src/AnimeClient/API/Enum/MangaReadingStatus/Title.php index f8d2f5fb..040e4cae 100644 --- a/src/API/Enum/MangaReadingStatus/Title.php +++ b/src/AnimeClient/API/Enum/MangaReadingStatus/Title.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/FailedResponseException.php b/src/AnimeClient/API/FailedResponseException.php similarity index 87% rename from src/API/FailedResponseException.php rename to src/AnimeClient/API/FailedResponseException.php index 1813d683..cfa05f97 100644 --- a/src/API/FailedResponseException.php +++ b/src/AnimeClient/API/FailedResponseException.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/JsonAPI.php b/src/AnimeClient/API/JsonAPI.php similarity index 98% rename from src/API/JsonAPI.php rename to src/AnimeClient/API/JsonAPI.php index bbad2462..bb3129ba 100644 --- a/src/API/JsonAPI.php +++ b/src/AnimeClient/API/JsonAPI.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -144,6 +144,8 @@ final class JsonAPI { } } + unset($item); + $data['data']['included'] = $included; return $data['data']; @@ -193,6 +195,7 @@ final class JsonAPI { $organized[$type][$id] = $newItem; } + unset($item); // Second pass, go through and fill missing relationships in the first pass foreach($organized as $type => $items) diff --git a/src/API/Kitsu.php b/src/AnimeClient/API/Kitsu.php similarity index 98% rename from src/API/Kitsu.php rename to src/AnimeClient/API/Kitsu.php index f0911e1f..831a37ce 100644 --- a/src/API/Kitsu.php +++ b/src/AnimeClient/API/Kitsu.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Kitsu/Auth.php b/src/AnimeClient/API/Kitsu/Auth.php similarity index 90% rename from src/API/Kitsu/Auth.php rename to src/AnimeClient/API/Kitsu/Auth.php index e5591e2e..94755d3f 100644 --- a/src/API/Kitsu/Auth.php +++ b/src/AnimeClient/API/Kitsu/Auth.php @@ -4,18 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\API\Kitsu; +use Aura\Session\Segment; + +use Aviat\Banker\Exception\InvalidArgumentException; use const Aviat\AnimeClient\SESSION_SEGMENT; use Aviat\AnimeClient\API\{ @@ -23,7 +26,9 @@ use Aviat\AnimeClient\API\{ Kitsu as K }; use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; -use Exception; +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; + +use Throwable; /** * Kitsu API Authentication @@ -42,7 +47,7 @@ final class Auth { /** * Session object * - * @var \Aura\Session\Segment + * @var Segment */ private $segment; @@ -50,6 +55,8 @@ final class Auth { * Constructor * * @param ContainerInterface $container + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -64,8 +71,10 @@ final class Auth { * Make the appropriate authentication call, * and save the resulting auth token if successful * - * @param string $password + * @param string $password * @return boolean + * @throws InvalidArgumentException + * @throws Throwable */ public function authenticate(string $password): bool { @@ -109,6 +118,8 @@ final class Auth { * * @param string $token * @return boolean + * @throws InvalidArgumentException + * @throws Throwable */ public function reAuthenticate(string $token): bool { diff --git a/src/API/Kitsu/Enum/AnimeAiringStatus.php b/src/AnimeClient/API/Kitsu/Enum/AnimeAiringStatus.php similarity index 89% rename from src/API/Kitsu/Enum/AnimeAiringStatus.php rename to src/AnimeClient/API/Kitsu/Enum/AnimeAiringStatus.php index c59343b9..d69623f3 100644 --- a/src/API/Kitsu/Enum/AnimeAiringStatus.php +++ b/src/AnimeClient/API/Kitsu/Enum/AnimeAiringStatus.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Kitsu/GraphQL/Mutations/.gitkeep b/src/AnimeClient/API/Kitsu/GraphQL/Mutations/.gitkeep similarity index 100% rename from src/API/Kitsu/GraphQL/Mutations/.gitkeep rename to src/AnimeClient/API/Kitsu/GraphQL/Mutations/.gitkeep diff --git a/src/API/Kitsu/GraphQL/Queries/.gitkeep b/src/AnimeClient/API/Kitsu/GraphQL/Queries/.gitkeep similarity index 100% rename from src/API/Kitsu/GraphQL/Queries/.gitkeep rename to src/AnimeClient/API/Kitsu/GraphQL/Queries/.gitkeep diff --git a/src/API/Kitsu/GraphQL/Queries/AnimeDetails.graphql b/src/AnimeClient/API/Kitsu/GraphQL/Queries/AnimeDetails.graphql similarity index 100% rename from src/API/Kitsu/GraphQL/Queries/AnimeDetails.graphql rename to src/AnimeClient/API/Kitsu/GraphQL/Queries/AnimeDetails.graphql diff --git a/src/API/Kitsu/GraphQL/Queries/UserDetails.graphql b/src/AnimeClient/API/Kitsu/GraphQL/Queries/UserDetails.graphql similarity index 100% rename from src/API/Kitsu/GraphQL/Queries/UserDetails.graphql rename to src/AnimeClient/API/Kitsu/GraphQL/Queries/UserDetails.graphql diff --git a/src/API/Kitsu/KitsuRequestBuilder.php b/src/AnimeClient/API/Kitsu/KitsuRequestBuilder.php similarity index 92% rename from src/API/Kitsu/KitsuRequestBuilder.php rename to src/AnimeClient/API/Kitsu/KitsuRequestBuilder.php index 41f3df62..bd8d0aa0 100644 --- a/src/API/Kitsu/KitsuRequestBuilder.php +++ b/src/AnimeClient/API/Kitsu/KitsuRequestBuilder.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Kitsu/KitsuTrait.php b/src/AnimeClient/API/Kitsu/KitsuTrait.php similarity index 90% rename from src/API/Kitsu/KitsuTrait.php rename to src/AnimeClient/API/Kitsu/KitsuTrait.php index 982e80bc..0b4f9f31 100644 --- a/src/API/Kitsu/KitsuTrait.php +++ b/src/AnimeClient/API/Kitsu/KitsuTrait.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -21,8 +21,8 @@ use const Aviat\AnimeClient\SESSION_SEGMENT; use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; -use Amp\Artax\Request; -use Amp\Artax\Response; +use Amp\Http\Client\Request; +use Amp\Http\Client\Response; use Aviat\AnimeClient\API\{ FailedResponseException, Kitsu as K @@ -30,6 +30,8 @@ use Aviat\AnimeClient\API\{ use Aviat\Ion\Json; use Aviat\Ion\JsonException; +use Throwable; + trait KitsuTrait { /** @@ -56,7 +58,7 @@ trait KitsuTrait { * @param string $type * @param string $url * @param array $options - * @return \Amp\Artax\Request + * @return Request */ public function setUpRequest(string $type, string $url, array $options = []): Request { @@ -120,6 +122,7 @@ trait KitsuTrait { * @param string $url * @param array $options * @return Response + * @throws Throwable */ private function getResponse(string $type, string $url, array $options = []): Response { @@ -151,8 +154,9 @@ trait KitsuTrait { * @param string $type * @param string $url * @param array $options - * @throws \Aviat\Ion\JsonException + * @throws JsonException * @throws FailedResponseException + * @throws Throwable * @return array */ private function request(string $type, string $url, array $options = []): array @@ -165,7 +169,7 @@ trait KitsuTrait { $response = $this->getResponse($type, $url, $options); - if ((int) $response->getStatus() > 299 OR (int) $response->getStatus() < 200) + if ((int) $response->getStatus() > 299 || (int) $response->getStatus() < 200) { if ($logger) { @@ -177,7 +181,7 @@ trait KitsuTrait { try { - return Json::decode(wait($response->getBody())); + return Json::decode(wait($response->getBody()->buffer())); } catch (JsonException $e) { @@ -191,6 +195,7 @@ trait KitsuTrait { * Remove some boilerplate for get requests * * @param mixed ...$args + * @throws Throwable * @return array */ protected function getRequest(...$args): array @@ -202,6 +207,7 @@ trait KitsuTrait { * Remove some boilerplate for patch requests * * @param mixed ...$args + * @throws Throwable * @return array */ protected function patchRequest(...$args): array @@ -213,6 +219,7 @@ trait KitsuTrait { * Remove some boilerplate for post requests * * @param mixed ...$args + * @throws Throwable * @return array */ protected function postRequest(...$args): array @@ -234,13 +241,14 @@ trait KitsuTrait { } } - return JSON::decode(wait($response->getBody()), TRUE); + return JSON::decode(wait($response->getBody()->buffer()), TRUE); } /** * Remove some boilerplate for delete requests * * @param mixed ...$args + * @throws Throwable * @return bool */ protected function deleteRequest(...$args): bool diff --git a/src/API/Kitsu/ListItem.php b/src/AnimeClient/API/Kitsu/ListItem.php similarity index 81% rename from src/API/Kitsu/ListItem.php rename to src/AnimeClient/API/Kitsu/ListItem.php index a32d9b4f..dde2d38d 100644 --- a/src/API/Kitsu/ListItem.php +++ b/src/AnimeClient/API/Kitsu/ListItem.php @@ -4,36 +4,45 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\API\Kitsu; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; use const Aviat\AnimeClient\SESSION_SEGMENT; use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; -use Amp\Artax\Request; -use Aviat\AnimeClient\API\ListItemInterface; +use Amp\Http\Client\Request; +use Aviat\AnimeClient\API\AbstractListItem; use Aviat\AnimeClient\Types\FormItemData; use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Json; +use Throwable; + /** * CRUD operations for Kitsu list items */ -final class ListItem implements ListItemInterface { +final class ListItem extends AbstractListItem { use ContainerAware; use KitsuTrait; + /** + * @param array $data + * @return Request + * @throws Throwable + */ public function create(array $data): Request { $body = [ @@ -78,6 +87,11 @@ final class ListItem implements ListItemInterface { ->getFullRequest(); } + /** + * @param string $id + * @return Request + * @throws Throwable + */ public function delete(string $id): Request { $authHeader = $this->getAuthHeader(); @@ -91,6 +105,11 @@ final class ListItem implements ListItemInterface { return $request->getFullRequest(); } + /** + * @param string $id + * @return array + * @throws Throwable + */ public function get(string $id): array { $authHeader = $this->getAuthHeader(); @@ -107,7 +126,7 @@ final class ListItem implements ListItemInterface { $request = $request->getFullRequest(); $response = getResponse($request); - return Json::decode(wait($response->getBody())); + return Json::decode(wait($response->getBody()->buffer())); } public function increment(string $id, FormItemData $data): Request @@ -115,6 +134,12 @@ final class ListItem implements ListItemInterface { return $this->update($id, $data); } + /** + * @param string $id + * @param FormItemData $data + * @return Request + * @throws Throwable + */ public function update(string $id, FormItemData $data): Request { $authHeader = $this->getAuthHeader(); @@ -137,6 +162,11 @@ final class ListItem implements ListItemInterface { return $request->getFullRequest(); } + /** + * @return bool|string + * @throws ContainerException + * @throws NotFoundException + */ private function getAuthHeader() { $cache = $this->getContainer()->get('cache'); diff --git a/src/API/Kitsu/Model.php b/src/AnimeClient/API/Kitsu/Model.php similarity index 94% rename from src/API/Kitsu/Model.php rename to src/AnimeClient/API/Kitsu/Model.php index a9919f1d..dc3c3c5d 100644 --- a/src/API/Kitsu/Model.php +++ b/src/AnimeClient/API/Kitsu/Model.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -18,7 +18,7 @@ namespace Aviat\AnimeClient\API\Kitsu; use function Amp\Promise\wait; -use Amp\Artax\Request; +use Amp\Http\Client\Request; use Aviat\AnimeClient\API\{ CacheTrait, JsonAPI, @@ -41,8 +41,13 @@ use Aviat\AnimeClient\Types\{ FormItem, MangaPage }; + +use Aviat\Banker\Exception\InvalidArgumentException; use Aviat\Ion\{Di\ContainerAware, Json}; +use ReflectionException; +use Throwable; + /** * Kitsu API Model */ @@ -103,6 +108,7 @@ final class Model { * @param string $username * @param string $password * @return bool|array + * @throws Throwable */ public function authenticate(string $username, string $password) { @@ -120,7 +126,7 @@ final class Model { 'password' => $password ] ]); - $data = Json::decode(wait($response->getBody())); + $data = Json::decode(wait($response->getBody()->buffer())); if (array_key_exists('error', $data)) { @@ -142,6 +148,7 @@ final class Model { * * @param string $token * @return bool|array + * @throws Throwable */ public function reAuthenticate(string $token) { @@ -156,7 +163,7 @@ final class Model { ] ]); - $data = Json::decode(wait($response->getBody())); + $data = Json::decode(wait($response->getBody()->buffer())); if (array_key_exists('access_token', $data)) { @@ -171,6 +178,7 @@ final class Model { * * @param string $username * @return string + * @throws InvalidArgumentException */ public function getUserIdByUsername(string $username = NULL): string { @@ -206,7 +214,7 @@ final class Model { */ public function getCharacter(string $slug): array { - $data = $this->getRequest('characters', [ + return $this->getRequest('characters', [ 'query' => [ 'filter' => [ 'slug' => $slug, @@ -218,8 +226,6 @@ final class Model { 'include' => 'castings.person,castings.media' ] ]); - - return $data; } /** @@ -227,6 +233,7 @@ final class Model { * * @param string $id * @return array + * @throws InvalidArgumentException */ public function getPerson(string $id): array { @@ -265,8 +272,7 @@ final class Model { */ public function getUserData(string $username): array { - // $userId = $this->getUserIdByUsername($username); - $data = $this->getRequest('users', [ + return $this->getRequest('users', [ 'query' => [ 'filter' => [ 'name' => $username, @@ -279,8 +285,6 @@ final class Model { 'include' => 'waifu,favorites.item,stats' ] ]); - - return $data; } /** @@ -399,6 +403,7 @@ final class Model { * * @param string $status - The watching status to filter the list with * @return array + * @throws InvalidArgumentException */ public function getAnimeList(string $status): array { @@ -421,6 +426,7 @@ final class Model { { $item['included'] = $included; } + unset($item); $transformed = $this->animeListTransformer->transformCollection($data['data']); $keyed = []; @@ -441,6 +447,7 @@ final class Model { * * @param string $status - Optional status to filter by * @return int + * @throws InvalidArgumentException */ public function getAnimeListCount(string $status = '') : int { @@ -472,6 +479,8 @@ final class Model { * * @param array $options * @return array + * @throws InvalidArgumentException + * @throws Throwable */ public function getFullRawAnimeList(array $options = [ 'include' => 'anime.mappings' @@ -507,6 +516,8 @@ final class Model { * Get all the anime entries, that are organized for output to html * * @return array + * @throws ReflectionException + * @throws InvalidArgumentException */ public function getFullOrganizedAnimeList(): array { @@ -564,6 +575,7 @@ final class Model { * @param int $offset * @param array $options * @return Request + * @throws InvalidArgumentException */ public function getPagedAnimeList(int $limit, int $offset = 0, array $options = [ 'include' => 'anime.mappings' @@ -590,6 +602,8 @@ final class Model { * * @param string $status - The watching status to filter the list with * @return array + * @throws InvalidArgumentException + * @throws Throwable */ public function getRawAnimeList(string $status): array { @@ -647,6 +661,7 @@ final class Model { * @param int $limit - The number of list items to fetch per page * @param int $offset - The page offset * @return array + * @throws InvalidArgumentException */ public function getMangaList(string $status, int $limit = 200, int $offset = 0): array { @@ -685,6 +700,7 @@ final class Model { { $item['included'] = $included; } + unset($item); $transformed = $this->mangaListTransformer->transformCollection($data['data']); @@ -700,6 +716,7 @@ final class Model { * * @param string $status - Optional status to filter by * @return int + * @throws InvalidArgumentException */ public function getMangaListCount(string $status = '') : int { @@ -731,6 +748,8 @@ final class Model { * * @param array $options * @return array + * @throws InvalidArgumentException + * @throws Throwable */ public function getFullRawMangaList(array $options = [ 'include' => 'manga.mappings' @@ -766,6 +785,8 @@ final class Model { * Get all Manga lists * * @return array + * @throws ReflectionException + * @throws InvalidArgumentException */ public function getFullOrganizedMangaList(): array { @@ -787,6 +808,7 @@ final class Model { * @param int $offset * @param array $options * @return Request + * @throws InvalidArgumentException */ public function getPagedMangaList(int $limit, int $offset = 0, array $options = [ 'include' => 'manga.mappings' @@ -845,10 +867,16 @@ final class Model { * * @param array $data * @return Request + * @throws InvalidArgumentException */ - public function createListItem(array $data): Request + public function createListItem(array $data): ?Request { $data['user_id'] = $this->getUserIdByUsername($this->getUsername()); + if ($data['id'] === NULL) + { + return NULL; + } + return $this->listItem->create($data); } diff --git a/src/API/Kitsu/Transformer/AnimeListTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/AnimeListTransformer.php similarity index 95% rename from src/API/Kitsu/Transformer/AnimeListTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/AnimeListTransformer.php index 5f29b9b8..74d3739a 100644 --- a/src/API/Kitsu/Transformer/AnimeListTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/AnimeListTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -100,7 +100,7 @@ final class AnimeListTransformer extends AbstractTransformer { 'title' => $title, 'titles' => $titles, 'slug' => $anime['slug'], - 'show_type' => $this->string($anime['subtype'])->upperCaseFirst()->__toString(), + 'show_type' => (string)$this->string($anime['subtype'])->upperCaseFirst(), 'cover_image' => $anime['posterImage']['small'], 'genres' => $genres, 'streaming_links' => $streamingLinks, diff --git a/src/API/Kitsu/Transformer/AnimeTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/AnimeTransformer.php similarity index 91% rename from src/API/Kitsu/Transformer/AnimeTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/AnimeTransformer.php index f93adf48..0369a795 100644 --- a/src/API/Kitsu/Transformer/AnimeTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/AnimeTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -89,14 +89,14 @@ final class AnimeTransformer extends AbstractTransformer { if ( ! empty($characters['main'])) { - uasort($characters['main'], function ($a, $b) { + uasort($characters['main'], static function ($a, $b) { return $a['name'] <=> $b['name']; }); } if ( ! empty($characters['supporting'])) { - uasort($characters['supporting'], function ($a, $b) { + uasort($characters['supporting'], static function ($a, $b) { return $a['name'] <=> $b['name']; }); } @@ -114,7 +114,7 @@ final class AnimeTransformer extends AbstractTransformer { 'genres' => $item['genres'], 'id' => $item['id'], 'included' => $item['included'], - 'show_type' => $this->string($item['showType'])->upperCaseFirst()->__toString(), + 'show_type' => (string)$this->string($item['showType'])->upperCaseFirst(), 'slug' => $item['slug'], 'staff' => $staff, 'status' => Kitsu::getAiringStatus($item['startDate'], $item['endDate']), diff --git a/src/API/Kitsu/Transformer/CharacterTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php similarity index 82% rename from src/API/Kitsu/Transformer/CharacterTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php index 0a5cd5cb..76c8bffa 100644 --- a/src/API/Kitsu/Transformer/CharacterTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/CharacterTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -26,6 +26,10 @@ use Aviat\Ion\Transformer\AbstractTransformer; */ final class CharacterTransformer extends AbstractTransformer { + /** + * @param array $characterData + * @return Character + */ public function transform($characterData): Character { $data = JsonAPI::organizeData($characterData); @@ -44,14 +48,14 @@ final class CharacterTransformer extends AbstractTransformer { { if (array_key_exists('anime', $data['included'])) { - uasort($data['included']['anime'], function ($a, $b) { + uasort($data['included']['anime'], static function ($a, $b) { return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle']; }); } if (array_key_exists('manga', $data['included'])) { - uasort($data['included']['manga'], function ($a, $b) { + uasort($data['included']['manga'], static function ($a, $b) { return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle']; }); } @@ -142,23 +146,24 @@ final class CharacterTransformer extends AbstractTransformer { foreach ($role['relationships']['person']['people'] as $pid => $peoples) { $p = $peoples; + + $person = $p['attributes']; + $person['id'] = $pid; + $person['image'] = $person['image']['original']; + + uasort($role['relationships']['media']['anime'], static function ($a, $b) { + return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle']; + }); + + $item = [ + 'person' => $person, + 'series' => $role['relationships']['media']['anime'] + ]; + + $output[$roleName][$language][] = $item; } - - $person = $p['attributes']; - $person['id'] = $pid; - $person['image'] = $person['image']['original']; - - uasort($role['relationships']['media']['anime'], function ($a, $b) { - return $a['attributes']['canonicalTitle'] <=> $b['attributes']['canonicalTitle']; - }); - - $item = [ - 'person' => $person, - 'series' => $role['relationships']['media']['anime'] - ]; - - $output[$roleName][$language][] = $item; - } else + } + else { foreach ($role['relationships']['person']['people'] as $pid => $person) { diff --git a/src/API/Kitsu/Transformer/MangaListTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/MangaListTransformer.php similarity index 94% rename from src/API/Kitsu/Transformer/MangaListTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/MangaListTransformer.php index 28691ecb..2692e01d 100644 --- a/src/API/Kitsu/Transformer/MangaListTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/MangaListTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -85,7 +85,7 @@ final class MangaListTransformer extends AbstractTransformer { $titles = Kitsu::filterTitles($manga); $title = array_shift($titles); - $map = new MangaListItem([ + return new MangaListItem([ 'id' => $item['id'], 'mal_id' => $MALid, 'chapters' => [ @@ -103,7 +103,7 @@ final class MangaListTransformer extends AbstractTransformer { 'slug' => $manga['slug'], 'title' => $title, 'titles' => $titles, - 'type' => $this->string($manga['subtype'])->upperCaseFirst()->__toString(), + 'type' => (string)$this->string($manga['subtype'])->upperCaseFirst(), 'url' => 'https://kitsu.io/manga/' . $manga['slug'], ]), 'reading_status' => $item['attributes']['status'], @@ -112,8 +112,6 @@ final class MangaListTransformer extends AbstractTransformer { 'reread' => $item['attributes']['reconsumeCount'], 'user_rating' => $rating, ]); - - return $map; } /** diff --git a/src/API/Kitsu/Transformer/MangaTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/MangaTransformer.php similarity index 90% rename from src/API/Kitsu/Transformer/MangaTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/MangaTransformer.php index 0dc2ddfa..a5338a89 100644 --- a/src/API/Kitsu/Transformer/MangaTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/MangaTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -98,14 +98,14 @@ final class MangaTransformer extends AbstractTransformer { if ( ! empty($characters['main'])) { - uasort($characters['main'], function ($a, $b) { + uasort($characters['main'], static function ($a, $b) { return $a['name'] <=> $b['name']; }); } if ( ! empty($characters['supporting'])) { - uasort($characters['supporting'], function ($a, $b) { + uasort($characters['supporting'], static function ($a, $b) { return $a['name'] <=> $b['name']; }); } @@ -130,10 +130,14 @@ final class MangaTransformer extends AbstractTransformer { ]); } - private function count(int $value = NULL) + /** + * @param int|null $value + * @return string + */ + private function count(int $value = NULL): string { return ((int)$value === 0) ? '-' - : $value; + : (string)$value; } } \ No newline at end of file diff --git a/src/API/Kitsu/Transformer/PersonTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/PersonTransformer.php similarity index 87% rename from src/API/Kitsu/Transformer/PersonTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/PersonTransformer.php index 7e07600a..6a0b4ea2 100644 --- a/src/API/Kitsu/Transformer/PersonTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/PersonTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -25,6 +25,10 @@ use Aviat\Ion\Transformer\AbstractTransformer; */ final class PersonTransformer extends AbstractTransformer { + /** + * @param array|object $personData + * @return Person + */ public function transform($personData): Person { $data = JsonAPI::organizeData($personData); @@ -78,7 +82,7 @@ final class PersonTransformer extends AbstractTransformer { $includedMedia = array_replace_recursive($existingMedia, $relatedMedia); - uasort($includedMedia, function ($a, $b) { + uasort($includedMedia, static function ($a, $b) { return $a['canonicalTitle'] <=> $b['canonicalTitle']; }); @@ -103,10 +107,10 @@ final class PersonTransformer extends AbstractTransformer { } } - uasort($output['characters']['main'], function ($a, $b) { + uasort($output['characters']['main'], static function ($a, $b) { return $a['character']['canonicalName'] <=> $b['character']['canonicalName']; }); - uasort($output['characters']['supporting'], function ($a, $b) { + uasort($output['characters']['supporting'], static function ($a, $b) { return $a['character']['canonicalName'] <=> $b['character']['canonicalName']; }); ksort($output['staff']); @@ -114,14 +118,14 @@ final class PersonTransformer extends AbstractTransformer { { if (array_key_exists('anime', $media)) { - uasort($media['anime'], function ($a, $b) { + uasort($media['anime'], static function ($a, $b) { return $a['canonicalTitle'] <=> $b['canonicalTitle']; }); } if (array_key_exists('manga', $media)) { - uasort($media['manga'], function ($a, $b) { + uasort($media['manga'], static function ($a, $b) { return $a['canonicalTitle'] <=> $b['canonicalTitle']; }); } diff --git a/src/API/Kitsu/Transformer/UserTransformer.php b/src/AnimeClient/API/Kitsu/Transformer/UserTransformer.php similarity index 95% rename from src/API/Kitsu/Transformer/UserTransformer.php rename to src/AnimeClient/API/Kitsu/Transformer/UserTransformer.php index c5b05464..21ea0e25 100644 --- a/src/API/Kitsu/Transformer/UserTransformer.php +++ b/src/AnimeClient/API/Kitsu/Transformer/UserTransformer.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -24,6 +24,9 @@ use Aviat\Ion\Transformer\AbstractTransformer; /** * Transform user profile data for display + * + * @param array|object $profileData + * @return User */ final class UserTransformer extends AbstractTransformer { public function transform($profileData): User @@ -41,6 +44,7 @@ final class UserTransformer extends AbstractTransformer { $stats[$key] = $item['attributes']['statsData']; unset($item); } + unset($item); $waifu = []; if (array_key_exists('waifu', $rels)) @@ -131,7 +135,7 @@ final class UserTransformer extends AbstractTransformer { return $output; } - private function organizeStats($stats, $data = []): array + private function organizeStats(array $stats, $data = []): array { $animeStats = []; $mangaStats = []; diff --git a/src/API/Mapping/AnimeWatchingStatus.php b/src/AnimeClient/API/Mapping/AnimeWatchingStatus.php similarity index 96% rename from src/API/Mapping/AnimeWatchingStatus.php rename to src/AnimeClient/API/Mapping/AnimeWatchingStatus.php index 81e516b6..a7f0eca6 100644 --- a/src/API/Mapping/AnimeWatchingStatus.php +++ b/src/AnimeClient/API/Mapping/AnimeWatchingStatus.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/Mapping/MangaReadingStatus.php b/src/AnimeClient/API/Mapping/MangaReadingStatus.php similarity index 96% rename from src/API/Mapping/MangaReadingStatus.php rename to src/AnimeClient/API/Mapping/MangaReadingStatus.php index d2dd609e..3c114a66 100644 --- a/src/API/Mapping/MangaReadingStatus.php +++ b/src/AnimeClient/API/Mapping/MangaReadingStatus.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/API/ParallelAPIRequest.php b/src/AnimeClient/API/ParallelAPIRequest.php similarity index 80% rename from src/API/ParallelAPIRequest.php rename to src/AnimeClient/API/ParallelAPIRequest.php index 355188b4..6230eee5 100644 --- a/src/API/ParallelAPIRequest.php +++ b/src/AnimeClient/API/ParallelAPIRequest.php @@ -4,22 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\API; +use Amp\Http\Client\Request; use function Amp\call; use function Amp\Promise\{all, wait}; use function Aviat\AnimeClient\getApiClient; +use Throwable; + /** * Class to simplify making and validating simultaneous requests */ @@ -35,7 +38,7 @@ final class ParallelAPIRequest { /** * Add a request * - * @param string|\Amp\Artax\Request $request + * @param string|Request $request * @param string|number $key * @return self */ @@ -54,7 +57,7 @@ final class ParallelAPIRequest { /** * Add multiple requests * - * @param string[]|\Amp\Artax\Request[] $requests + * @param string[]|Request[] $requests * @return self */ public function addRequests(array $requests): self @@ -67,7 +70,7 @@ final class ParallelAPIRequest { * Make the requests, and return the body for each * * @return array - * @throws \Throwable + * @throws Throwable */ public function makeRequests(): array { @@ -77,9 +80,9 @@ final class ParallelAPIRequest { foreach ($this->requests as $key => $url) { - $promises[$key] = call(function () use ($client, $url) { + $promises[$key] = call(static function () use ($client, $url) { $response = yield $client->request($url); - return yield $response->getBody(); + return yield $response->getBody()->buffer(); }); } @@ -90,7 +93,7 @@ final class ParallelAPIRequest { * Make the requests and return the response objects * * @return array - * @throws \Throwable + * @throws Throwable */ public function getResponses(): array { @@ -100,7 +103,7 @@ final class ParallelAPIRequest { foreach ($this->requests as $key => $url) { - $promises[$key] = call(function () use ($client, $url) { + $promises[$key] = call(static function () use ($client, $url) { return yield $client->request($url); }); } diff --git a/src/AnimeClient.php b/src/AnimeClient/AnimeClient.php similarity index 92% rename from src/AnimeClient.php rename to src/AnimeClient/AnimeClient.php index 4440f5b0..1242a74d 100644 --- a/src/AnimeClient.php +++ b/src/AnimeClient/AnimeClient.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -18,7 +18,10 @@ namespace Aviat\AnimeClient; use function Amp\Promise\wait; -use Amp\Artax\{Client, DefaultClient, Response}; +use Amp\Http\Client\Request; +use Amp\Http\Client\Response; +use Amp\Http\Client\HttpClient; +use Amp\Http\Client\HttpClientBuilder; use Aviat\Ion\ConfigInterface; use Yosymfony\Toml\{Toml, TomlBuilder}; @@ -178,8 +181,8 @@ function checkFolderPermissions(ConfigInterface $config): array $publicDir = $config->get('asset_dir'); $pathMap = [ - 'app/config' => realpath(__DIR__ . '/../app/config'), - 'app/logs' => realpath(__DIR__ . '/../app/logs'), + 'app/config' => realpath(__DIR__ . '/../../app/config'), + 'app/logs' => realpath(__DIR__ . '/../../app/logs'), 'public/images/avatars' => "{$publicDir}/images/avatars", 'public/images/anime' => "{$publicDir}/images/anime", 'public/images/characters' => "{$publicDir}/images/characters", @@ -218,23 +221,29 @@ function getApiClient () if ($client === NULL) { - $client = new DefaultClient; - $client->setOption(Client::OP_TRANSFER_TIMEOUT, 0); + $client = HttpClientBuilder::buildDefault(); } return $client; } /** - * Simplify making a request with Artax + * Simplify making a request with Http\Client * - * @param $request + * @param string|Request $request * @return Response * @throws \Throwable */ function getResponse ($request): Response { $client = getApiClient(); + + if (is_string($request)) + { + $request = new Request($request); + } + + return wait($client->request($request)); } diff --git a/src/Command/BaseCommand.php b/src/AnimeClient/Command/BaseCommand.php similarity index 87% rename from src/Command/BaseCommand.php rename to src/AnimeClient/Command/BaseCommand.php index 34840af3..02205d88 100644 --- a/src/Command/BaseCommand.php +++ b/src/AnimeClient/Command/BaseCommand.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -36,7 +36,7 @@ use Zend\Diactoros\{Response, ServerRequestFactory}; /** * Base class for console command setup */ -class BaseCommand extends Command { +abstract class BaseCommand extends Command { use CacheTrait; use ContainerAware; @@ -46,7 +46,7 @@ class BaseCommand extends Command { * @param string $message * @return void */ - protected function echoBox($message) + protected function echoBox($message): void { try { @@ -68,7 +68,7 @@ class BaseCommand extends Command { */ protected function setupContainer(): Container { - $APP_DIR = realpath(__DIR__ . '/../../app'); + $APP_DIR = realpath(__DIR__ . '/../../../app'); $APPCONF_DIR = realpath("{$APP_DIR}/appConf/"); $CONF_DIR = realpath("{$APP_DIR}/config/"); $baseConfig = require $APPCONF_DIR . '/base_config.php'; @@ -82,7 +82,7 @@ class BaseCommand extends Command { $configArray = array_replace_recursive($baseConfig, $config, $overrideConfig); - $di = static function ($configArray) use ($APP_DIR) { + $di = static function ($configArray) use ($APP_DIR): Container { $container = new Container(); // ------------------------------------------------------------------------- @@ -91,16 +91,19 @@ class BaseCommand extends Command { $app_logger = new Logger('animeclient'); $app_logger->pushHandler(new RotatingFileHandler($APP_DIR . '/logs/app-cli.log', Logger::NOTICE)); + $kitsu_request_logger = new Logger('kitsu-request'); $kitsu_request_logger->pushHandler(new RotatingFileHandler($APP_DIR . '/logs/kitsu_request-cli.log', Logger::NOTICE)); + $anilistRequestLogger = new Logger('anilist-request'); $anilistRequestLogger->pushHandler(new RotatingFileHandler($APP_DIR . '/logs/anilist_request-cli.log', Logger::NOTICE)); + $container->setLogger($app_logger); $container->setLogger($anilistRequestLogger, 'anilist-request'); $container->setLogger($kitsu_request_logger, 'kitsu-request'); // Create Config Object - $container->set('config', static function() use ($configArray) { + $container->set('config', static function() use ($configArray): Config { return new Config($configArray); }); @@ -126,7 +129,7 @@ class BaseCommand extends Command { $_FILES ); }); - $container->set('response', static function() { + $container->set('response', static function(): Response { return new Response; }); @@ -136,7 +139,7 @@ class BaseCommand extends Command { }); // Models - $container->set('kitsu-model', static function($container) { + $container->set('kitsu-model', static function($container): Kitsu\Model { $requestBuilder = new KitsuRequestBuilder(); $requestBuilder->setLogger($container->getLogger('kitsu-request')); @@ -152,7 +155,7 @@ class BaseCommand extends Command { $model->setCache($cache); return $model; }); - $container->set('anilist-model', static function ($container) { + $container->set('anilist-model', static function ($container): Anilist\Model { $requestBuilder = new Anilist\AnilistRequestBuilder(); $requestBuilder->setLogger($container->getLogger('anilist-request')); @@ -166,21 +169,21 @@ class BaseCommand extends Command { return $model; }); - $container->set('settings-model', static function($container) { + $container->set('settings-model', static function($container): Model\Settings { $model = new Model\Settings($container->get('config')); $model->setContainer($container); return $model; }); - $container->set('auth', static function($container) { + $container->set('auth', static function($container): Kitsu\Auth { return new Kitsu\Auth($container); }); - $container->set('url-generator', static function($container) { + $container->set('url-generator', static function($container): UrlGenerator { return new UrlGenerator($container); }); - $container->set('util', static function($container) { + $container->set('util', static function($container): Util { return new Util($container); }); diff --git a/src/Command/CacheClear.php b/src/AnimeClient/Command/CacheClear.php similarity index 73% rename from src/Command/CacheClear.php rename to src/AnimeClient/Command/CacheClear.php index ac7b6538..14d5aa6e 100644 --- a/src/Command/CacheClear.php +++ b/src/AnimeClient/Command/CacheClear.php @@ -4,18 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Command; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; + /** * Clears the API Cache */ @@ -25,15 +28,15 @@ final class CacheClear extends BaseCommand { * * @param array $args * @param array $options - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ public function execute(array $args, array $options = []): void { $this->setContainer($this->setupContainer()); - $cache = $this->container->get('cache'); - $cache->clear(); + + $this->container->get('cache')->clear(); $this->echoBox('API Cache has been cleared.'); } diff --git a/src/Command/CachePrime.php b/src/AnimeClient/Command/CachePrime.php similarity index 85% rename from src/Command/CachePrime.php rename to src/AnimeClient/Command/CachePrime.php index e265ae83..6848a61a 100644 --- a/src/Command/CachePrime.php +++ b/src/AnimeClient/Command/CachePrime.php @@ -4,18 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Command; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; + /** * Clears the API Cache */ @@ -25,8 +28,8 @@ final class CachePrime extends BaseCommand { * * @param array $args * @param array $options - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ public function execute(array $args, array $options = []): void @@ -50,8 +53,9 @@ final class CachePrime extends BaseCommand { $userIdItem->save(); } - // Prime anime list cache $kitsuModel = $this->container->get('kitsu-model'); + + // Prime anime list cache $kitsuModel->getFullOrganizedAnimeList(); // Prime manga list cache diff --git a/src/Command/ClearThumbnails.php b/src/AnimeClient/Command/ClearThumbnails.php similarity index 93% rename from src/Command/ClearThumbnails.php rename to src/AnimeClient/Command/ClearThumbnails.php index 0a5a0229..1c1a1061 100644 --- a/src/Command/ClearThumbnails.php +++ b/src/AnimeClient/Command/ClearThumbnails.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/Command/SyncLists.php b/src/AnimeClient/Command/SyncLists.php similarity index 95% rename from src/Command/SyncLists.php rename to src/AnimeClient/Command/SyncLists.php index bd923fb4..8934937d 100644 --- a/src/Command/SyncLists.php +++ b/src/AnimeClient/Command/SyncLists.php @@ -4,26 +4,34 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Command; -use Aviat\AnimeClient\API\ -{Anilist\MissingIdException, FailedResponseException, JsonAPI, ParallelAPIRequest}; +use Aviat\AnimeClient\API\{ + Anilist\MissingIdException, + FailedResponseException, + JsonAPI, + ParallelAPIRequest +}; use Aviat\AnimeClient\API\Anilist\Transformer\{ AnimeListTransformer as AALT, MangaListTransformer as AMLT }; +use Aviat\AnimeClient\API\Anilist\Model as AnilistModel; +use Aviat\AnimeClient\API\Kitsu\Model as KitsuModel; use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus}; use Aviat\AnimeClient\Types\FormItem; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; use Aviat\Ion\Json; use DateTime; @@ -34,13 +42,13 @@ final class SyncLists extends BaseCommand { /** * Model for making requests to Anilist API - * @var \Aviat\AnimeClient\API\Anilist\Model + * @var AnilistModel */ protected $anilistModel; /** * Model for making requests to Kitsu API - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var KitsuModel */ protected $kitsuModel; @@ -49,8 +57,8 @@ final class SyncLists extends BaseCommand { * * @param array $args * @param array $options - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @throws \Throwable */ public function execute(array $args, array $options = []): void @@ -169,8 +177,8 @@ final class SyncLists extends BaseCommand { * Format an Anilist anime list for comparison * * @return array - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ protected function formatAnilistAnimeList(): array { @@ -202,8 +210,8 @@ final class SyncLists extends BaseCommand { * Format an Anilist manga list for comparison * * @return array - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ protected function formatAnilistMangaList(): array { @@ -596,6 +604,12 @@ final class SyncLists extends BaseCommand { } else if ($action === 'create') { + $maybeRequest = $this->kitsuModel->createListItem($item); + if ($maybeRequest === NULL) + { + $this->echoBox("Skipped creating Kitsu {$type} due to missing id ¯\_(ツ)_/¯"); + continue; + } $requester->addRequest($this->kitsuModel->createListItem($item)); } } @@ -676,7 +690,6 @@ final class SyncLists extends BaseCommand { $responseData = Json::decode($response); - // $id = $itemsToUpdate[$key]['id']; if ( ! array_key_exists('errors', $responseData)) { $verb = ($action === 'update') ? 'updated' : 'created'; diff --git a/src/Command/UpdateThumbnails.php b/src/AnimeClient/Command/UpdateThumbnails.php similarity index 87% rename from src/Command/UpdateThumbnails.php rename to src/AnimeClient/Command/UpdateThumbnails.php index 80d88a6b..13eb789a 100644 --- a/src/Command/UpdateThumbnails.php +++ b/src/AnimeClient/Command/UpdateThumbnails.php @@ -4,19 +4,20 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Command; use Aviat\AnimeClient\API\JsonAPI; +use Aviat\AnimeClient\API\Kitsu\Model; use Aviat\AnimeClient\Controller\Images; /** @@ -26,7 +27,7 @@ use Aviat\AnimeClient\Controller\Images; final class UpdateThumbnails extends ClearThumbnails { /** * Model for making requests to Kitsu API - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var Model */ protected $kitsuModel; @@ -62,7 +63,11 @@ final class UpdateThumbnails extends ClearThumbnails { $this->echoBox('Finished regenerating all thumbnails'); } - public function getImageList() + /** + * @return array array-key[][] + * @psalm-return array{anime: list, manga: list} + */ + public function getImageList(): array { $mangaList = $this->kitsuModel->getFullRawMangaList(); $includes = JsonAPI::organizeIncludes($mangaList['included']); diff --git a/src/Controller.php b/src/AnimeClient/Controller.php similarity index 83% rename from src/Controller.php rename to src/AnimeClient/Controller.php index e76784d5..8e17f891 100644 --- a/src/Controller.php +++ b/src/AnimeClient/Controller.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -18,9 +18,19 @@ namespace Aviat\AnimeClient; use function Aviat\Ion\_dir; +use Aura\Router\Generator; +use Aura\Session\Segment; +use Aviat\AnimeClient\API\Kitsu\Auth; +use Aviat\Ion\ConfigInterface; +use Psr\Cache\CacheItemPoolInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; + use Aviat\Ion\Di\{ ContainerAware, - ContainerInterface + ContainerInterface, + Exception\ContainerException, + Exception\NotFoundException }; use Aviat\Ion\Exception\DoubleRenderException; use Aviat\Ion\View\{HtmlView, HttpView, JsonView}; @@ -35,31 +45,31 @@ class Controller { /** * The authentication object - * @var \Aviat\AnimeClient\API\Kitsu\Auth $auth ; + * @var Auth $auth ; */ protected $auth; /** * Cache manager - * @var \Psr\Cache\CacheItemPoolInterface + * @var CacheItemPoolInterface */ protected $cache; /** * The global configuration object - * @var \Aviat\Ion\ConfigInterface $config + * @var ConfigInterface $config */ public $config; /** * Request object - * @var \Psr\Http\Message\ServerRequestInterface $request + * @var ServerRequestInterface $request */ protected $request; /** * Response object - * @var \Psr\Http\Message\ResponseInterface $response + * @var ResponseInterface $response */ public $response; @@ -71,13 +81,13 @@ class Controller { /** * Aura url generator - * @var \Aura\Router\Generator + * @var Generator */ protected $url; /** * Session segment - * @var \Aura\Session\Segment + * @var Segment */ protected $session; @@ -91,8 +101,8 @@ class Controller { * Controller constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -127,8 +137,8 @@ class Controller { * Set the current url in the session as the target of a future redirect * * @param string|NULL $url - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function setSessionRedirect(string $url = NULL): void { @@ -151,7 +161,7 @@ class Controller { return; } - if (null === $url) + if (NULL === $url) { $url = $util->isViewPage() ? (string) $this->request->getUri() @@ -167,8 +177,8 @@ class Controller { * If one is not set, redirect to default url * * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ public function sessionRedirect(): void @@ -191,7 +201,6 @@ class Controller { 'Forbidden', 'You must
log in to perform this action.' ); - die(); } } @@ -202,8 +211,8 @@ class Controller { * @param string $template * @param array $data * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return string */ protected function loadPartial($view, string $template, array $data = []): string @@ -236,8 +245,8 @@ class Controller { * @param string $template * @param array $data * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ protected function renderFullPage($view, string $template, array $data): void @@ -266,8 +275,8 @@ class Controller { * @param string $title * @param string $message * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ public function notFound( @@ -287,18 +296,18 @@ class Controller { * @param int $httpCode * @param string $title * @param string $message - * @param string $long_message + * @param string $longMessage * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ - public function errorPage(int $httpCode, string $title, string $message, string $long_message = ''): void + public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void { $this->outputHTML('error', [ 'title' => $title, 'message' => $message, - 'long_message' => $long_message + 'long_message' => $longMessage ], NULL, $httpCode); } @@ -342,7 +351,7 @@ class Controller { /** * Helper for consistent page titles * - * @param string[] $parts Title segments + * @param string ...$parts Title segments * @return string */ public function formatTitle(string ...$parts) : string @@ -357,8 +366,8 @@ class Controller { * @param string $type * @param string $message * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return string */ protected function showMessage($view, string $type, string $message): string @@ -374,16 +383,16 @@ class Controller { * * @param string $template * @param array $data - * @param HtmlView|null $view + * @param HtmlView|NULL $view * @param int $code * @throws InvalidArgumentException - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return void */ protected function outputHTML(string $template, array $data = [], $view = NULL, int $code = 200): void { - if (null === $view) + if (NULL === $view) { $view = new HtmlView($this->container); } diff --git a/src/Controller/Anime.php b/src/AnimeClient/Controller/Anime.php similarity index 88% rename from src/Controller/Anime.php rename to src/AnimeClient/Controller/Anime.php index 3bcb39cc..540c167a 100644 --- a/src/Controller/Anime.php +++ b/src/AnimeClient/Controller/Anime.php @@ -4,26 +4,32 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aura\Router\Exception\RouteNotFound; use Aviat\AnimeClient\Controller as BaseController; use Aviat\AnimeClient\API\Kitsu\Transformer\AnimeListTransformer; use Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Kitsu as KitsuWatchingStatus; use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus; use Aviat\AnimeClient\Types\FormItem; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; use Aviat\Ion\Json; +use InvalidArgumentException; +use Throwable; + /** * Controller for Anime-related pages */ @@ -39,8 +45,8 @@ final class Anime extends BaseController { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -60,9 +66,10 @@ final class Anime extends BaseController { * * @param string|int $type - The section of the list * @param string $view - List or cover view - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException + * @throws Throwable * @return void */ public function index($type = KitsuWatchingStatus::WATCHING, string $view = NULL): void @@ -104,10 +111,11 @@ final class Anime extends BaseController { /** * Form to add an anime * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aura\Router\Exception\RouteNotFound - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws RouteNotFound + * @throws InvalidArgumentException + * @throws Throwable * @return void */ public function addForm(): void @@ -128,8 +136,9 @@ final class Anime extends BaseController { /** * Add an anime to the list * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException + * @throws Throwable * @return void */ public function add(): void @@ -168,6 +177,7 @@ final class Anime extends BaseController { * * @param string $id * @param string $status + * @throws RouteNotFound */ public function edit(string $id, $status = 'all'): void { @@ -204,8 +214,9 @@ final class Anime extends BaseController { /** * Update an anime item via a form submission * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException + * @throws Throwable * @return void */ public function formUpdate(): void @@ -236,6 +247,7 @@ final class Anime extends BaseController { /** * Increase the watched count for an anime item * + * @throws Throwable * @return void */ public function increment(): void @@ -266,6 +278,7 @@ final class Anime extends BaseController { /** * Remove an anime from the list * + * @throws Throwable * @return void */ public function delete(): void @@ -292,9 +305,9 @@ final class Anime extends BaseController { * View details of an anime * * @param string $animeId - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function details(string $animeId): void diff --git a/src/Controller/AnimeCollection.php b/src/AnimeClient/Controller/AnimeCollection.php similarity index 86% rename from src/Controller/AnimeCollection.php rename to src/AnimeClient/Controller/AnimeCollection.php index 1aa86676..85147cd3 100644 --- a/src/Controller/AnimeCollection.php +++ b/src/AnimeClient/Controller/AnimeCollection.php @@ -4,24 +4,30 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aura\Router\Exception\RouteNotFound; use Aviat\AnimeClient\Controller as BaseController; use Aviat\AnimeClient\Model\{ Anime as AnimeModel, AnimeCollection as AnimeCollectionModel }; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; +use Aviat\Ion\Exception\DoubleRenderException; + +use InvalidArgumentException; /** * Controller for Anime collection pages @@ -44,8 +50,8 @@ final class AnimeCollection extends BaseController { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -69,7 +75,7 @@ final class AnimeCollection extends BaseController { /** * Search for anime * - * @throws \Aviat\Ion\Exception\DoubleRenderException + * @throws DoubleRenderException * @return void */ public function search(): void @@ -83,9 +89,9 @@ final class AnimeCollection extends BaseController { * Show the anime collection page * * @param string $view - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function view($view): void @@ -108,10 +114,10 @@ final class AnimeCollection extends BaseController { * Show the anime collection add/edit form * * @param integer|null $id - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aura\Router\Exception\RouteNotFound - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws RouteNotFound + * @throws InvalidArgumentException * @return void */ public function form($id = NULL): void @@ -138,9 +144,9 @@ final class AnimeCollection extends BaseController { /** * Update a collection item * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function edit(): void @@ -173,9 +179,9 @@ final class AnimeCollection extends BaseController { /** * Add a collection item * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function add(): void diff --git a/src/Controller/Character.php b/src/AnimeClient/Controller/Character.php similarity index 84% rename from src/Controller/Character.php rename to src/AnimeClient/Controller/Character.php index 5440dfd0..6c14253e 100644 --- a/src/Controller/Character.php +++ b/src/AnimeClient/Controller/Character.php @@ -4,22 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aviat\AnimeClient\API\Kitsu\Model; use Aviat\AnimeClient\Controller as BaseController; use Aviat\AnimeClient\API\Kitsu\Transformer\CharacterTransformer; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; /** * Controller for character description pages @@ -27,7 +30,7 @@ use Aviat\Ion\Di\ContainerInterface; class Character extends BaseController { /** - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var Model */ private $model; @@ -35,8 +38,8 @@ class Character extends BaseController { * Character constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { diff --git a/src/Controller/Images.php b/src/AnimeClient/Controller/Images.php similarity index 92% rename from src/Controller/Images.php rename to src/AnimeClient/Controller/Images.php index a9ad4344..a6c5f1ff 100644 --- a/src/Controller/Images.php +++ b/src/AnimeClient/Controller/Images.php @@ -4,24 +4,28 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; + use function Amp\Promise\wait; use function Aviat\AnimeClient\getResponse; use function Aviat\AnimeClient\createPlaceholderImage; use Aviat\AnimeClient\Controller as BaseController; +use Throwable; + /** * Controller for handling routes that don't fit elsewhere */ @@ -32,17 +36,14 @@ final class Images extends BaseController { * @param string $type The category of image * @param string $file The filename to look for * @param bool $display Whether to output the image to the server - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException - * @throws \TypeError - * @throws \Error - * @throws \Throwable * @return void + * @throws NotFoundException + * @throws Throwable + * @throws ContainerException */ public function cache(string $type, string $file, $display = TRUE): void { - $currentUrl = $this->request->getUri()->__toString(); + $currentUrl = (string)$this->request->getUri(); $kitsuUrl = 'https://media.kitsu.io/'; $fileName = str_replace('-original', '', $file); @@ -129,7 +130,7 @@ final class Images extends BaseController { return; } - $data = wait($response->getBody()); + $data = wait($response->getBody()->buffer()); [$origWidth] = getimagesizefromstring($data); $gdImg = imagecreatefromstring($data); diff --git a/src/Controller/Manga.php b/src/AnimeClient/Controller/Manga.php similarity index 84% rename from src/Controller/Manga.php rename to src/AnimeClient/Controller/Manga.php index b8add390..634b19f2 100644 --- a/src/Controller/Manga.php +++ b/src/AnimeClient/Controller/Manga.php @@ -4,25 +4,30 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aura\Router\Exception\RouteNotFound; use Aviat\AnimeClient\Controller; use Aviat\AnimeClient\API\Kitsu\Transformer\MangaListTransformer; use Aviat\AnimeClient\API\Mapping\MangaReadingStatus; use Aviat\AnimeClient\Model\Manga as MangaModel; use Aviat\AnimeClient\Types\FormItem; use Aviat\Ion\Di\ContainerInterface; -use Aviat\Ion\{Json, StringWrapper}; +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; +use Aviat\Ion\Json; + +use InvalidArgumentException; +use Throwable; /** * Controller for manga list @@ -39,8 +44,8 @@ final class Manga extends Controller { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -59,9 +64,9 @@ final class Manga extends Controller { * * @param string $status * @param string $view - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function index($status = 'all', $view = ''): void @@ -103,10 +108,10 @@ final class Manga extends Controller { /** * Form to add an manga * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aura\Router\Exception\RouteNotFound - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws RouteNotFound + * @throws InvalidArgumentException * @return void */ public function addForm(): void @@ -129,9 +134,10 @@ final class Manga extends Controller { /** * Add an manga to the list * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException * @return void + * @throws NotFoundException + * @throws Throwable + * @throws ContainerException */ public function add(): void { @@ -168,10 +174,10 @@ final class Manga extends Controller { * * @param string $id * @param string $status - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aura\Router\Exception\RouteNotFound - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws RouteNotFound + * @throws InvalidArgumentException * @return void */ public function edit($id, $status = 'All'): void @@ -210,9 +216,10 @@ final class Manga extends Controller { /** * Update an manga item via a form submission * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException * @return void + * @throws Throwable + * @throws NotFoundException + * @throws ContainerException */ public function formUpdate(): void { @@ -228,7 +235,7 @@ final class Manga extends Controller { if ($full_result['statusCode'] === 200) { - $this->setFlashMessage("Successfully updated manga.", 'success'); + $this->setFlashMessage('Successfully updated manga.', 'success'); $this->cache->clear(); } else @@ -242,6 +249,7 @@ final class Manga extends Controller { /** * Increment the progress of a manga item + * @throws Throwable */ public function increment(): void { @@ -265,8 +273,9 @@ final class Manga extends Controller { /** * Remove an manga from the list * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException + * @throws Throwable * @return void */ public function delete(): void @@ -293,9 +302,10 @@ final class Manga extends Controller { * View details of an manga * * @param string $manga_id - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException + * @throws Throwable * @return void */ public function details($manga_id): void diff --git a/src/Controller/MangaCollection.php b/src/AnimeClient/Controller/MangaCollection.php similarity index 83% rename from src/Controller/MangaCollection.php rename to src/AnimeClient/Controller/MangaCollection.php index 73a8cf44..fce90263 100644 --- a/src/Controller/MangaCollection.php +++ b/src/AnimeClient/Controller/MangaCollection.php @@ -4,25 +4,31 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aura\Router\Exception\RouteNotFound; use Aviat\AnimeClient\Controller as BaseController; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; +use Aviat\Ion\Exception\DoubleRenderException; use Aviat\AnimeClient\Model\{ Manga as MangaModel, MangaCollection as MangaCollectionModel }; use Aviat\Ion\Di\ContainerInterface; +use InvalidArgumentException; + /** * Controller for manga collection pages */ @@ -44,8 +50,8 @@ final class MangaCollection extends BaseController { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @throws \InvalidArgumentException */ public function __construct(ContainerInterface $container) @@ -65,7 +71,7 @@ final class MangaCollection extends BaseController { /** * Search for manga * - * @throws \Aviat\Ion\Exception\DoubleRenderException + * @throws DoubleRenderException * @return void */ public function search(): void @@ -79,9 +85,9 @@ final class MangaCollection extends BaseController { * Show the manga collection page * * @param string $view - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function index($view): void @@ -104,10 +110,10 @@ final class MangaCollection extends BaseController { * Show the manga collection add/edit form * * @param integer|null $id - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aura\Router\Exception\RouteNotFound - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws RouteNotFound + * @throws InvalidArgumentException * @return void */ public function form($id = NULL): void @@ -132,9 +138,9 @@ final class MangaCollection extends BaseController { /** * Update a collection item * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function edit(): void @@ -156,9 +162,9 @@ final class MangaCollection extends BaseController { /** * Add a collection item * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \InvalidArgumentException + * @throws ContainerException + * @throws NotFoundException + * @throws InvalidArgumentException * @return void */ public function add(): void diff --git a/src/Controller/Misc.php b/src/AnimeClient/Controller/Misc.php similarity index 95% rename from src/Controller/Misc.php rename to src/AnimeClient/Controller/Misc.php index b73afc5b..6737fe4f 100644 --- a/src/Controller/Misc.php +++ b/src/AnimeClient/Controller/Misc.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/Controller/People.php b/src/AnimeClient/Controller/People.php similarity index 83% rename from src/Controller/People.php rename to src/AnimeClient/Controller/People.php index 30b333d6..2722f2e6 100644 --- a/src/Controller/People.php +++ b/src/AnimeClient/Controller/People.php @@ -4,22 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aviat\AnimeClient\API\Kitsu\Model; use Aviat\AnimeClient\Controller as BaseController; use Aviat\AnimeClient\API\Kitsu\Transformer\PersonTransformer; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; /** * Controller for People pages @@ -27,7 +30,7 @@ use Aviat\Ion\Di\ContainerInterface; final class People extends BaseController { /** - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var Model */ private $model; @@ -35,8 +38,8 @@ final class People extends BaseController { * People constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { diff --git a/src/Controller/Settings.php b/src/AnimeClient/Controller/Settings.php similarity index 91% rename from src/Controller/Settings.php rename to src/AnimeClient/Controller/Settings.php index 82a296dd..20e2a56c 100644 --- a/src/Controller/Settings.php +++ b/src/AnimeClient/Controller/Settings.php @@ -4,20 +4,24 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aura\Router\Exception\RouteNotFound; +use Aviat\AnimeClient\API\Anilist\Model; use Aviat\AnimeClient\Controller as BaseController; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; /** * Controller for user settings @@ -25,7 +29,7 @@ use Aviat\Ion\Di\ContainerInterface; final class Settings extends BaseController { /** - * @var \Aviat\AnimeClient\API\Anilist\Model + * @var Model */ private $anilistModel; @@ -38,8 +42,8 @@ final class Settings extends BaseController { * Settings constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -75,7 +79,7 @@ final class Settings extends BaseController { /** * Attempt to save the user's settings * - * @throws \Aura\Router\Exception\RouteNotFound + * @throws RouteNotFound */ public function update(): void { diff --git a/src/Controller/User.php b/src/AnimeClient/Controller/User.php similarity index 84% rename from src/Controller/User.php rename to src/AnimeClient/Controller/User.php index ed62d2ad..6df00d17 100644 --- a/src/Controller/User.php +++ b/src/AnimeClient/Controller/User.php @@ -4,22 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Controller; +use Aviat\AnimeClient\API\Kitsu\Model; use Aviat\AnimeClient\API\Kitsu\Transformer\UserTransformer; use Aviat\AnimeClient\Controller as BaseController; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; /** * Controller for handling routes that don't fit elsewhere @@ -27,7 +30,7 @@ use Aviat\Ion\Di\ContainerInterface; final class User extends BaseController { /** - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var Model */ private $kitsuModel; @@ -35,8 +38,8 @@ final class User extends BaseController { * User constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { diff --git a/src/Dispatcher.php b/src/AnimeClient/Dispatcher.php similarity index 90% rename from src/Dispatcher.php rename to src/AnimeClient/Dispatcher.php index faeb4df5..e0a98ca5 100644 --- a/src/Dispatcher.php +++ b/src/AnimeClient/Dispatcher.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -18,13 +18,16 @@ namespace Aviat\AnimeClient; use function Aviat\Ion\_dir; -use Aura\Router\{Matcher, Rule}; +use Aura\Router\{Matcher, Route, Rule}; use Aviat\AnimeClient\API\FailedResponseException; use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Friend; use Aviat\Ion\StringWrapper; +use LogicException; +use ReflectionException; + /** * Basic routing/ dispatch */ @@ -74,7 +77,7 @@ final class Dispatcher extends RoutingBase { /** * Get the current route object, if one matches * - * @return \Aura\Router\Route|false + * @return Route|false */ public function getRoute() { @@ -109,6 +112,7 @@ final class Dispatcher extends RoutingBase { * * @param object|null $route * @return void + * @throws ReflectionException */ public function __invoke($route = NULL): void { @@ -125,14 +129,7 @@ final class Dispatcher extends RoutingBase { } } - if ($route) - { - $parsed = $this->processRoute(new Friend($route)); - $controllerName = $parsed['controller_name']; - $actionMethod = $parsed['action_method']; - $params = $parsed['params']; - } - else + if ( ! $route) { // If not route was matched, return an appropriate http // error message @@ -140,8 +137,15 @@ final class Dispatcher extends RoutingBase { $controllerName = DEFAULT_CONTROLLER; $actionMethod = $errorRoute['action_method']; $params = $errorRoute['params']; + $this->call($controllerName, $actionMethod, $params); + return; } + $parsed = $this->processRoute(new Friend($route)); + $controllerName = $parsed['controller_name']; + $actionMethod = $parsed['action_method']; + $params = $parsed['params']; + $this->call($controllerName, $actionMethod, $params); } @@ -149,20 +153,21 @@ final class Dispatcher extends RoutingBase { * Parse out the arguments for the appropriate controller for * the current route * - * @param \Aura\Router\Route $route - * @throws \LogicException + * @param Route $route + * @throws LogicException * @return array */ protected function processRoute($route): array { + if ( ! array_key_exists('controller', $route->attributes)) + { + throw new LogicException('Missing controller'); + } + if (array_key_exists('controller', $route->attributes)) { $controllerName = $route->attributes['controller']; } - else - { - throw new \LogicException('Missing controller'); - } // Get the full namespace for a controller if a short name is given if (strpos($controllerName, '\\') === FALSE) @@ -249,7 +254,7 @@ final class Dispatcher extends RoutingBase { foreach ($classFiles as $file) { $rawClassName = basename(str_replace('.php', '', $file)); - $path = $this->string($rawClassName)->dasherize()->__toString(); + $path = (string)$this->string($rawClassName)->dasherize(); $className = trim($defaultNamespace . '\\' . $rawClassName, '\\'); $controllers[$path] = $className; @@ -296,7 +301,7 @@ final class Dispatcher extends RoutingBase { /** * Get the appropriate params for the error page - * pased on the failed route + * passed on the failed route * * @return array|false */ @@ -388,16 +393,15 @@ final class Dispatcher extends RoutingBase { if ( ! array_key_exists('tokens', $route)) { $routes[] = $this->router->$add($name, $path)->defaults($route); + continue; } - else - { - $tokens = $route['tokens']; - unset($route['tokens']); - $routes[] = $this->router->$add($name, $path) - ->defaults($route) - ->tokens($tokens); - } + $tokens = $route['tokens']; + unset($route['tokens']); + + $routes[] = $this->router->$add($name, $path) + ->defaults($route) + ->tokens($tokens); } return $routes; diff --git a/src/FormGenerator.php b/src/AnimeClient/FormGenerator.php similarity index 76% rename from src/FormGenerator.php rename to src/AnimeClient/FormGenerator.php index c535ca42..3e55dfe6 100644 --- a/src/FormGenerator.php +++ b/src/AnimeClient/FormGenerator.php @@ -4,19 +4,22 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; +use Aura\Html\HelperLocator; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; /** * Helper object to manage form generation, especially for config editing @@ -25,7 +28,7 @@ final class FormGenerator { /** * Html generation helper * - * @var \Aura\Html\HelperLocator + * @var HelperLocator */ private $helper; @@ -33,8 +36,8 @@ final class FormGenerator { * FormGenerator constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -51,19 +54,21 @@ final class FormGenerator { public function generate(string $name, array $form): string { $type = $form['type']; + $display = $form['display'] ?? TRUE; + $value = $form['value'] ?? ''; - if ($form['display'] === FALSE) + if ($display === FALSE) { - return $this->helper->input([ + return (string)$this->helper->input([ 'type' => 'hidden', 'name' => $name, - 'value' => $form['value'], + 'value' => $value, ]); } $params = [ 'name' => $name, - 'value' => $form['value'], + 'value' => $value, 'attribs' => [ 'id' => $name, ], @@ -92,7 +97,7 @@ final class FormGenerator { foreach (['readonly', 'disabled'] as $key) { - if ($form[$key] !== FALSE) + if (array_key_exists($key, $form) && $form[$key] !== FALSE) { $params['attribs'][$key] = $form[$key]; } diff --git a/src/Helper/Form.php b/src/AnimeClient/Helper/Form.php similarity index 90% rename from src/Helper/Form.php rename to src/AnimeClient/Helper/Form.php index efe099bf..9c20946b 100644 --- a/src/Helper/Form.php +++ b/src/AnimeClient/Helper/Form.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/Helper/Menu.php b/src/AnimeClient/Helper/Menu.php similarity index 90% rename from src/Helper/Menu.php rename to src/AnimeClient/Helper/Menu.php index faa32250..92378bae 100644 --- a/src/Helper/Menu.php +++ b/src/AnimeClient/Helper/Menu.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/Helper/Picture.php b/src/AnimeClient/Helper/Picture.php similarity index 94% rename from src/Helper/Picture.php rename to src/AnimeClient/Helper/Picture.php index 9e8b2dcc..d4741fb2 100644 --- a/src/Helper/Picture.php +++ b/src/AnimeClient/Helper/Picture.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -62,6 +62,9 @@ final class Picture { $urlGenerator = $this->container->get('url-generator'); $helper = $this->container->get('html-helper'); + $imgAttrs['loading'] = 'lazy'; + $picAttrs['loading'] = 'lazy'; + // If it is a placeholder image, make the // fallback a png, not a jpg if (strpos($uri, 'placeholder') !== FALSE) diff --git a/src/MenuGenerator.php b/src/AnimeClient/MenuGenerator.php similarity index 80% rename from src/MenuGenerator.php rename to src/AnimeClient/MenuGenerator.php index bcfb797a..e04f4f89 100644 --- a/src/MenuGenerator.php +++ b/src/AnimeClient/MenuGenerator.php @@ -4,23 +4,24 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; -use Aviat\Ion\{ - ArrayWrapper, StringWrapper -}; +use Aviat\Ion\{ArrayWrapper, StringWrapper}; +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; +use Aura\Html\HelperLocator; use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Exception\ConfigException; +use Psr\Http\Message\RequestInterface; /** * Helper object to manage menu creation and selection @@ -33,14 +34,14 @@ final class MenuGenerator extends UrlGenerator { /** * Html generation helper * - * @var \Aura\Html\HelperLocator + * @var HelperLocator */ protected $helper; /** * Request object * - * @var \Psr\Http\Message\RequestInterface + * @var RequestInterface */ protected $request; @@ -48,8 +49,8 @@ final class MenuGenerator extends UrlGenerator { * MenuGenerator constructor. * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -71,10 +72,10 @@ final class MenuGenerator extends UrlGenerator { foreach ($menus as $name => $menu) { $parsed[$name] = []; - foreach ($menu['items'] as $path_name => $partial_path) + foreach ($menu['items'] as $pathName => $partialPath) { - $title = (string)$this->string($path_name)->humanize()->titleize(); - $parsed[$name][$title] = (string)$this->string($menu['route_prefix'])->append($partial_path); + $title = (string)$this->string($pathName)->humanize()->titleize(); + $parsed[$name][$title] = (string)$this->string($menu['route_prefix'])->append($partialPath); } } diff --git a/src/Model/API.php b/src/AnimeClient/Model/API.php similarity index 90% rename from src/Model/API.php rename to src/AnimeClient/Model/API.php index ebc7c06c..19aaf1f5 100644 --- a/src/Model/API.php +++ b/src/AnimeClient/Model/API.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,7 +19,7 @@ namespace Aviat\AnimeClient\Model; /** * Base model for api interaction */ -class API { +abstract class API { /** * Sort the list entries by their title * diff --git a/src/Model/Anime.php b/src/AnimeClient/Model/Anime.php similarity index 80% rename from src/Model/Anime.php rename to src/AnimeClient/Model/Anime.php index 213a8bc3..83a25c30 100644 --- a/src/Model/Anime.php +++ b/src/AnimeClient/Model/Anime.php @@ -4,18 +4,20 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Model; +use Aviat\AnimeClient\API\Anilist\Model as AnilistModel; +use Aviat\AnimeClient\API\Kitsu\Model as KitsuModel; use Aviat\AnimeClient\API\ParallelAPIRequest; use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus; use Aviat\AnimeClient\Types\{ @@ -26,6 +28,8 @@ use Aviat\AnimeClient\Types\{ use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Json; +use Throwable; + /** * Model for handling requests dealing with the anime list */ @@ -41,14 +45,14 @@ class Anime extends API { /** * Model for making requests to Anilist API * - * @var \Aviat\AnimeClient\API\Anilist\Model + * @var AnilistModel */ protected $anilistModel; /** * Model for making requests to Kitsu API * - * @var \Aviat\AnimeClient\API\Kitsu\Model + * @var KitsuModel */ protected $kitsuModel; @@ -160,6 +164,7 @@ class Anime extends API { * * @param array $data * @return bool + * @throws Throwable */ public function createLibraryItem(array $data): bool { @@ -168,7 +173,12 @@ class Anime extends API { if ($this->anilistEnabled && $data['mal_id'] !== null) { - $requester->addRequest($this->anilistModel->createListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->createListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -181,6 +191,7 @@ class Anime extends API { * * @param FormItem $data * @return array + * @throws Throwable */ public function incrementLibraryItem(FormItem $data): array { @@ -189,7 +200,12 @@ class Anime extends API { if (( ! empty($data['mal_id'])) && $this->anilistEnabled) { - $requester->addRequest($this->anilistModel->incrementListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->incrementListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -208,6 +224,7 @@ class Anime extends API { * * @param FormItem $data * @return array + * @throws Throwable */ public function updateLibraryItem(FormItem $data): array { @@ -216,7 +233,12 @@ class Anime extends API { if (( ! empty($data['mal_id'])) && $this->anilistEnabled) { - $requester->addRequest($this->anilistModel->updateListItem($data, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->updateListItem($data, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); @@ -236,6 +258,7 @@ class Anime extends API { * @param string $id * @param string|null $malId * @return bool + * @throws Throwable */ public function deleteLibraryItem(string $id, string $malId = NULL): bool { @@ -244,7 +267,12 @@ class Anime extends API { if ($this->anilistEnabled && $malId !== null) { - $requester->addRequest($this->anilistModel->deleteListItem($malId, 'ANIME'), 'anilist'); + // If can't map MAL id, this will be null + $maybeRequest = $this->anilistModel->deleteListItem($malId, 'ANIME'); + if ($maybeRequest !== NULL) + { + $requester->addRequest($maybeRequest, 'anilist'); + } } $results = $requester->makeRequests(); diff --git a/src/Model/AnimeCollection.php b/src/AnimeClient/Model/AnimeCollection.php similarity index 89% rename from src/Model/AnimeCollection.php rename to src/AnimeClient/Model/AnimeCollection.php index 12b8e826..bc764ff4 100644 --- a/src/Model/AnimeCollection.php +++ b/src/AnimeClient/Model/AnimeCollection.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -75,6 +75,11 @@ final class AnimeCollection extends Collection { */ public function getMediaTypeList(): array { + if ($this->validDatabase === FALSE) + { + return []; + } + $output = []; $query = $this->db->select('id, type') @@ -136,6 +141,11 @@ final class AnimeCollection extends Collection { */ public function add($data): void { + if ($this->validDatabase === FALSE) + { + return; + } + $id = $data['id']; // Check that the anime doesn't already exist @@ -166,11 +176,16 @@ final class AnimeCollection extends Collection { /** * Verify that an item was added * - * @param $data + * @param array|null|object $data * @return bool */ public function wasAdded($data): bool { + if ($this->validDatabase === FALSE) + { + return FALSE; + } + $row = $this->get($data['id']); return ! empty($row); @@ -184,6 +199,11 @@ final class AnimeCollection extends Collection { */ public function update($data): void { + if ($this->validDatabase === FALSE) + { + return; + } + // If there's no id to update, don't update if ( ! array_key_exists('hummingbird_id', $data)) { @@ -204,11 +224,17 @@ final class AnimeCollection extends Collection { /** * Verify that the collection item was updated * - * @param $data + * @param array|null|object $data + * * @return bool */ public function wasUpdated($data): bool { + if ($this->validDatabase === FALSE) + { + return FALSE; + } + $row = $this->get($data['hummingbird_id']); foreach ($data as $key => $value) @@ -230,6 +256,11 @@ final class AnimeCollection extends Collection { */ public function delete($data): void { + if ($this->validDatabase === FALSE) + { + return; + } + // If there's no id to update, don't delete if ( ! array_key_exists('hummingbird_id', $data)) { @@ -243,8 +274,17 @@ final class AnimeCollection extends Collection { ->delete('anime_set'); } + /** + * @param array|null|object $data + * @return bool + */ public function wasDeleted($data): bool { + if ($this->validDatabase === FALSE) + { + return FALSE; + } + $animeRow = $this->get($data['hummingbird_id']); return empty($animeRow); @@ -258,6 +298,11 @@ final class AnimeCollection extends Collection { */ public function get($kitsuId) { + if ($this->validDatabase === FALSE) + { + return FALSE; + } + $query = $this->db->from('anime_set') ->where('hummingbird_id', $kitsuId) ->get(); @@ -273,6 +318,11 @@ final class AnimeCollection extends Collection { */ public function getGenreList(array $filter = []): array { + if ($this->validDatabase === FALSE) + { + return []; + } + $output = []; // Catch the missing table PDOException @@ -330,6 +380,11 @@ final class AnimeCollection extends Collection { */ private function updateGenre($animeId): void { + if ($this->validDatabase === FALSE) + { + return; + } + // Get api information $anime = $this->animeModel->getAnimeById($animeId); @@ -372,6 +427,11 @@ final class AnimeCollection extends Collection { */ private function addNewGenres(array $genres): void { + if ($this->validDatabase === FALSE) + { + return; + } + $existingGenres = $this->getExistingGenres(); $newGenres = array_diff($genres, $existingGenres); @@ -409,6 +469,11 @@ final class AnimeCollection extends Collection { private function getExistingGenres(): array { + if ($this->validDatabase === FALSE) + { + return []; + } + $genres = []; // Get existing genres @@ -428,6 +493,11 @@ final class AnimeCollection extends Collection { private function getExistingGenreLinkEntries(): array { + if ($this->validDatabase === FALSE) + { + return []; + } + $links = []; $query = $this->db->select('hummingbird_id, genre_id') diff --git a/src/Model/Collection.php b/src/AnimeClient/Model/Collection.php similarity index 85% rename from src/Model/Collection.php rename to src/AnimeClient/Model/Collection.php index ea99f191..eeb32fcd 100644 --- a/src/Model/Collection.php +++ b/src/AnimeClient/Model/Collection.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,6 +19,7 @@ namespace Aviat\AnimeClient\Model; use Aviat\Ion\Di\ContainerInterface; use PDOException; +use Query\Query_Builder_Interface; use function Query; /** @@ -28,7 +29,7 @@ class Collection extends DB { /** * The query builder object - * @var \Query\Query_Builder_Interface + * @var Query_Builder_Interface */ protected $db; @@ -52,7 +53,13 @@ class Collection extends DB { $this->db = Query($this->dbConfig); $this->validDatabase = TRUE; } - catch (PDOException $e) {} + catch (PDOException $e) + { + $this->db = Query([ + 'type' => 'sqlite', + 'file' => ':memory:', + ]); + } // Is database valid? If not, set a flag so the // app can be run without a valid database diff --git a/src/Model/DB.php b/src/AnimeClient/Model/DB.php similarity index 89% rename from src/Model/DB.php rename to src/AnimeClient/Model/DB.php index f66b71e3..d69481ec 100644 --- a/src/Model/DB.php +++ b/src/AnimeClient/Model/DB.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -21,7 +21,7 @@ use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; /** * Base model for database interaction */ -class DB { +abstract class DB { use ContainerAware; /** diff --git a/src/Model/Manga.php b/src/AnimeClient/Model/Manga.php similarity index 96% rename from src/Model/Manga.php rename to src/AnimeClient/Model/Manga.php index 2acad927..9ff04072 100644 --- a/src/Model/Manga.php +++ b/src/AnimeClient/Model/Manga.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -29,6 +29,8 @@ use Aviat\AnimeClient\Types\{ use Aviat\Ion\Di\ContainerInterface; use Aviat\Ion\Json; +use Throwable; + /** * Model for handling requests dealing with the manga list */ @@ -130,6 +132,7 @@ class Manga extends API { * * @param array $data * @return bool + * @throws Throwable */ public function createLibraryItem(array $data): bool { @@ -151,6 +154,7 @@ class Manga extends API { * * @param FormItem $data * @return array + * @throws Throwable */ public function updateLibraryItem(FormItem $data): array { @@ -179,6 +183,7 @@ class Manga extends API { * * @param FormItem $data * @return array + * @throws Throwable */ public function incrementLibraryItem(FormItem $data): array { @@ -208,6 +213,7 @@ class Manga extends API { * @param string $id * @param string|null $malId * @return bool + * @throws Throwable */ public function deleteLibraryItem(string $id, string $malId = NULL): bool { diff --git a/src/AnimeClient/Model/MangaCollection.php b/src/AnimeClient/Model/MangaCollection.php new file mode 100644 index 00000000..b1185d44 --- /dev/null +++ b/src/AnimeClient/Model/MangaCollection.php @@ -0,0 +1,43 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\Model; + +use Aviat\Ion\Di\ContainerInterface; + +/** + * Model for getting anime collection data + */ +final class MangaCollection extends Collection { + + /** + * Manga API Model + * @var Manga $mangaModel + */ + protected $mangaModel; + + /** + * Create the collection model + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + parent::__construct($container); + $this->mangaModel = $container->get('manga-model'); + } +} +// End of MangaCollectionModel.php \ No newline at end of file diff --git a/src/Model/Settings.php b/src/AnimeClient/Model/Settings.php similarity index 96% rename from src/Model/Settings.php rename to src/AnimeClient/Model/Settings.php index 90d0f582..92dc1e91 100644 --- a/src/Model/Settings.php +++ b/src/AnimeClient/Model/Settings.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -207,7 +207,7 @@ final class Settings { return FALSE; } - $savePath = realpath(_dir(__DIR__, '..', '..', 'app', 'config')); + $savePath = realpath(_dir(__DIR__, '..', '..', '..', 'app', 'config')); $saveFile = _dir($savePath, 'admin-override.toml'); $saved = file_put_contents($saveFile, arrayToToml($settings)); diff --git a/src/RoutingBase.php b/src/AnimeClient/RoutingBase.php similarity index 73% rename from src/RoutingBase.php rename to src/AnimeClient/RoutingBase.php index 90a6424c..34c0deec 100644 --- a/src/RoutingBase.php +++ b/src/AnimeClient/RoutingBase.php @@ -4,20 +4,25 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; +use Aviat\Ion\Config; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; +use Aviat\Ion\Exception\ConfigException; use Aviat\Ion\StringWrapper; +use Psr\Http\Message\ServerRequestInterface; /** * Base for routing/url classes @@ -34,13 +39,13 @@ class RoutingBase { /** * Config Object - * @var \Aviat\Ion\Config + * @var Config */ protected $config; /** * Class wrapper for input superglobals - * @var \Psr\Http\Message\ServerRequestInterface + * @var ServerRequestInterface */ protected $request; @@ -48,9 +53,9 @@ class RoutingBase { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException - * @throws \Aviat\Ion\Exception\ConfigException + * @throws ContainerException + * @throws NotFoundException + * @throws ConfigException */ public function __construct(ContainerInterface $container) { @@ -61,8 +66,8 @@ class RoutingBase { /** * Get the current url path - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return string */ public function path(): string @@ -79,8 +84,8 @@ class RoutingBase { /** * Get the url segments - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return array */ public function segments(): array @@ -93,8 +98,8 @@ class RoutingBase { * Get a segment of the current url * * @param int $num - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return string|null */ public function getSegment($num): ?string @@ -106,8 +111,8 @@ class RoutingBase { /** * Retrieve the last url segment * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return string */ public function lastSegment(): string diff --git a/src/Types/AbstractType.php b/src/AnimeClient/Types/AbstractType.php similarity index 87% rename from src/Types/AbstractType.php rename to src/AnimeClient/Types/AbstractType.php index 6c04ffd6..d4a3c548 100644 --- a/src/Types/AbstractType.php +++ b/src/AnimeClient/Types/AbstractType.php @@ -4,20 +4,19 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Types; use ArrayAccess; -use ArrayObject; use Countable; abstract class AbstractType implements ArrayAccess, Countable { @@ -25,7 +24,7 @@ abstract class AbstractType implements ArrayAccess, Countable { * Populate values for un-serializing data * * @param $properties - * @return mixed + * @return self */ public static function __set_state($properties): self { @@ -37,7 +36,7 @@ abstract class AbstractType implements ArrayAccess, Countable { * * @param mixed $data */ - public function __construct($data = []) + final public function __construct($data = []) { $typeKeys = array_keys((array)$this); $dataKeys = array_keys((array)$data); @@ -64,7 +63,7 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function __isset($name): bool { - return property_exists($this, $name); + return property_exists($this, $name) && isset($this->$name); } /** @@ -102,12 +101,9 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function __get($name) { - if (property_exists($this, $name)) - { - return $this->$name; - } - - throw new UndefinedPropertyException("Trying to get undefined property: '$name'"); + // Be a bit more lenient here, so that you can easily typecast missing + // values to reasonable defaults, and not have to resort to array indexes + return ($this->__isset($name)) ? $this->$name : NULL; } /** @@ -180,14 +176,14 @@ abstract class AbstractType implements ArrayAccess, Countable { /** * Recursively cast properties to an array * - * @param null $parent + * @param mixed $parent * @return mixed */ public function toArray($parent = null) { $object = $parent ?? $this; - if (is_scalar($object) || empty($object)) + if (is_scalar($object) || $object === NULL) { return $object; } @@ -211,7 +207,7 @@ abstract class AbstractType implements ArrayAccess, Countable { */ public function isEmpty(): bool { - foreach ($this as $key => $value) + foreach ($this as $value) { if ( ! empty($value)) { diff --git a/src/Types/Anime.php b/src/AnimeClient/Types/Anime.php similarity index 55% rename from src/Types/Anime.php rename to src/AnimeClient/Types/Anime.php index eece5055..1b74b029 100644 --- a/src/Types/Anime.php +++ b/src/AnimeClient/Types/Anime.php @@ -4,37 +4,106 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Types; +use Aviat\AnimeClient\API\Kitsu\Enum\AnimeAiringStatus; + /** * Type representing an anime within a watch list */ class Anime extends AbstractType { + /** + * @var string + */ public $age_rating; + + /** + * @var string + */ public $age_rating_guide; + + /** + * @var string + */ public $cover_image; + + /** + * @var string|int + */ public $episode_count; + + /** + * @var string|int + */ public $episode_length; + + /** + * @var array + */ public $genres; + + /** + * @var string + */ public $id; + + /** + * @var array + */ public $included; + + /** + * @var string + */ public $show_type; + + /** + * @var string + */ public $slug; + + /** + * @var AnimeAiringStatus::NOT_YET_AIRED | AnimeAiringStatus::AIRING | AnimeAiringStatus::FINISHED_AIRING + */ public $status; + + /** + * @var array + */ public $streaming_links; + + /** + * @var string + */ public $synopsis; + + /** + * @var string + */ public $title; + + /** + * @var array + */ public $titles; + + /** + * @var string + */ public $trailer_id; + + /** + * @var string + */ public $url; } \ No newline at end of file diff --git a/src/Types/AnimeListItem.php b/src/AnimeClient/Types/AnimeListItem.php similarity index 68% rename from src/Types/AnimeListItem.php rename to src/AnimeClient/Types/AnimeListItem.php index 676e2e03..89c7d8b7 100644 --- a/src/Types/AnimeListItem.php +++ b/src/AnimeClient/Types/AnimeListItem.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,25 +20,74 @@ namespace Aviat\AnimeClient\Types; * Type representing an anime watch list item */ final class AnimeListItem extends AbstractType { + /** + * @var string + */ public $id; + + /** + * @var string + */ public $mal_id; + + /** + * @var string + */ public $anilist_item_id; + + /** + * @var array + */ public $episodes = [ 'length' => 0, 'total' => 0, 'watched' => '', ]; + + /** + * @var array + */ public $airing = [ 'status' => '', 'started' => '', 'ended' => '', ]; + + /** + * @var Anime + */ public $anime; + + /** + * @var string + */ public $notes = ''; + + /** + * @var bool + */ public $private; + + /** + * @var bool + */ public $rewatching; + + /** + * @var int + */ public $rewatched; + + /** + * @var int + */ public $user_rating; + + /** + * One of Aviat\AnimeClient\API\Enum\AnimeWatchingStatus + * + * @var string + */ public $watching_status; public function setAnime($anime): void diff --git a/src/Types/AnimePage.php b/src/AnimeClient/Types/AnimePage.php similarity index 80% rename from src/Types/AnimePage.php rename to src/AnimeClient/Types/AnimePage.php index e9d7b33a..5b2f2f6b 100644 --- a/src/Types/AnimePage.php +++ b/src/AnimeClient/Types/AnimePage.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,6 +20,13 @@ namespace Aviat\AnimeClient\Types; * Type representing an Anime object for a detail page */ final class AnimePage extends Anime { + /** + * @var array + */ public $characters; + + /** + * @var array + */ public $staff; } \ No newline at end of file diff --git a/src/Types/Character.php b/src/AnimeClient/Types/Character.php similarity index 68% rename from src/Types/Character.php rename to src/AnimeClient/Types/Character.php index 628ebcd8..d99154b7 100644 --- a/src/Types/Character.php +++ b/src/AnimeClient/Types/Character.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,20 +20,48 @@ namespace Aviat\AnimeClient\Types; * Type representing a character for display */ final class Character extends AbstractType { + /** + * @var array + */ public $castings; + + /** + * @var string + */ public $description; + + /** + * @var string + */ public $id; + + /** + * @var array + */ public $included; + + /** + * @var Media + */ public $media; + + /** + * @var string + */ public $name; + + /** + * @var array + */ public $names; + + /** + * @var array + */ public $otherNames; public function setMedia ($media): void { - $this->media = new class($media) extends AbstractType { - public $anime; - public $manga; - }; + $this->media = new Media($media); } } \ No newline at end of file diff --git a/src/AnimeClient/Types/Characters.php b/src/AnimeClient/Types/Characters.php new file mode 100644 index 00000000..28d0ae6f --- /dev/null +++ b/src/AnimeClient/Types/Characters.php @@ -0,0 +1,29 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\Types; + +final class Characters extends AbstractType { + /** + * @var array + */ + public $main; + + /** + * @var array + */ + public $supporting; +} \ No newline at end of file diff --git a/src/AnimeClient/Types/Config.php b/src/AnimeClient/Types/Config.php new file mode 100644 index 00000000..1eeed209 --- /dev/null +++ b/src/AnimeClient/Types/Config.php @@ -0,0 +1,177 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\Types; + +class Config extends AbstractType { + + // ------------------------------------------------------------------------ + // Config files/namespaces + // ------------------------------------------------------------------------ + + /** + * @var Config\Anilist + */ + public $anilist; + + /** + * @var Config\Cache + */ + public $cache; + + /** + * @var Config\Database + */ + public $database; + + // ------------------------------------------------------------------------ + // Settings in config.toml + // ------------------------------------------------------------------------ + + /** + * @var string + */ + public $asset_path; // Path to public folder for urls + + /** + * @deprecated Use 'theme' instead + * @var bool + */ + public $dark_theme; /* Deprecated */ + + /** + * Default Anime list status page, values are listed in + * Aviat\AnimeClient\API\Enum\AnimeWatchingStatus\Title + * + * @var string + */ + public $default_anime_list_path; + + /** + * The list to redirect to from the root url + * + * @var 'anime' | 'manga' + */ + public $default_list; + + /** + * Default Manga list status page, values are listed in + * Aviat\AnimeClient\API\Enum\MangaReadingStatus\Title + * + * @var string + */ + public $default_manga_list_path; + + /** + * @var 'cover_view' | 'list_view' + */ + public $default_view_type; + + /** + * @var string + */ + public $kitsu_username; + + /** + * @var bool + */ + public $secure_urls = TRUE; + + /** + * @var bool + */ + public $show_anime_collection; + + /** + * @var bool + */ + public $show_manga_collection = FALSE; + + /** + * CSS theme: light, dark, or auto-switching + * + * @var 'auto' | 'light' | 'dark' + */ + public $theme; + + /** + * @var string + */ + public $whose_list; + + // ------------------------------------------------------------------------ + // Application config + // ------------------------------------------------------------------------ + + /** + * @var array + */ + public $menus; + + /** + * @var array + */ + public $routes; + + // ------------------------------------------------------------------------ + // Generated config values + // ------------------------------------------------------------------------ + + /** + * @var string + */ + public $asset_dir; // Path to public folder for local files + + /** + * @var string + */ + public $base_config_dir; + + /** + * @var string + */ + public $config_dir; + + /** + * @var string + */ + public $data_cache_path; + + /** + * @var string + */ + public $img_cache_path; + + /** + * @var string + */ + public $view_path; + + public function setAnilist ($data): void + { + $this->anilist = new Config\Anilist($data); + } + + public function setCache ($data): void + { + $this->cache = new Config\Cache($data); + } + + public function setDatabase ($data): void + { + $this->database = new Config\Database($data); + } +} \ No newline at end of file diff --git a/src/Types/Config/Anilist.php b/src/AnimeClient/Types/Config/Anilist.php similarity index 72% rename from src/Types/Config/Anilist.php rename to src/AnimeClient/Types/Config/Anilist.php index 0636e478..0a77a62e 100644 --- a/src/Types/Config/Anilist.php +++ b/src/AnimeClient/Types/Config/Anilist.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,14 +19,38 @@ namespace Aviat\AnimeClient\Types\Config; use Aviat\AnimeClient\Types\AbstractType; class Anilist extends AbstractType { + /** + * @var bool + */ public $enabled = FALSE; + /** + * @var string + */ public $client_id; + + /** + * @var string + */ public $client_secret; + /** + * @var string + */ public $access_token; + + /** + * @var string + */ public $access_token_expires; + + /** + * @var string + */ public $refresh_token; + /** + * @var string + */ public $username; } \ No newline at end of file diff --git a/src/Types/Config/Cache.php b/src/AnimeClient/Types/Config/Cache.php similarity index 73% rename from src/Types/Config/Cache.php rename to src/AnimeClient/Types/Config/Cache.php index 929b4531..b9a5f51b 100644 --- a/src/Types/Config/Cache.php +++ b/src/AnimeClient/Types/Config/Cache.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,14 +19,18 @@ namespace Aviat\AnimeClient\Types\Config; use Aviat\AnimeClient\Types\AbstractType; class Cache extends AbstractType { + /** + * @var string + */ public $driver; + + /** + * @var array + */ public $connection = []; + + /** + * @var array + */ public $options = []; - - /* public function setConnection($data): void - { - $this->connection = new class($data) extends AbstractType { - - }; - } */ } \ No newline at end of file diff --git a/src/Types/Config/Database.php b/src/AnimeClient/Types/Config/Database.php similarity index 69% rename from src/Types/Config/Database.php rename to src/AnimeClient/Types/Config/Database.php index 8c807caa..84d1b4a8 100644 --- a/src/Types/Config/Database.php +++ b/src/AnimeClient/Types/Config/Database.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,11 +19,38 @@ namespace Aviat\AnimeClient\Types\Config; use Aviat\AnimeClient\Types\AbstractType; class Database extends AbstractType { + /** + * @var string + */ public $type; + + /** + * @var string + */ public $host; + + /** + * @var string + */ public $user; + + /** + * @var string + */ public $pass; + + /** + * @var string|int + */ public $port; + + /** + * @var string + */ public $database; + + /** + * @var string + */ public $file; } \ No newline at end of file diff --git a/src/Types/FormItem.php b/src/AnimeClient/Types/FormItem.php similarity index 77% rename from src/Types/FormItem.php rename to src/AnimeClient/Types/FormItem.php index 7a309231..135f9aa9 100644 --- a/src/Types/FormItem.php +++ b/src/AnimeClient/Types/FormItem.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,9 +20,24 @@ namespace Aviat\AnimeClient\Types; * Type representing an Anime object for display */ class FormItem extends AbstractType { + /** + * @var string + */ public $id; + + /** + * @var string + */ public $anilist_item_id; + + /** + * @var string + */ public $mal_id; + + /** + * @var FormItemData + */ public $data; public function setData($value): void diff --git a/src/Types/FormItemData.php b/src/AnimeClient/Types/FormItemData.php similarity index 67% rename from src/Types/FormItemData.php rename to src/AnimeClient/Types/FormItemData.php index 7c1e635f..03951cd2 100644 --- a/src/Types/FormItemData.php +++ b/src/AnimeClient/Types/FormItemData.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,13 +20,50 @@ namespace Aviat\AnimeClient\Types; * Type representing a Media object for editing/syncing */ class FormItemData extends AbstractType { + /** + * @var string + */ public $notes; + + /** + * @var bool + */ public $private; + + /** + * @var int + */ public $progress; + + /** + * @var int + */ public $rating; + + /** + * @var int + */ public $ratingTwenty; + + /** + * @var int + */ public $reconsumeCount; + + /** + * @var bool + */ public $reconsuming; + + /** + * @var string + */ public $status; + + /** + * W3C Format Date string + * + * @var string + */ public $updatedAt; } diff --git a/src/Types/MangaListItem.php b/src/AnimeClient/Types/MangaListItem.php similarity index 70% rename from src/Types/MangaListItem.php rename to src/AnimeClient/Types/MangaListItem.php index c4ce3943..b4dda4ce 100644 --- a/src/Types/MangaListItem.php +++ b/src/AnimeClient/Types/MangaListItem.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,21 +20,60 @@ namespace Aviat\AnimeClient\Types; * Type representing an Anime object for display */ final class MangaListItem extends AbstractType { + /** + * @var string + */ public $id; + + /** + * @var string + */ public $mal_id; + + /** + * @var array + */ public $chapters = [ 'read' => 0, 'total' => 0, ]; + + /** + * @var array + */ public $volumes = [ 'read' => '-', 'total' => 0, ]; + + /** + * @var object + */ public $manga; + + /** + * @var string + */ public $reading_status; + + /** + * @var string + */ public $notes; + + /** + * @var bool + */ public $rereading; + + /** + * @var int + */ public $reread; + + /** + * @var int + */ public $user_rating; } diff --git a/src/Types/MangaListItemDetail.php b/src/AnimeClient/Types/MangaListItemDetail.php similarity index 69% rename from src/Types/MangaListItemDetail.php rename to src/AnimeClient/Types/MangaListItemDetail.php index 6be6e8ab..55885b95 100644 --- a/src/Types/MangaListItemDetail.php +++ b/src/AnimeClient/Types/MangaListItemDetail.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,12 +20,43 @@ namespace Aviat\AnimeClient\Types; * Type representing the manga represented by the list item */ final class MangaListItemDetail extends AbstractType { + /** + * @var array + */ public $genres; + + /** + * @var string + */ public $id; + + /** + * @var string + */ public $image; + + /** + * @var string + */ public $slug; + + /** + * @var string + */ public $title; + + /** + * @var array + */ public $titles; + + /** + * @var string + */ public $type; + + /** + * @var string + */ public $url; } diff --git a/src/Types/MangaPage.php b/src/AnimeClient/Types/MangaPage.php similarity index 64% rename from src/Types/MangaPage.php rename to src/AnimeClient/Types/MangaPage.php index 2fa0b4e7..802d2f03 100644 --- a/src/Types/MangaPage.php +++ b/src/AnimeClient/Types/MangaPage.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,17 +20,68 @@ namespace Aviat\AnimeClient\Types; * Type representing an Anime object for display */ final class MangaPage extends AbstractType { + /** + * @var array + */ public $characters; + + /** + * @var int + */ public $chapter_count; + + /** + * @var string + */ public $cover_image; + + /** + * @var array + */ public $genres; + + /** + * @var string + */ public $id; + + /** + * @var array + */ public $included; + + /** + * @var string + */ public $manga_type; + + /** + * @var array + */ public $staff; + + /** + * @var string + */ public $synopsis; + + /** + * @var string + */ public $title; + + /** + * @var array + */ public $titles; + + /** + * @var string + */ public $url; + + /** + * @var int + */ public $volume_count; } diff --git a/src/AnimeClient/Types/Media.php b/src/AnimeClient/Types/Media.php new file mode 100644 index 00000000..f1064d6f --- /dev/null +++ b/src/AnimeClient/Types/Media.php @@ -0,0 +1,29 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\Types; + +final class Media extends AbstractType { + /** + * @var array + */ + public $anime = []; + + /** + * @var array + */ + public $manga = []; +} \ No newline at end of file diff --git a/src/Types/Person.php b/src/AnimeClient/Types/Person.php similarity index 72% rename from src/Types/Person.php rename to src/AnimeClient/Types/Person.php index df4a9f0c..d21f926e 100644 --- a/src/Types/Person.php +++ b/src/AnimeClient/Types/Person.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,16 +20,28 @@ namespace Aviat\AnimeClient\Types; * Type representing a person for display */ final class Person extends AbstractType { + /** + * @var string + */ public $id; + + /** + * @var string + */ public $name; + + /** + * @var Characters + */ public $characters; + + /** + * @var array + */ public $staff; public function setCharacters($characters): void { - $this->characters = new class($characters) extends AbstractType { - public $main; - public $supporting; - }; + $this->characters = new Characters($characters); } } \ No newline at end of file diff --git a/src/Types/UndefinedPropertyException.php b/src/AnimeClient/Types/UndefinedPropertyException.php similarity index 85% rename from src/Types/UndefinedPropertyException.php rename to src/AnimeClient/Types/UndefinedPropertyException.php index ff46700b..0cdc288e 100644 --- a/src/Types/UndefinedPropertyException.php +++ b/src/AnimeClient/Types/UndefinedPropertyException.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/src/Types/User.php b/src/AnimeClient/Types/User.php similarity index 67% rename from src/Types/User.php rename to src/AnimeClient/Types/User.php index 6f79bf34..1ff091af 100644 --- a/src/Types/User.php +++ b/src/AnimeClient/Types/User.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,13 +20,48 @@ namespace Aviat\AnimeClient\Types; * Type representing a Kitsu user for display */ final class User extends AbstractType { + /** + * @var string + */ public $about; + + /** + * @var string + */ public $avatar; + + /** + * @var array + */ public $favorites; + + /** + * @var string + */ public $location; + + /** + * @var string + */ public $name; + + /** + * @var string + */ public $slug; + + /** + * @var array + */ public $stats; + + /** + * @var array + */ public $waifu; + + /** + * @var string + */ public $website; } \ No newline at end of file diff --git a/src/UrlGenerator.php b/src/AnimeClient/UrlGenerator.php similarity index 81% rename from src/UrlGenerator.php rename to src/AnimeClient/UrlGenerator.php index 5b445f53..831272cd 100644 --- a/src/UrlGenerator.php +++ b/src/AnimeClient/UrlGenerator.php @@ -4,19 +4,21 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; use InvalidArgumentException; /** @@ -34,8 +36,8 @@ class UrlGenerator extends RoutingBase { * Constructor * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\Exception\ContainerException - * @throws \Aviat\Ion\Di\Exception\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -47,7 +49,7 @@ class UrlGenerator extends RoutingBase { /** * Get the base url for css/js/images * - * @param string[] $args + * @param string ...$args * @return string */ public function assetUrl(string ...$args): string @@ -74,20 +76,20 @@ class UrlGenerator extends RoutingBase { // Remove any optional parameters from the route // and replace them with existing route parameters, if they exist - $path_segments = explode('/', $path); - $segment_count = count($path_segments); + $pathSegments = explode('/', $path); + $segmentCount = count($pathSegments); $segments = $this->segments(); - for ($i = 0; $i < $segment_count; $i++) + for ($i = 0; $i < $segmentCount; $i++) { if ( ! array_key_exists($i + 1, $segments)) { $segments[$i + 1] = ''; } - $path_segments[$i] = preg_replace('`{.*?}`', $segments[$i + 1], $path_segments[$i]); + $pathSegments[$i] = preg_replace('`{.*?}`', $segments[$i + 1], $pathSegments[$i]); } - $path = implode('/', $path_segments); + $path = implode('/', $pathSegments); $scheme = $this->config->get('secure_urls') !== FALSE ? 'https:' : 'http:'; diff --git a/src/Util.php b/src/AnimeClient/Util.php similarity index 65% rename from src/Util.php rename to src/AnimeClient/Util.php index b7cff001..4e03218d 100644 --- a/src/Util.php +++ b/src/AnimeClient/Util.php @@ -4,19 +4,20 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient; -use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; +use Aviat\Ion\Di\{ContainerAware, ContainerInterface}; +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; /** * Utility method class @@ -45,8 +46,8 @@ class Util { * Set up the Util class * * @param ContainerInterface $container - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException */ public function __construct(ContainerInterface $container) { @@ -56,32 +57,32 @@ class Util { /** * HTML selection helper function * - * @param string $a - First item to compare - * @param string $b - Second item to compare + * @param string $left - First item to compare + * @param string $right - Second item to compare * @return string */ - public static function isSelected(string $a, string $b): string + public static function isSelected(string $left, string $right): string { - return ($a === $b) ? 'selected' : ''; + return ($left === $right) ? 'selected' : ''; } /** * Inverse of selected helper function * - * @param string $a - First item to compare - * @param string $b - Second item to compare + * @param string $left - First item to compare + * @param string $right - Second item to compare * @return string */ - public static function isNotSelected(string $a, string $b): string + public static function isNotSelected(string $left, string $right): string { - return ($a !== $b) ? 'selected' : ''; + return ($left !== $right) ? 'selected' : ''; } /** * Determine whether to show the sub-menu * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return bool */ public function isViewPage(): bool @@ -98,8 +99,8 @@ class Util { * Determine whether the page is a page with a form, and * not suitable for redirection * - * @throws \Aviat\Ion\Di\ContainerException - * @throws \Aviat\Ion\Di\NotFoundException + * @throws ContainerException + * @throws NotFoundException * @return bool */ public function isFormPage(): bool diff --git a/src/constants.php b/src/AnimeClient/constants.php similarity index 94% rename from src/constants.php rename to src/AnimeClient/constants.php index c70baa4c..3a54a8b0 100644 --- a/src/constants.php +++ b/src/AnimeClient/constants.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -24,7 +24,7 @@ const ERROR_MESSAGE_METHOD = 'errorPage'; const NOT_FOUND_METHOD = 'notFound'; const SESSION_SEGMENT = 'Aviat\AnimeClient\Auth'; const SRC_DIR = __DIR__; -const USER_AGENT = "Tim's Anime Client/4.1"; +const USER_AGENT = "Tim's Anime Client/4.2"; // Regex patterns const ALPHA_SLUG_PATTERN = '[a-z_]+'; @@ -133,11 +133,6 @@ const SETTINGS_MAP = [ ], ], ], - /* 'options' => [ - 'type' => 'subfield', - 'title' => 'Options', - 'fields' => [], - ] */ ], 'config' => [ 'kitsu_username' => [ @@ -163,12 +158,6 @@ const SETTINGS_MAP = [ 'Dark Theme' => 'dark', ] ], - /* 'dark_theme' => [ - 'type' => 'boolean', - 'title' => 'Use Dark Theme', - 'default' => FALSE, - 'description' => 'Use a darker background theme?', - ],*/ 'show_anime_collection' => [ 'type' => 'boolean', 'title' => 'Show Anime Collection', diff --git a/src/Ion/ArrayWrapper.php b/src/Ion/ArrayWrapper.php new file mode 100644 index 00000000..8a2eca7d --- /dev/null +++ b/src/Ion/ArrayWrapper.php @@ -0,0 +1,38 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Aviat\Ion\Type\ArrayType; + +/** + * Wrapper to shortcut creating ArrayType objects + */ +trait ArrayWrapper { + + /** + * Convenience method for wrapping an array + * with the array type class + * + * @param array $arr + * @return ArrayType + */ + public function arr(array $arr): ArrayType + { + return new ArrayType($arr); + } +} +// End of ArrayWrapper.php \ No newline at end of file diff --git a/src/Ion/Config.php b/src/Ion/Config.php new file mode 100644 index 00000000..c3d3ea8f --- /dev/null +++ b/src/Ion/Config.php @@ -0,0 +1,120 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Aviat\Ion\Exception\ConfigException; +use Aviat\Ion\Type\ArrayType; +use InvalidArgumentException; + +/** + * Wrapper for configuration values + */ +class Config implements ConfigInterface { + + use ArrayWrapper; + + /** + * Config object + * + * @var ArrayType + */ + protected $map; + + /** + * Constructor + * + * @param array $configArray + */ + public function __construct(array $configArray = []) + { + $this->map = $this->arr($configArray); + } + + /** + * Does the config item exist? + * + * @param string|int|array $key + * @return bool + */ + public function has($key): bool + { + return $this->map->hasKey($key); + } + + /** + * Get a config value + * + * @param array|string|null $key + * @return mixed + * @throws ConfigException + */ + public function get($key = NULL) + { + if (\is_array($key)) + { + return $this->map->getDeepKey($key); + } + + return $this->map->get($key); + } + + /** + * Remove a config value + * + * @param string|array $key + * @return void + */ + public function delete($key): void + { + if (\is_array($key)) + { + $this->map->setDeepKey($key, NULL); + } + else + { + $pos =& $this->map->get($key); + $pos = NULL; + } + } + + /** + * Set a config value + * + * @param integer|string|array $key + * @param mixed $value + * @throws InvalidArgumentException + * @return ConfigInterface + */ + public function set($key, $value): ConfigInterface + { + if (\is_array($key)) + { + $this->map->setDeepKey($key, $value); + } + else if (is_scalar($key) && ! empty($key)) + { + $this->map->set($key, $value); + } + else + { + throw new InvalidArgumentException('Key must be integer, string, or array, and cannot be empty'); + } + + return $this; + } +} +// End of config.php \ No newline at end of file diff --git a/src/Ion/ConfigInterface.php b/src/Ion/ConfigInterface.php new file mode 100644 index 00000000..9d0e4e3e --- /dev/null +++ b/src/Ion/ConfigInterface.php @@ -0,0 +1,56 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +/** + * Standard interface for retrieving/setting configuration values + */ +interface ConfigInterface { + /** + * Does the config item exist? + * + * @param string|int|array $key + * @return bool + */ + public function has($key): bool; + + /** + * Get a config value + * + * @param array|string|null $key + * @return mixed + */ + public function get($key = NULL); + + /** + * Set a config value + * + * @param integer|string|array $key + * @param mixed $value + * @throws \InvalidArgumentException + * @return ConfigInterface + */ + public function set($key, $value): self; + + /** + * Remove a config value + * + * @param string|array $key + * @return void + */ + public function delete($key): void; +} \ No newline at end of file diff --git a/src/Ion/Di/Container.php b/src/Ion/Di/Container.php new file mode 100644 index 00000000..e6bfea93 --- /dev/null +++ b/src/Ion/Di/Container.php @@ -0,0 +1,228 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di; + +use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException}; +use Psr\Log\LoggerInterface; + +/** + * Dependency container + */ +class Container implements ContainerInterface { + + /** + * Array of container Generator functions + * + * @var Callable[] + */ + protected $container = []; + + /** + * Array of object instances + * + * @var array + */ + protected $instances = []; + + /** + * Map of logger instances + * + * @var array + */ + protected $loggers = []; + + /** + * Constructor + * + * @param array $values (optional) + */ + public function __construct(array $values = []) + { + $this->container = $values; + $this->loggers = []; + } + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id - Identifier of the entry to look for. + * + * @throws NotFoundException - No entry was found for this identifier. + * @throws ContainerException - Error while retrieving the entry. + * + * @return mixed Entry. + */ + public function get($id) + { + if ( ! \is_string($id)) + { + throw new ContainerException('Id must be a string'); + } + + if ($this->has($id)) + { + // Return an object instance, if it already exists + if (array_key_exists($id, $this->instances)) + { + return $this->instances[$id]; + } + + // If there isn't already an instance, create one + $obj = $this->getNew($id); + $this->instances[$id] = $obj; + return $obj; + } + + throw new NotFoundException("Item '{$id}' does not exist in container."); + } + + /** + * Get a new instance of the specified item + * + * @param string $id - Identifier of the entry to look for. + * @param array $args - Optional arguments for the factory callable + * @throws NotFoundException - No entry was found for this identifier. + * @throws ContainerException - Error while retrieving the entry. + * @return mixed + */ + public function getNew($id, array $args = NULL) + { + if ( ! \is_string($id)) + { + throw new ContainerException('Id must be a string'); + } + + if ($this->has($id)) + { + // By default, call a factory with the Container + $args = \is_array($args) ? $args : [$this]; + $obj = \call_user_func_array($this->container[$id], $args); + + // Check for container interface, and apply the container to the object + // if applicable + return $this->applyContainer($obj); + } + + throw new NotFoundException("Item '{$id}' does not exist in container."); + } + + /** + * Add a factory to the container + * + * @param string $id + * @param Callable $value - a factory callable for the item + * @return ContainerInterface + */ + public function set(string $id, Callable $value): ContainerInterface + { + $this->container[$id] = $value; + return $this; + } + + /** + * Set a specific instance in the container for an existing factory + * + * @param string $id + * @param mixed $value + * @throws NotFoundException - No entry was found for this identifier. + * @return ContainerInterface + */ + public function setInstance(string $id, $value): ContainerInterface + { + if ( ! $this->has($id)) + { + throw new NotFoundException("Factory '{$id}' does not exist in container. Set that first."); + } + + $this->instances[$id] = $value; + return $this; + } + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * @param string $id Identifier of the entry to look for. + * @return boolean + */ + public function has($id): bool + { + return array_key_exists($id, $this->container); + } + + /** + * Determine whether a logger channel is registered + * + * @param string $id The logger channel + * @return boolean + */ + public function hasLogger(string $id = 'default'): bool + { + return array_key_exists($id, $this->loggers); + } + + /** + * Add a logger to the Container + * + * @param LoggerInterface $logger + * @param string $id The logger 'channel' + * @return ContainerInterface + */ + public function setLogger(LoggerInterface $logger, string $id = 'default'): ContainerInterface + { + $this->loggers[$id] = $logger; + return $this; + } + + /** + * Retrieve a logger for the selected channel + * + * @param string $id The logger to retrieve + * @return LoggerInterface|null + */ + public function getLogger(string $id = 'default'): ?LoggerInterface + { + return $this->hasLogger($id) + ? $this->loggers[$id] + : NULL; + } + + /** + * Check if object implements ContainerAwareInterface + * or uses ContainerAware trait, and if so, apply the container + * to that object + * + * @param mixed $obj + * @return mixed + */ + private function applyContainer($obj) + { + $trait_name = ContainerAware::class; + $interface_name = ContainerAwareInterface::class; + + $uses_trait = \in_array($trait_name, class_uses($obj), TRUE); + $implements_interface = \in_array($interface_name, class_implements($obj), TRUE); + + if ($uses_trait || $implements_interface) + { + $obj->setContainer($this); + } + + return $obj; + } +} +// End of Container.php \ No newline at end of file diff --git a/src/Ion/Di/ContainerAware.php b/src/Ion/Di/ContainerAware.php new file mode 100644 index 00000000..c1edcc0d --- /dev/null +++ b/src/Ion/Di/ContainerAware.php @@ -0,0 +1,53 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di; + +/** + * Trait implementation of ContainerAwareInterface + */ +trait ContainerAware { + + /** + * Di Container + * + * @var ContainerInterface + */ + protected $container; + + /** + * Set the container for the current object + * + * @param ContainerInterface $container + * @return self + */ + public function setContainer(ContainerInterface $container): self + { + $this->container = $container; + return $this; + } + + /** + * Get the container object + * + * @return ContainerInterface + */ + public function getContainer(): ContainerInterface + { + return $this->container; + } +} +// End of ContainerAware.php \ No newline at end of file diff --git a/src/Ion/Di/ContainerAwareInterface.php b/src/Ion/Di/ContainerAwareInterface.php new file mode 100644 index 00000000..f35baadf --- /dev/null +++ b/src/Ion/Di/ContainerAwareInterface.php @@ -0,0 +1,40 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di; + +/** + * Interface for a class that is aware of the Di Container + */ +interface ContainerAwareInterface { + + /** + * Set the container for the current object + * + * @param ContainerInterface $container + * @return void + */ + public function setContainer(ContainerInterface $container); + + /** + * Get the container object + * + * @return ContainerInterface + */ + public function getContainer(): ContainerInterface; + +} +// End of ContainerAwareInterface.php \ No newline at end of file diff --git a/src/Ion/Di/ContainerInterface.php b/src/Ion/Di/ContainerInterface.php new file mode 100644 index 00000000..7d1e273f --- /dev/null +++ b/src/Ion/Di/ContainerInterface.php @@ -0,0 +1,100 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di; + +use Psr\Log\LoggerInterface; + +/** + * Interface for the Dependency Injection Container + * + * Based on container-interop interface, but return types and + * scalar type hints make the interface incompatible to the PHP parser + * + * @see https://github.com/container-interop/container-interop + */ +interface ContainerInterface { + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * @throws Exception\NotFoundException No entry was found for this identifier. + * @throws Exception\ContainerException Error while retrieving the entry. + * @return mixed Entry. + */ + public function get($id); + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * @param string $id Identifier of the entry to look for. + * @return boolean + */ + public function has($id): bool; + + /** + * Add a factory to the container + * + * @param string $id + * @param Callable $value - a factory callable for the item + * @return ContainerInterface + */ + public function set(string $id, Callable $value): ContainerInterface; + + /** + * Set a specific instance in the container for an existing factory + * + * @param string $id + * @param mixed $value + * @return ContainerInterface + */ + public function setInstance(string $id, $value): ContainerInterface; + + /** + * Get a new instance of the specified item + * + * @param string $id + * @return mixed + */ + public function getNew($id); + + /** + * Determine whether a logger channel is registered + * + * @param string $id The logger channel + * @return boolean + */ + public function hasLogger(string $id = 'default'): bool; + + /** + * Add a logger to the Container + * + * @param LoggerInterface $logger + * @param string $id The logger 'channel' + * @return ContainerInterface + */ + public function setLogger(LoggerInterface $logger, string $id = 'default'): ContainerInterface; + + /** + * Retrieve a logger for the selected channel + * + * @param string $id The logger to retrieve + * @return LoggerInterface|null + */ + public function getLogger(string $id = 'default'): ?LoggerInterface; +} \ No newline at end of file diff --git a/src/Ion/Di/Exception/ContainerException.php b/src/Ion/Di/Exception/ContainerException.php new file mode 100644 index 00000000..1f9ab88d --- /dev/null +++ b/src/Ion/Di/Exception/ContainerException.php @@ -0,0 +1,28 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di\Exception; + +use Exception; +use Psr\Container\ContainerExceptionInterface; + +/** + * Generic exception for Di Container + */ +class ContainerException extends Exception implements ContainerExceptionInterface { + +} +// End of ContainerException.php \ No newline at end of file diff --git a/src/Ion/Di/Exception/NotFoundException.php b/src/Ion/Di/Exception/NotFoundException.php new file mode 100644 index 00000000..214f7690 --- /dev/null +++ b/src/Ion/Di/Exception/NotFoundException.php @@ -0,0 +1,28 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Di\Exception; + +use Psr\Container\NotFoundExceptionInterface; + +/** + * Exception for Di Container when trying to access a + * key that doesn't exist in the container + */ +class NotFoundException extends ContainerException implements NotFoundExceptionInterface { + +} +// End of NotFoundException.php \ No newline at end of file diff --git a/src/Ion/Enum.php b/src/Ion/Enum.php new file mode 100644 index 00000000..397f2228 --- /dev/null +++ b/src/Ion/Enum.php @@ -0,0 +1,59 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use ReflectionClass; + +/** + * Class emulating an enumeration type + */ +abstract class Enum { + + /** + * Return the list of constant values for the Enum + * + * @return array + * @throws \ReflectionException + */ + public static function getConstList(): array + { + static $self; + + if ($self === NULL) + { + $class = static::class; + $self = new $class; + } + + $reflect = new ReflectionClass($self); + return $reflect->getConstants(); + } + + /** + * Verify that a constant value is valid + * + * @param mixed $key + * @return boolean + * @throws \ReflectionException + */ + public static function isValid($key): bool + { + $values = array_values(static::getConstList()); + return \in_array($key, $values, TRUE); + } +} +// End of Enum.php \ No newline at end of file diff --git a/src/Ion/Exception/ConfigException.php b/src/Ion/Exception/ConfigException.php new file mode 100644 index 00000000..82aad58a --- /dev/null +++ b/src/Ion/Exception/ConfigException.php @@ -0,0 +1,26 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Exception; + +use InvalidArgumentException; + +/** + * Exception for bad configuration + */ +class ConfigException extends InvalidArgumentException { + +} \ No newline at end of file diff --git a/src/Ion/Exception/DoubleRenderException.php b/src/Ion/Exception/DoubleRenderException.php new file mode 100644 index 00000000..9e782cda --- /dev/null +++ b/src/Ion/Exception/DoubleRenderException.php @@ -0,0 +1,38 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Exception; + +use Exception; +use LogicException; + +/** + * Exception called when a view is attempted to be sent twice + */ +class DoubleRenderException extends LogicException { + + /** + * DoubleRenderException constructor. + * + * @param string $message + * @param int $code + * @param Exception|null $previous + */ + public function __construct(string $message = 'A view can only be rendered once, because headers can only be sent once.', int $code = 0, Exception $previous = NULL) + { + parent::__construct($message, $code, $previous); + } +} \ No newline at end of file diff --git a/src/Ion/Friend.php b/src/Ion/Friend.php new file mode 100644 index 00000000..675bbdc3 --- /dev/null +++ b/src/Ion/Friend.php @@ -0,0 +1,157 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use BadMethodCallException; +use InvalidArgumentException; +use ReflectionClass; +use ReflectionMethod; +use ReflectionProperty; + +/** + * Friend class for testing + */ +class Friend { + + /** + * Object to create a friend of + * @var mixed + */ + private $_friend_; + + /** + * Reflection class of the object + * @var ReflectionClass + */ + private $_reflect_; + + /** + * Create a friend object + * + * @param mixed $obj + * @throws InvalidArgumentException + * @throws \ReflectionException + */ + public function __construct($obj) + { + if ( ! \is_object($obj)) + { + throw new InvalidArgumentException('Friend must be an object'); + } + + $this->_friend_ = $obj; + $this->_reflect_ = new ReflectionClass($obj); + } + + /** + * Retrieve a friend's property + * + * @param string $key + * @return mixed + */ + public function __get(string $key) + { + if ($this->__isset($key)) + { + $property = $this->_get_property($key); + + if ($property !== NULL) + { + return $property->getValue($this->_friend_); + } + } + + return NULL; + } + + /** + * See if a property exists on the friend + * + * @param string $name + * @return bool + */ + public function __isset(string $name): bool + { + return $this->_reflect_->hasProperty($name); + } + + /** + * Set a friend's property + * + * @param string $key + * @param mixed $value + * @return void + */ + public function __set(string $key, $value) + { + if ($this->__isset($key)) + { + $property = $this->_get_property($key); + + if ($property !== NULL) + { + $property->setValue($this->_friend_, $value); + } + } + } + + /** + * Calls a protected or private method on the friend + * + * @param string $method + * @param array $args + * @return mixed + * @throws BadMethodCallException + * @throws \ReflectionException + */ + public function __call(string $method, array $args) + { + if ( ! $this->_reflect_->hasMethod($method)) + { + throw new BadMethodCallException("Method '{$method}' does not exist"); + } + + $friendMethod = new ReflectionMethod($this->_friend_, $method); + $friendMethod->setAccessible(TRUE); + return $friendMethod->invokeArgs($this->_friend_, $args); + } + + /** + * Iterates over parent classes to get a ReflectionProperty + * + * @param string $name + * @return ReflectionProperty|null + */ + private function _get_property(string $name): ?ReflectionProperty + { + try + { + $property = $this->_reflect_->getProperty($name); + $property->setAccessible(TRUE); + return $property; + } + // Return NULL on any exception, so no further logic needed + // in the catch block + // @codeCoverageIgnoreStart + catch (\Exception $e) + { + return NULL; + } + // @codeCoverageIgnoreEnd + } +} +// End of Friend.php \ No newline at end of file diff --git a/src/Ion/Json.php b/src/Ion/Json.php new file mode 100644 index 00000000..07e61e69 --- /dev/null +++ b/src/Ion/Json.php @@ -0,0 +1,139 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Aviat\Ion\Type\StringType; + +/** + * Helper class for json convenience methods + */ +class Json { + + /** + * Encode data in json format + * + * @param mixed $data + * @param int $options + * @param int $depth + * @throws JsonException + * @return string + */ + public static function encode($data, $options = 0, $depth = 512): string + { + $json = json_encode($data, $options, $depth); + self::check_json_error(); + return $json; + } + + /** + * Encode data in json format and save to a file + * + * @param string $filename + * @param mixed $data + * @param int $jsonOptions - Options to pass to json_encode + * @param int $fileOptions - Options to pass to file_get_contents + * @throws JsonException + * @return int + */ + public static function encodeFile(string $filename, $data, int $jsonOptions = 0, int $fileOptions = 0): int + { + $json = self::encode($data, $jsonOptions); + return file_put_contents($filename, $json, $fileOptions); + } + + /** + * Decode data from json + * + * @param string|null $json + * @param bool $assoc + * @param int $depth + * @param int $options + * @throws JsonException + * @return mixed + */ + public static function decode($json, bool $assoc = TRUE, int $depth = 512, int $options = 0) + { + // Don't try to decode null + if ($json === NULL) + { + return NULL; + } + + $data = json_decode($json, $assoc, $depth, $options); + + self::check_json_error(); + return $data; + } + + /** + * Decode json data loaded from the passed filename + * + * @param string $filename + * @param bool $assoc + * @param int $depth + * @param int $options + * @throws JsonException + * @return mixed + */ + public static function decodeFile(string $filename, bool $assoc = TRUE, int $depth = 512, int $options = 0) + { + $json = file_get_contents($filename); + return self::decode($json, $assoc, $depth, $options); + } + + /** + * Determines whether a string is valid json + * + * @param string $string + * @throws \InvalidArgumentException + * @return boolean + */ + public static function isJson(string $string): bool + { + return StringType::create($string)->isJson(); + } + + /** + * Call the json error functions to check for errors encoding/decoding + * + * @throws JsonException + * @return void + */ + protected static function check_json_error(): void + { + $constant_map = [ + JSON_ERROR_NONE => 'JSON_ERROR_NONE', + JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH', + JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH', + JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR', + JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX', + JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8', + JSON_ERROR_RECURSION => 'JSON_ERROR_RECURSION', + JSON_ERROR_INF_OR_NAN => 'JSON_ERROR_INF_OR_NAN', + JSON_ERROR_UNSUPPORTED_TYPE => 'JSON_ERROR_UNSUPPORTED_TYPE' + ]; + + $error = json_last_error(); + $message = json_last_error_msg(); + + if (JSON_ERROR_NONE !== $error) + { + throw new JsonException("{$constant_map[$error]} - {$message}", $error); + } + } +} +// End of JSON.php \ No newline at end of file diff --git a/src/Ion/JsonException.php b/src/Ion/JsonException.php new file mode 100644 index 00000000..bd1fb9ad --- /dev/null +++ b/src/Ion/JsonException.php @@ -0,0 +1,27 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use InvalidArgumentException; + +/** + * Exceptions thrown by the Json class + */ +class JsonException extends InvalidArgumentException { + +} +// End of JsonException.php \ No newline at end of file diff --git a/src/Ion/Model.php b/src/Ion/Model.php new file mode 100644 index 00000000..7f72c0b1 --- /dev/null +++ b/src/Ion/Model.php @@ -0,0 +1,25 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +/** + * Common base for all Models + */ +class Model { + use StringWrapper; +} +// End of Model.php diff --git a/src/Ion/Model/DB.php b/src/Ion/Model/DB.php new file mode 100644 index 00000000..f06eda2a --- /dev/null +++ b/src/Ion/Model/DB.php @@ -0,0 +1,55 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Model; + +use Aviat\Ion\ConfigInterface; +use Aviat\Ion\Model as BaseModel; + +/** + * Base model for database interaction + */ +class DB extends BaseModel { + /** + * The query builder object + * @var object $db + */ + protected $db; + + /** + * The config manager + * @var ConfigInterface + */ + protected $config; + + /** + * The database connection information array + * @var array $db_config + */ + protected $db_config; + + /** + * Constructor + * + * @param ConfigInterface $config + */ + public function __construct(ConfigInterface $config) + { + $this->config = $config; + $this->db_config = (array)$config->get('database'); + } +} +// End of DB.php diff --git a/src/Ion/StringWrapper.php b/src/Ion/StringWrapper.php new file mode 100644 index 00000000..71609f05 --- /dev/null +++ b/src/Ion/StringWrapper.php @@ -0,0 +1,38 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Aviat\Ion\Type\StringType; + +/** + * Trait to add convenience method for creating StringType objects + */ +trait StringWrapper { + + /** + * Wrap the String in the Stringy class + * + * @param string $str + * @throws \InvalidArgumentException + * @return StringType + */ + public function string($str): StringType + { + return StringType::create($str); + } +} +// End of StringWrapper.php \ No newline at end of file diff --git a/src/Ion/Transformer/AbstractTransformer.php b/src/Ion/Transformer/AbstractTransformer.php new file mode 100644 index 00000000..56b56194 --- /dev/null +++ b/src/Ion/Transformer/AbstractTransformer.php @@ -0,0 +1,69 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Transformer; + +use Aviat\Ion\StringWrapper; + +use BadMethodCallException; + +/** + * Base class for data transformation + */ +abstract class AbstractTransformer implements TransformerInterface { + + use StringWrapper; + + /** + * Mutate the data structure + * + * @param array|object $item + * @return mixed + */ + abstract public function transform($item); + + /** + * Transform a set of structures + * + * @param iterable $collection + * @return array + */ + public function transformCollection(iterable $collection): array + { + $list = (array)$collection; + return array_map([$this, 'transform'], $list); + } + + /** + * Untransform a set of structures + * + * Requires an 'untransform' method in the extending class + * + * @param iterable $collection + * @return array + */ + public function untransformCollection(iterable $collection): array + { + if ( ! method_exists($this, 'untransform')) + { + throw new BadMethodCallException('untransform() method does not exist.'); + } + + $list = (array)$collection; + return array_map([$this, 'untransform'], $list); + } +} +// End of AbstractTransformer.php \ No newline at end of file diff --git a/src/Ion/Transformer/TransformerInterface.php b/src/Ion/Transformer/TransformerInterface.php new file mode 100644 index 00000000..b89e8f95 --- /dev/null +++ b/src/Ion/Transformer/TransformerInterface.php @@ -0,0 +1,31 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Transformer; + +/** + * Interface for data transformation classes + */ +interface TransformerInterface { + + /** + * Mutate the data structure + * + * @param array|object $item + * @return mixed + */ + public function transform($item); +} \ No newline at end of file diff --git a/src/Ion/Type/ArrayType.php b/src/Ion/Type/ArrayType.php new file mode 100644 index 00000000..f1e84928 --- /dev/null +++ b/src/Ion/Type/ArrayType.php @@ -0,0 +1,286 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Type; + +use InvalidArgumentException; + +/** + * Wrapper class for native array methods for convenience + * + * @method array chunk(int $size, bool $preserve_keys = FALSE) + * @method array pluck(mixed $column_key, mixed $index_key = NULL) + * @method array filter(callable $callback = NULL, int $flag = 0) + */ +class ArrayType { + + /** + * The current array + * + * @var array + */ + protected $arr; + + /** + * Map generated methods to their native implementations + * + * @var array + */ + protected $nativeMethods = [ + 'chunk' => 'array_chunk', + 'diff' => 'array_diff', + 'filter' => 'array_filter', + 'flip' => 'array_flip', + 'intersect' => 'array_intersect', + 'key_diff' => 'array_diff_key', + 'keys' => 'array_keys', + 'merge' => 'array_merge', + 'pad' => 'array_pad', + 'pluck' => 'array_column', + 'product' => 'array_product', + 'random' => 'array_rand', + 'reduce' => 'array_reduce', + 'reverse' => 'array_reverse', + 'sum' => 'array_sum', + 'unique' => 'array_unique', + 'values' => 'array_values', + ]; + + /** + * Native methods that modify the passed in array + * + * @var array + */ + protected $nativeInPlaceMethods = [ + 'shuffle' => 'shuffle', + 'shift' => 'array_shift', + 'unshift' => 'array_unshift', + 'push' => 'array_push', + 'pop' => 'array_pop', + ]; + + /** + * Create an ArrayType wrapper class + * + * @param array $arr + */ + public function __construct(array &$arr) + { + $this->arr =& $arr; + } + + /** + * Call one of the dynamically created methods + * + * @param string $method + * @param array $args + * @return mixed + * @throws InvalidArgumentException + */ + public function __call(string $method, array $args) + { + // Simple mapping for the majority of methods + if (array_key_exists($method, $this->nativeMethods)) + { + $func = $this->nativeMethods[$method]; + // Set the current array as the first argument of the method + return $func($this->arr, ...$args); + } + + // Mapping for in-place methods + if (array_key_exists($method, $this->nativeInPlaceMethods)) + { + $func = $this->nativeInPlaceMethods[$method]; + $func($this->arr); + return $this->arr; + } + + throw new InvalidArgumentException("Method '{$method}' does not exist"); + } + + /** + * Does the passed key exist in the current array? + * + * @param int|string|array $key + * @return bool + */ + public function hasKey($key): bool + { + if (\is_array($key)) + { + $pos =& $this->arr; + + foreach($key as $level) + { + if ( ! array_key_exists($level, $pos)) + { + return FALSE; + } + + $pos =& $pos[$level]; + } + + return TRUE; + } + + return array_key_exists($key, $this->arr); + } + + /** + * Fill an array with the specified value + * + * @param int $start_index + * @param int $num + * @param mixed $value + * @return array + */ + public function fill(int $start_index, int $num, $value): array + { + return array_fill($start_index, $num, $value); + } + + /** + * Call a callback on each item of the array + * + * @param callable $callback + * @return array + */ + public function map(callable $callback): array + { + return array_map($callback, $this->arr); + } + + /** + * Find an array key by its associated value + * + * @param mixed $value + * @param bool $strict + * @return false|integer|string + */ + public function search($value, bool $strict = TRUE) + { + return array_search($value, $this->arr, $strict); + } + + /** + * Determine if the array has the passed value + * + * @param mixed $value + * @param bool $strict + * @return bool + */ + public function has($value, bool $strict = TRUE): bool + { + return \in_array($value, $this->arr, $strict); + } + + /** + * Return the array, or a key + * + * @param string|integer|null $key + * @return mixed + */ + public function &get($key = NULL) + { + $value = NULL; + if ($key === NULL) + { + $value =& $this->arr; + } + else + { + if ($this->hasKey($key)) + { + $value =& $this->arr[$key]; + } + } + + return $value; + } + + /** + * Set a key on the array + * + * @param mixed $key + * @param mixed $value + * @return ArrayType + */ + public function set($key, $value): ArrayType + { + $this->arr[$key] = $value; + return $this; + } + + /** + * Return a reference to the value of an arbitrary key on the array + * + * @example $arr = new ArrayType([0 => ['data' => ['foo' => 'bar']]]); + * $val = $arr->getDeepKey([0, 'data', 'foo']); + * // returns 'bar' + * @param array $key An array of keys of the array + * @return mixed + */ + public function &getDeepKey(array $key) + { + $pos =& $this->arr; + + foreach ($key as $level) + { + if (empty($pos) || ! is_array($pos)) + { + // Directly returning a NULL value here will + // result in a reference error. This isn't + // excess code, just what's required for this + // unique situation. + $pos = NULL; + return $pos; + } + $pos =& $pos[$level]; + } + + return $pos; + } + + /** + * Sets the value of an arbitrarily deep key in the array + * and returns the modified array + * + * @param array $key + * @param mixed $value + * @return array + */ + public function setDeepKey(array $key, $value): array + { + $pos =& $this->arr; + + // Iterate through the levels of the array, + // create the levels if they don't exist + foreach ($key as $level) + { + if ( ! \is_array($pos) && empty($pos)) + { + $pos = []; + $pos[$level] = []; + } + $pos =& $pos[$level]; + } + + $pos = $value; + + return $this->arr; + } +} +// End of ArrayType.php \ No newline at end of file diff --git a/src/Ion/Type/StringType.php b/src/Ion/Type/StringType.php new file mode 100644 index 00000000..5601731f --- /dev/null +++ b/src/Ion/Type/StringType.php @@ -0,0 +1,42 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Type; + +use Stringy\Stringy; + +/** + * Wrapper around Stringy + */ +class StringType extends Stringy { + + /** + * See if two strings match, despite being delimited differently, + * such as camelCase, PascalCase, kebab-case, or snake_case. + * + * @param string $strToMatch + * @throws \InvalidArgumentException + * @return boolean + */ + public function fuzzyCaseMatch(string $strToMatch): bool + { + $firstStr = (string)self::create($this->str)->dasherize(); + $secondStr = (string)self::create($strToMatch)->dasherize(); + + return $firstStr === $secondStr; + } +} +// End of StringType.php \ No newline at end of file diff --git a/src/Ion/View.php b/src/Ion/View.php new file mode 100644 index 00000000..1b4d2ec2 --- /dev/null +++ b/src/Ion/View.php @@ -0,0 +1,143 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Psr\Http\Message\ResponseInterface; + +use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Exception\DoubleRenderException; + +/** + * Base view response class + */ +abstract class View + // partially + implements ViewInterface { + + use Di\ContainerAware; + use StringWrapper; + + /** + * HTTP response Object + * + * @var ResponseInterface + */ + public $response; + + /** + * If the view has sent output via + * __toString or send method + * + * @var boolean + */ + protected $hasRendered = FALSE; + + /** + * Constructor + * + * @param ContainerInterface $container + * @throws Di\Exception\ContainerException + * @throws Di\Exception\NotFoundException + */ + public function __construct(ContainerInterface $container) + { + $this->setContainer($container); + $this->response = $container->get('response'); + } + + /** + * Send output to client + */ + public function __destruct() + { + if ( ! $this->hasRendered) + { + $this->send(); + } + } + + /** + * Return rendered output as string. Renders the view, + * and any attempts to call again will result in a DoubleRenderException + * + * @throws DoubleRenderException + * @return string + */ + public function __toString(): string + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + $this->hasRendered = TRUE; + return $this->getOutput(); + } + + /** + * Add an http header + * + * @param string $name + * @param string|string[] $value + * @throws \InvalidArgumentException + * @return ViewInterface + */ + public function addHeader(string $name, $value): ViewInterface + { + $this->response = $this->response->withHeader($name, $value); + return $this; + } + + /** + * Set the output string + * + * @param mixed $string + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @return ViewInterface + */ + public function setOutput($string): ViewInterface + { + $this->response->getBody()->write($string); + + return $this; + } + + /** + * Append additional output. + * + * @param string $string + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @return ViewInterface + */ + public function appendOutput(string $string): ViewInterface + { + return $this->setOutput($string); + } + + /** + * Get the current output as a string. Does not + * render view or send headers. + * + * @return string + */ + public function getOutput(): string + { + return (string)$this->response->getBody(); + } +} +// End of View.php \ No newline at end of file diff --git a/src/Ion/View/HtmlView.php b/src/Ion/View/HtmlView.php new file mode 100644 index 00000000..70e544ce --- /dev/null +++ b/src/Ion/View/HtmlView.php @@ -0,0 +1,81 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\View; + +use Aura\Html\HelperLocator; +use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Di\Exception\NotFoundException; + +/** + * View class for outputting HTML + */ +class HtmlView extends HttpView { + + /** + * HTML generator/escaper helper + * + * @var HelperLocator + */ + protected $helper; + + /** + * Response mime type + * + * @var string + */ + protected $contentType = 'text/html'; + + /** + * Create the Html View + * + * @param ContainerInterface $container + * @throws ContainerException + * @throws NotFoundException + */ + public function __construct(ContainerInterface $container) + { + parent::__construct($container); + $this->helper = $container->get('html-helper'); + } + + /** + * Render a basic html Template + * + * @param string $path + * @param array $data + * @return string + */ + public function renderTemplate(string $path, array $data): string + { + $data['helper'] = $this->helper; + $data['escape'] = $this->helper->escape(); + $data['container'] = $this->container; + + ob_start(); + extract($data, \EXTR_OVERWRITE); + include_once $path; + $buffer = ob_get_clean(); + + + // Very basic html minify, that won't affect content between html tags + $buffer = preg_replace('/>\s+ <', $buffer); + + return $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 new file mode 100644 index 00000000..6fa5f09a --- /dev/null +++ b/src/Ion/View/HttpView.php @@ -0,0 +1,102 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\View; + +use Laminas\Diactoros\Response; +use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; + +use Aviat\Ion\Exception\DoubleRenderException; +use Aviat\Ion\View as BaseView; + +/** + * Base view class for Http output + */ +class HttpView extends BaseView { + + /** + * Response mime type + * + * @var string + */ + protected $contentType = ''; + + /** + * Do a redirect + * + * @param string $url + * @param int $code + * @param array $headers + * @throws \InvalidArgumentException + * @return void + */ + public function redirect(string $url, int $code = 302, array $headers = []): void + { + $this->response = new Response\RedirectResponse($url, $code, $headers); + } + + /** + * Set the status code of the request + * + * @param int $code + * @throws \InvalidArgumentException + * @return HttpView + */ + public function setStatusCode(int $code): HttpView + { + $this->response = $this->response->withStatus($code) + ->withProtocolVersion('1.1'); + return $this; + } + + /** + * Send output to client. As it renders the view, + * any attempt to call again will result in a DoubleRenderException. + * + * @throws DoubleRenderException + * @throws \InvalidArgumentException + * @return void + */ + public function send(): void + { + $this->output(); + } + + /** + * Send the appropriate response + * + * @throws DoubleRenderException + * @throws \InvalidArgumentException + * @return void + */ + protected function output(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->response = $this->response + ->withHeader('Content-type', "{$this->contentType};charset=utf-8") + ->withHeader('X-Content-Type-Options', 'nosniff') + ->withHeader('X-XSS-Protection', '1;mode=block') + ->withHeader('X-Frame-Options', 'SAMEORIGIN'); + + (new SapiEmitter())->emit($this->response); + + $this->hasRendered = TRUE; + } +} \ No newline at end of file diff --git a/src/Ion/View/JsonView.php b/src/Ion/View/JsonView.php new file mode 100644 index 00000000..a294d06f --- /dev/null +++ b/src/Ion/View/JsonView.php @@ -0,0 +1,54 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\View; + +use Aviat\Ion\Json; +use Aviat\Ion\JsonException; +use Aviat\Ion\ViewInterface; + +/** + * View class to serialize Json + */ +class JsonView extends HttpView { + + /** + * Response mime type + * + * @var string + */ + protected $contentType = 'application/json'; + + /** + * Set the output string + * + * @param mixed $string + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @throws JsonException + * @return ViewInterface + */ + public function setOutput($string): ViewInterface + { + if ( ! \is_string($string)) + { + $string = Json::encode($string); + } + + return parent::setOutput($string); + } +} +// End of JsonView.php \ No newline at end of file diff --git a/src/Ion/ViewInterface.php b/src/Ion/ViewInterface.php new file mode 100644 index 00000000..aeb767d3 --- /dev/null +++ b/src/Ion/ViewInterface.php @@ -0,0 +1,75 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +use Aviat\Ion\Exception\DoubleRenderException; + +/** + * View Interface abstracting a Response + */ +interface ViewInterface { + /** + * Return rendered output as string. Renders the view, + * and any attempts to call again will result in a DoubleRenderException + * + * @throws DoubleRenderException + * @return string + */ + public function __toString(): string; + + /** + * Set the output string + * + * @param mixed $string + * @return ViewInterface + */ + public function setOutput($string): self; + + /** + * Append additional output. + * + * @param string $string + * @return ViewInterface + */ + public function appendOutput(string $string): self; + + /** + * Add an http header + * + * @param string $name + * @param string|string[] $value + * @return ViewInterface + */ + public function addHeader(string $name, $value): self; + + /** + * Get the current output as a string. Does not + * render view or send headers. + * + * @return string + */ + public function getOutput(): string; + + /** + * Send output to client. As it renders the view, + * any attempt to call again will result in a DoubleRenderException. + * + * @throws DoubleRenderException + * @return void + */ + public function send(): void; +} \ No newline at end of file diff --git a/src/Ion/functions.php b/src/Ion/functions.php new file mode 100644 index 00000000..439d6107 --- /dev/null +++ b/src/Ion/functions.php @@ -0,0 +1,29 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion; + +/** + * Joins paths together. Variadic to take an + * arbitrary number of arguments + * + * @param string ...$args + * @return string + */ +function _dir(string ...$args): string +{ + return implode(DIRECTORY_SEPARATOR, $args); +} \ No newline at end of file diff --git a/src/Model/MangaCollection.php b/src/Model/MangaCollection.php deleted file mode 100644 index 71238f42..00000000 --- a/src/Model/MangaCollection.php +++ /dev/null @@ -1,288 +0,0 @@ - - * @copyright 2015 - 2018 Timothy J. Warren - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 - * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient - */ - -namespace Aviat\AnimeClient\Model; - -use Aviat\Ion\Di\ContainerInterface; -use PDO; - -/** - * Model for getting anime collection data - */ -final class MangaCollection extends Collection { - - /** - * Manga API Model - * @var Manga $mangaModel - */ - protected $mangaModel; - - /** - * Create the collection model - * - * @param ContainerInterface $container - */ - public function __construct(ContainerInterface $container) - { - parent::__construct($container); - $this->mangaModel = $container->get('manga-model'); - } - - /** - * Get collection from the database, and organize by media type - * - * @return array - */ - public function getCollection(): array - { - $rawCollection = $this->getCollectionFromDatabase(); - - $collection = []; - - foreach ($rawCollection as $row) - { - if (array_key_exists($row['media'], $collection)) - { - $collection[$row['media']][] = $row; - } - else - { - $collection[$row['media']] = [$row]; - } - } - - return $collection; - } - - /** - * Get list of media types - * - * @return array - */ - public function getMediaTypeList(): array - { - $output = []; - - $query = $this->db->select('id, type') - ->from('media') - ->get(); - - foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) - { - $output[$row['id']] = $row['type']; - } - - return $output; - } - - /** - * Get full collection from the database - * - * @return array - */ - private function getCollectionFromDatabase(): array - { - if ( ! $this->validDatabase) - { - return []; - } - - $query = $this->db->select('hummingbird_id, slug, title, alternate_title, show_type, - age_rating, episode_count, episode_length, cover_image, notes, media.type as media') - ->from('manga_set a') - ->join('media', 'media.id=a.media_id', 'inner') - ->order_by('media') - ->order_by('title') - ->get(); - - return $query->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * Add an item to the anime collection - * - * @param array $data - * @return void - */ - public function add($data): void - { - $anime = (object)$this->mangaModel->getMangaById($data['id']); - $this->db->set([ - 'hummingbird_id' => $data['id'], - 'slug' => $anime->slug, - 'title' => array_shift($anime->titles), - 'alternate_title' => implode('
', $anime->titles), - 'show_type' => $anime->show_type, - 'age_rating' => $anime->age_rating, - 'cover_image' => $anime->cover_image, - 'episode_count' => $anime->episode_count, - 'episode_length' => $anime->episode_length, - 'media_id' => $data['media_id'], - 'notes' => $data['notes'] - ])->insert('manga_set'); - - $this->updateGenre($data['id']); - } - - /** - * Update a collection item - * - * @param array $data - * @return void - */ - public function update($data): void - { - // If there's no id to update, don't update - if ( ! array_key_exists('hummingbird_id', $data)) - { - return; - } - - $id = $data['hummingbird_id']; - unset($data['hummingbird_id']); - - $this->db->set($data) - ->where('hummingbird_id', $id) - ->update('manga_set'); - } - - /** - * Remove a collection item - * - * @param array $data - * @return void - */ - public function delete($data): void - { - // If there's no id to update, don't delete - if ( ! array_key_exists('hummingbird_id', $data)) - { - return; - } - - $this->db->where('hummingbird_id', $data['hummingbird_id']) - ->delete('genre_manga_set_link'); - - $this->db->where('hummingbird_id', $data['hummingbird_id']) - ->delete('manga_set'); - } - - /** - * Get the details of a collection item - * - * @param string $kitsuId - * @return array - */ - public function get($kitsuId): array - { - $query = $this->db->from('manga_set') - ->where('hummingbird_id', $kitsuId) - ->get(); - - return $query->fetch(PDO::FETCH_ASSOC); - } - - /** - * Update genre information for selected manga - * - * @param string $mangaId The current manga - * @return void - */ - private function updateGenre($mangaId): void - { - $genreInfo = $this->getGenreData(); - $genres = $genreInfo['genres']; - $links = $genreInfo['links']; - - // Get api information - $manga = $this->mangaModel->getMangaById($mangaId); - - foreach ($manga['genres'] as $genre) - { - // Add genres that don't currently exist - if ( ! \in_array($genre, $genres, TRUE)) - { - $this->db->set('genre', $genre) - ->insert('genres'); - - $genres[] = $genre; - } - - // Update link table - // Get id of genre to put in link table - $flippedGenres = array_flip($genres); - - $insertArray = [ - 'hummingbird_id' => $mangaId, - 'genre_id' => $flippedGenres[$genre] - ]; - - if (array_key_exists($mangaId, $links)) - { - if ( ! \in_array($flippedGenres[$genre], $links[$mangaId], TRUE)) - { - $this->db->set($insertArray)->insert('genre_manga_set_link'); - } - } - else - { - $this->db->set($insertArray)->insert('genre_manga_set_link'); - } - } - } - - /** - * Get list of existing genres - * - * @return array - */ - private function getGenreData(): array - { - $genres = []; - $links = []; - - // Get existing genres - $query = $this->db->select('id, genre') - ->from('genres') - ->get(); - foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $genre) - { - $genres[$genre['id']] = $genre['genre']; - } - - // Get existing link table entries - $query = $this->db->select('hummingbird_id, genre_id') - ->from('genre_manga_set_link') - ->get(); - foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $link) - { - if (array_key_exists($link['hummingbird_id'], $links)) - { - $links[$link['hummingbird_id']][] = $link['genre_id']; - } - else - { - $links[$link['hummingbird_id']] = [$link['genre_id']]; - } - } - - return [ - 'genres' => $genres, - 'links' => $links - ]; - } -} -// End of MangaCollectionModel.php \ No newline at end of file diff --git a/src/Types/Config.php b/src/Types/Config.php deleted file mode 100644 index 488cbedb..00000000 --- a/src/Types/Config.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright 2015 - 2018 Timothy J. Warren - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 - * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient - */ - -namespace Aviat\AnimeClient\Types; - -class Config extends AbstractType { - // Config files/namespaces - public $anilist; - public $cache; - public $database; - - // Settings in config.toml - public $asset_path; // Path to public folder for urls - public $dark_theme; /* Deprecated */ - public $default_anime_list_path; - public $default_list; - public $default_manga_list_path; - public $default_view_type; - public $kitsu_username; - public $secure_urls = TRUE; - public $show_anime_collection; - public $show_manga_collection; - public $theme; - public $whose_list; - - // Application config - public $menus; - public $routes; - - // Generated config values - public $asset_dir; // Path to public folder for local files - public $base_config_dir; - public $config_dir; - public $data_cache_path; - public $img_cache_path; - public $view_path; - - public function setAnilist ($data): void - { - $this->anilist = new Config\Anilist($data); - } - - public function setCache ($data): void - { - $this->cache = new Config\Cache($data); - } - - public function setDatabase ($data): void - { - $this->database = new Config\Database($data); - } -} \ No newline at end of file diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #0__1.php b/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #0__1.php deleted file mode 100644 index 4b97af5e..00000000 --- a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #0__1.php +++ /dev/null @@ -1,15 +0,0 @@ - 14047981, - 'anilist_item_id' => NULL, - 'mal_id' => NULL, - 'data' => - Aviat\AnimeClient\Types\FormItemData::__set_state(array( - 'notes' => 'Very formulaic.', - 'private' => false, - 'progress' => 38, - 'ratingTwenty' => 16, - 'reconsumeCount' => 0, - 'reconsuming' => false, - 'status' => 'current', - )), -)); diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #1__1.php b/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #1__1.php deleted file mode 100644 index ca751d41..00000000 --- a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #1__1.php +++ /dev/null @@ -1,15 +0,0 @@ - 14047981, - 'anilist_item_id' => NULL, - 'mal_id' => '12345', - 'data' => - Aviat\AnimeClient\Types\FormItemData::__set_state(array( - 'notes' => 'Very formulaic.', - 'private' => true, - 'progress' => 38, - 'ratingTwenty' => 16, - 'reconsumeCount' => 0, - 'reconsuming' => true, - 'status' => 'current', - )), -)); diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #2__1.php b/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #2__1.php deleted file mode 100644 index 9375de10..00000000 --- a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set #2__1.php +++ /dev/null @@ -1,14 +0,0 @@ - 14047983, - 'anilist_item_id' => NULL, - 'mal_id' => '12347', - 'data' => - Aviat\AnimeClient\Types\FormItemData::__set_state(array( - 'notes' => '', - 'private' => true, - 'progress' => 12, - 'reconsumeCount' => 0, - 'reconsuming' => true, - 'status' => 'current', - )), -)); diff --git a/tests/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.php b/tests/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.php deleted file mode 100644 index 8d1c950f..00000000 --- a/tests/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.php +++ /dev/null @@ -1,201 +0,0 @@ - - Aviat\AnimeClient\Types\MangaListItem::__set_state(array( - 'id' => '15084773', - 'mal_id' => '26769', - 'chapters' => - array ( - 'read' => 67, - 'total' => '-', - ), - 'volumes' => - array ( - 'read' => '-', - 'total' => '-', - ), - 'manga' => - Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array( - 'genres' => - array ( - 0 => 'Comedy', - 1 => 'Romance', - 2 => 'School', - 3 => 'Slice of Life', - 4 => 'Thriller', - ), - 'id' => '20286', - 'image' => 'https://media.kitsu.io/manga/poster_images/20286/small.jpg?1434293999', - 'slug' => 'bokura-wa-minna-kawaisou', - 'title' => 'Bokura wa Minna Kawaisou', - 'titles' => - array ( - ), - 'type' => 'Manga', - 'url' => 'https://kitsu.io/manga/bokura-wa-minna-kawaisou', - )), - 'reading_status' => 'current', - 'notes' => '', - 'rereading' => false, - 'reread' => 0, - 'user_rating' => 9, - )), - 1 => - Aviat\AnimeClient\Types\MangaListItem::__set_state(array( - 'id' => '15085607', - 'mal_id' => '16', - 'chapters' => - array ( - 'read' => 17, - 'total' => 120, - ), - 'volumes' => - array ( - 'read' => '-', - 'total' => 14, - ), - 'manga' => - Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array( - 'genres' => - array ( - 0 => 'Comedy', - 1 => 'Ecchi', - 2 => 'Harem', - 3 => 'Romance', - 4 => 'Sports', - ), - 'id' => '47', - 'image' => 'https://media.kitsu.io/manga/poster_images/47/small.jpg?1434249493', - 'slug' => 'love-hina', - 'title' => 'Love Hina', - 'titles' => - array ( - ), - 'type' => 'Manga', - 'url' => 'https://kitsu.io/manga/love-hina', - )), - 'reading_status' => 'current', - 'notes' => '', - 'rereading' => false, - 'reread' => 0, - 'user_rating' => 7, - )), - 2 => - Aviat\AnimeClient\Types\MangaListItem::__set_state(array( - 'id' => '15084529', - 'mal_id' => '35003', - 'chapters' => - array ( - 'read' => 16, - 'total' => '-', - ), - 'volumes' => - array ( - 'read' => '-', - 'total' => '-', - ), - 'manga' => - Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array( - 'genres' => - array ( - 0 => 'Comedy', - 1 => 'Ecchi', - 2 => 'Gender Bender', - 3 => 'Romance', - 4 => 'School', - 5 => 'Sports', - 6 => 'Supernatural', - ), - 'id' => '11777', - 'image' => 'https://media.kitsu.io/manga/poster_images/11777/small.jpg?1438784325', - 'slug' => 'yamada-kun-to-7-nin-no-majo', - 'title' => 'Yamada-kun to 7-nin no Majo', - 'titles' => - array ( - 0 => 'Yamada-kun and the Seven Witches', - ), - 'type' => 'Manga', - 'url' => 'https://kitsu.io/manga/yamada-kun-to-7-nin-no-majo', - )), - 'reading_status' => 'current', - 'notes' => '', - 'rereading' => false, - 'reread' => 0, - 'user_rating' => 9, - )), - 3 => - Aviat\AnimeClient\Types\MangaListItem::__set_state(array( - 'id' => '15312827', - 'mal_id' => '78523', - 'chapters' => - array ( - 'read' => 68, - 'total' => '-', - ), - 'volumes' => - array ( - 'read' => '-', - 'total' => '-', - ), - 'manga' => - Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array( - 'genres' => - array ( - 0 => 'Romance', - 1 => 'School', - 2 => 'Slice of Life', - ), - 'id' => '27175', - 'image' => 'https://media.kitsu.io/manga/poster_images/27175/small.jpg?1464379411', - 'slug' => 'relife', - 'title' => 'ReLIFE', - 'titles' => - array ( - ), - 'type' => 'Manga', - 'url' => 'https://kitsu.io/manga/relife', - )), - 'reading_status' => 'current', - 'notes' => '', - 'rereading' => false, - 'reread' => 0, - 'user_rating' => '-', - )), - 4 => - Aviat\AnimeClient\Types\MangaListItem::__set_state(array( - 'id' => '15084769', - 'mal_id' => '60815', - 'chapters' => - array ( - 'read' => 43, - 'total' => '-', - ), - 'volumes' => - array ( - 'read' => '-', - 'total' => '-', - ), - 'manga' => - Aviat\AnimeClient\Types\MangaListItemDetail::__set_state(array( - 'genres' => - array ( - 0 => 'Comedy', - 1 => 'School', - 2 => 'Slice of Life', - ), - 'id' => '25491', - 'image' => 'https://media.kitsu.io/manga/poster_images/25491/small.jpg?1434305043', - 'slug' => 'joshikausei', - 'title' => 'Joshikausei', - 'titles' => - array ( - ), - 'type' => 'Manga', - 'url' => 'https://kitsu.io/manga/joshikausei', - )), - 'reading_status' => 'current', - 'notes' => '', - 'rereading' => false, - 'reread' => 0, - 'user_rating' => 8, - )), -); diff --git a/tests/API/APIRequestBuilderTest.php b/tests/AnimeClient/API/APIRequestBuilderTest.php similarity index 86% rename from tests/API/APIRequestBuilderTest.php rename to tests/AnimeClient/API/APIRequestBuilderTest.php index 32d15060..116db20b 100644 --- a/tests/API/APIRequestBuilderTest.php +++ b/tests/AnimeClient/API/APIRequestBuilderTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -28,8 +28,7 @@ class APIRequestBuilderTest extends TestCase { protected $builder; - public function setUp() - { + public function setUp(): void { $this->builder = new class extends APIRequestBuilder { protected $baseUrl = 'https://httpbin.org/'; @@ -44,7 +43,7 @@ class APIRequestBuilderTest extends TestCase { $request = $this->builder->newRequest('GET', 'gzip') ->getFullRequest(); $response = getResponse($request); - $body = Json::decode(wait($response->getBody())); + $body = Json::decode(wait($response->getBody()->buffer())); $this->assertEquals(1, $body['gzipped']); } @@ -62,7 +61,7 @@ class APIRequestBuilderTest extends TestCase { ->getFullRequest(); $response = getResponse($request); - $body = Json::decode(wait($response->getBody())); + $body = Json::decode(wait($response->getBody()->buffer())); $this->assertEquals('Basic dXNlcm5hbWU6cGFzc3dvcmQ=', $body['headers']['Authorization']); } @@ -90,7 +89,7 @@ class APIRequestBuilderTest extends TestCase { ->getFullRequest(); $response = getResponse($request); - $body = Json::decode(wait($response->getBody())); + $body = Json::decode(wait($response->getBody()->buffer())); $this->assertEquals($expected, $body['args']); } @@ -107,7 +106,7 @@ class APIRequestBuilderTest extends TestCase { ->getFullRequest(); $response = getResponse($request); - $body = Json::decode(wait($response->getBody())); + $body = Json::decode(wait($response->getBody()->buffer())); $this->assertEquals($formValues, $body['form']); } @@ -131,7 +130,7 @@ class APIRequestBuilderTest extends TestCase { ->getFullRequest(); $response = getResponse($request); - $body = Json::decode(wait($response->getBody())); + $body = Json::decode(wait($response->getBody()->buffer())); $this->assertEquals($data, $body['json']); } diff --git a/tests/API/CacheTraitTest.php b/tests/AnimeClient/API/CacheTraitTest.php similarity index 90% rename from tests/API/CacheTraitTest.php rename to tests/AnimeClient/API/CacheTraitTest.php index 427b14c0..2bd73b83 100644 --- a/tests/API/CacheTraitTest.php +++ b/tests/AnimeClient/API/CacheTraitTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -23,8 +23,7 @@ class CacheTraitTest extends AnimeClientTestCase { protected $testClass; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->testClass = new class { use CacheTrait; diff --git a/tests/API/JsonAPITest.php b/tests/AnimeClient/API/JsonAPITest.php similarity index 92% rename from tests/API/JsonAPITest.php rename to tests/AnimeClient/API/JsonAPITest.php index ac08c1be..b9aac7a6 100644 --- a/tests/API/JsonAPITest.php +++ b/tests/AnimeClient/API/JsonAPITest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -26,8 +26,7 @@ class JsonAPITest extends TestCase { protected $organizedIncludes; protected $inlineIncluded; - public function setUp() - { + public function setUp(): void { $dir = __DIR__ . '/../test_data/JsonAPI'; $this->startData = Json::decodeFile("{$dir}/jsonApiExample.json"); $this->organizedIncludes = Json::decodeFile("{$dir}/organizedIncludes.json"); diff --git a/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php b/tests/AnimeClient/API/Kitsu/Transformer/AnimeListTransformerTest.php similarity index 94% rename from tests/API/Kitsu/Transformer/AnimeListTransformerTest.php rename to tests/AnimeClient/API/Kitsu/Transformer/AnimeListTransformerTest.php index c8ef8009..5ca9d5a8 100644 --- a/tests/API/Kitsu/Transformer/AnimeListTransformerTest.php +++ b/tests/AnimeClient/API/Kitsu/Transformer/AnimeListTransformerTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -27,8 +27,7 @@ class AnimeListTransformerTest extends AnimeClientTestCase { protected $afterTransform; protected $transformer; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->dir = AnimeClientTestCase::TEST_DATA_DIR . '/Kitsu'; diff --git a/tests/API/Kitsu/Transformer/AnimeTransformerTest.php b/tests/AnimeClient/API/Kitsu/Transformer/AnimeTransformerTest.php similarity index 90% rename from tests/API/Kitsu/Transformer/AnimeTransformerTest.php rename to tests/AnimeClient/API/Kitsu/Transformer/AnimeTransformerTest.php index 4e3ac657..e1d5fc85 100644 --- a/tests/API/Kitsu/Transformer/AnimeTransformerTest.php +++ b/tests/AnimeClient/API/Kitsu/Transformer/AnimeTransformerTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -27,8 +27,7 @@ class AnimeTransformerTest extends AnimeClientTestCase { protected $afterTransform; protected $transformer; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->dir = AnimeClientTestCase::TEST_DATA_DIR . '/Kitsu'; diff --git a/tests/API/Kitsu/Transformer/MangaListTransformerTest.php b/tests/AnimeClient/API/Kitsu/Transformer/MangaListTransformerTest.php similarity index 95% rename from tests/API/Kitsu/Transformer/MangaListTransformerTest.php rename to tests/AnimeClient/API/Kitsu/Transformer/MangaListTransformerTest.php index 7e60ef24..2e3164cc 100644 --- a/tests/API/Kitsu/Transformer/MangaListTransformerTest.php +++ b/tests/AnimeClient/API/Kitsu/Transformer/MangaListTransformerTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -33,8 +33,7 @@ class MangaListTransformerTest extends AnimeClientTestCase { protected $afterTransform; protected $transformer; - public function setUp() - { + public function setUp(): void { parent::setUp(); $kitsuModel = $this->container->get('kitsu-model'); diff --git a/tests/API/Kitsu/Transformer/MangaTransformerTest.php b/tests/AnimeClient/API/Kitsu/Transformer/MangaTransformerTest.php similarity index 91% rename from tests/API/Kitsu/Transformer/MangaTransformerTest.php rename to tests/AnimeClient/API/Kitsu/Transformer/MangaTransformerTest.php index 430fc72f..75b6e5b8 100644 --- a/tests/API/Kitsu/Transformer/MangaTransformerTest.php +++ b/tests/AnimeClient/API/Kitsu/Transformer/MangaTransformerTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -28,8 +28,7 @@ class MangaTransformerTest extends AnimeClientTestCase { protected $afterTransform; protected $transformer; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->dir = AnimeClientTestCase::TEST_DATA_DIR . '/Kitsu'; diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php index 8fb7c0d6..7559803d 100644 --- a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.php @@ -36,10 +36,10 @@ 1 => '小林さんちのメイドラゴン', ), )), - 'watching_status' => 'current', 'notes' => NULL, + 'private' => false, 'rewatching' => false, 'rewatched' => 0, 'user_rating' => '-', - 'private' => false, + 'watching_status' => 'current', )); diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.yml new file mode 100644 index 00000000..866e1a5b --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testTransform__1.yml @@ -0,0 +1,28 @@ +empty: false +id: '15839442' +mal_id: '33206' +episodes: + watched: '-' + total: '-' + length: null +airing: + status: 'Currently Airing' + started: '2017-01-12' + ended: null +anime: + empty: false + age_rating: null + cover_image: 'https://media.kitsu.io/anime/poster_images/12243/small.jpg?1481144116' + genres: [Comedy, Fantasy, 'Slice of Life'] + id: '12243' + show_type: TV + slug: kobayashi-san-chi-no-maid-dragon + streaming_links: { } + title: 'Kobayashi-san Chi no Maid Dragon' + titles: ['Miss Kobayashi''s Dragon Maid', 小林さんちのメイドラゴン] +notes: null +private: false +rewatching: false +rewatched: 0 +user_rating: '-' +watching_status: current diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.php diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.yml new file mode 100644 index 00000000..22fb6164 --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 0__1.yml @@ -0,0 +1,13 @@ +empty: false +id: 14047981 +anilist_item_id: null +mal_id: null +data: + empty: false + notes: 'Very formulaic.' + private: false + progress: 38 + ratingTwenty: 16 + reconsumeCount: 0 + reconsuming: false + status: current diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.php diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.yml new file mode 100644 index 00000000..6769276d --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 1__1.yml @@ -0,0 +1,13 @@ +empty: false +id: 14047981 +anilist_item_id: null +mal_id: '12345' +data: + empty: false + notes: 'Very formulaic.' + private: true + progress: 38 + ratingTwenty: 16 + reconsumeCount: 0 + reconsuming: true + status: current diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.php diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.yml new file mode 100644 index 00000000..adc5fcbe --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeListTransformerTest__testUntransform with data set 2__1.yml @@ -0,0 +1,12 @@ +empty: false +id: 14047983 +anilist_item_id: null +mal_id: '12347' +data: + empty: false + notes: '' + private: true + progress: 12 + reconsumeCount: 0 + reconsuming: true + status: current diff --git a/tests/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.php diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.yml new file mode 100644 index 00000000..f736c331 --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/AnimeTransformerTest__testTransform__1.yml @@ -0,0 +1,33 @@ +empty: false +characters: { } +staff: { } +age_rating: R +age_rating_guide: 'Violence, Profanity' +cover_image: 'https://media.kitsu.io/anime/poster_images/7442/small.jpg?1418580054' +episode_count: 25 +episode_length: 24 +genres: { } +id: 32344 +included: + categories: { 23: { name: 'Super Power', slug: super-power, description: null }, 11: { name: Fantasy, slug: fantasy, description: '' }, 4: { name: Drama, slug: drama, description: '' }, 1: { name: Action, slug: action, description: '' } } + mappings: { 5686: { externalSite: myanimelist/anime, externalId: '16498', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/5686/relationships/media', related: 'https://kitsu.io/api/edge/mappings/5686/media' } } } }, 14153: { externalSite: thetvdb/series, externalId: '267440', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/14153/relationships/media', related: 'https://kitsu.io/api/edge/mappings/14153/media' } } } }, 15073: { externalSite: thetvdb/season, externalId: '514060', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/15073/relationships/media', related: 'https://kitsu.io/api/edge/mappings/15073/media' } } } } } + streamingLinks: { 103: { url: 'http://www.crunchyroll.com/attack-on-titan', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/103/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/103/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/103/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/103/media' } } } }, 102: { url: 'http://www.hulu.com/attack-on-titan', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/102/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/102/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/102/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/102/media' } } } }, 101: { url: 'http://www.funimation.com/shows/attack-on-titan/videos/episodes', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/101/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/101/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/101/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/101/media' } } } }, 100: { url: t, subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/100/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/100/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/100/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/100/media' } } } } } +show_type: TV +slug: attack-on-titan +status: 'Finished Airing' +streaming_links: + - { meta: { name: Crunchyroll, link: true, image: streaming-logos/crunchyroll.svg }, link: 'http://www.crunchyroll.com/attack-on-titan', subs: [en], dubs: [ja] } + - { meta: { name: Funimation, link: true, image: streaming-logos/funimation.svg }, link: 'http://www.funimation.com/shows/attack-on-titan/videos/episodes', subs: [en], dubs: [ja] } + - { meta: { name: Hulu, link: true, image: streaming-logos/hulu.svg }, link: 'http://www.hulu.com/attack-on-titan', subs: [en], dubs: [ja] } + - { meta: { name: Netflix, link: false, image: streaming-logos/netflix.svg }, link: t, subs: [en], dubs: [ja] } +synopsis: | + Several hundred years ago, humans were nearly exterminated by titans. Titans are typically several stories tall, seem to have no intelligence, devour human beings and, worst of all, seem to do it for the pleasure rather than as a food source. A small percentage of humanity survived by enclosing themselves in a city protected by extremely high walls, even taller than the biggest of titans. Flash forward to the present and the city has not seen a titan in over 100 years. Teenage boy Eren and his foster sister Mikasa witness something horrific as the city walls are destroyed by a colossal titan that appears out of thin air. As the smaller titans flood the city, the two kids watch in horror as their mother is eaten alive. Eren vows that he will murder every single titan and take revenge for all of mankind. + + (Source: ANN) +title: 'Attack on Titan' +titles: + - 'Attack on Titan' + - 'Shingeki no Kyojin' + - 進撃の巨人 +trailer_id: n4Nj6Y_SNYI +url: 'https://kitsu.io/anime/attack-on-titan' diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.yml new file mode 100644 index 00000000..87effff0 --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaListTransformerTest__testTransform__1.yml @@ -0,0 +1,5 @@ +- null +- null +- null +- null +- null diff --git a/tests/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.php b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.php similarity index 100% rename from tests/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.php rename to tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.php diff --git a/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.yml b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.yml new file mode 100644 index 00000000..7ba6eb79 --- /dev/null +++ b/tests/AnimeClient/API/Kitsu/Transformer/__snapshots__/MangaTransformerTest__testTransform__1.yml @@ -0,0 +1,19 @@ +empty: false +characters: { } +chapter_count: '-' +cover_image: 'https://media.kitsu.io/manga/poster_images/20286/small.jpg?1434293999' +genres: { } +id: '20286' +included: + genres: { 3: { attributes: { name: Comedy, slug: comedy, description: null } }, 24: { attributes: { name: School, slug: school, description: null } }, 16: { attributes: { name: 'Slice of Life', slug: slice-of-life, description: '' } }, 14: { attributes: { name: Romance, slug: romance, description: '' } }, 18: { attributes: { name: Thriller, slug: thriller, description: null } } } + mappings: { 48014: { attributes: { externalSite: myanimelist/manga, externalId: '26769' } } } +manga_type: manga +staff: { } +synopsis: | + Usa, a high-school student aspiring to begin a bachelor lifestyle, moves into a new apartment only to discover that he not only shares a room with a perverted roommate that has an obsession for underaged girls, but also that another girl, Ritsu, a love-at-first-sight, is living in the same building as well! + (Source: Kirei Cake) +title: 'Bokura wa Minna Kawaisou' +titles: + - null +url: 'https://kitsu.io/manga/bokura-wa-minna-kawaisou' +volume_count: '-' diff --git a/tests/API/KitsuTest.php b/tests/AnimeClient/API/KitsuTest.php similarity index 92% rename from tests/API/KitsuTest.php rename to tests/AnimeClient/API/KitsuTest.php index 7f31e262..9ed312de 100644 --- a/tests/API/KitsuTest.php +++ b/tests/AnimeClient/API/KitsuTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/API/ParallelAPIRequestTest.php b/tests/AnimeClient/API/ParallelAPIRequestTest.php similarity index 93% rename from tests/API/ParallelAPIRequestTest.php rename to tests/AnimeClient/API/ParallelAPIRequestTest.php index f70fe17d..345e9840 100644 --- a/tests/API/ParallelAPIRequestTest.php +++ b/tests/AnimeClient/API/ParallelAPIRequestTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/AnimeClientTest.php b/tests/AnimeClient/AnimeClientTest.php similarity index 94% rename from tests/AnimeClientTest.php rename to tests/AnimeClient/AnimeClientTest.php index 57948d1e..0f73ab84 100644 --- a/tests/AnimeClientTest.php +++ b/tests/AnimeClient/AnimeClientTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/AnimeClientTestCase.php b/tests/AnimeClient/AnimeClientTestCase.php similarity index 77% rename from tests/AnimeClientTestCase.php rename to tests/AnimeClient/AnimeClientTestCase.php index c7fa67dd..c9c6a8a9 100644 --- a/tests/AnimeClientTestCase.php +++ b/tests/AnimeClient/AnimeClientTestCase.php @@ -4,53 +4,45 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Tests; -use const Aviat\AnimeClient\SRC_DIR; - use function Aviat\Ion\_dir; -use Aura\Web\WebFactory; use Aviat\Ion\Json; use PHPUnit\Framework\TestCase; use Spatie\Snapshots\MatchesSnapshots; -use Zend\Diactoros\{ +use Laminas\Diactoros\{ Response as HttpResponse, ServerRequestFactory }; -\define('ROOT_DIR', __DIR__ . '/../'); -\define('TEST_DATA_DIR', __DIR__ . '/test_data'); -\define('TEST_VIEW_DIR', __DIR__ . '/test_views'); - /** * Base class for TestCases */ class AnimeClientTestCase extends TestCase { use MatchesSnapshots; - // Test directory constants - const ROOT_DIR = ROOT_DIR; - const SRC_DIR = SRC_DIR; - const TEST_DATA_DIR = TEST_DATA_DIR; - const TEST_VIEW_DIR = TEST_VIEW_DIR; + public const ROOT_DIR = ROOT_DIR; + public const SRC_DIR = SRC_DIR; + public const TEST_DATA_DIR = __DIR__ . '/test_data'; + public const TEST_VIEW_DIR = __DIR__ . '/test_views'; protected $container; protected static $staticContainer; protected static $session_handler; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { // Use mock session handler //$session_handler = new TestSessionHandler(); @@ -58,21 +50,18 @@ class AnimeClientTestCase extends TestCase { //self::$session_handler = $session_handler; // Remove test cache files - $files = glob(_dir(TEST_DATA_DIR, 'cache', '*.json')); + $files = glob(_dir(self::TEST_DATA_DIR, 'cache', '*.json')); array_map('unlink', $files); } - public function setUp() + public function setUp(): void { parent::setUp(); - $ROOT_DIR = realpath(_dir(__DIR__, '/../')); - $APP_DIR = _dir($ROOT_DIR, 'app'); - $config_array = [ 'asset_path' => '/assets', 'img_cache_path' => _dir(ROOT_DIR, 'public/images'), - 'data_cache_path' => _dir(TEST_DATA_DIR, 'cache'), + 'data_cache_path' => _dir(self::TEST_DATA_DIR, 'cache'), 'cache' => [ 'driver' => 'null', 'connection' => [] @@ -105,11 +94,11 @@ class AnimeClientTestCase extends TestCase { ]; // Set up DI container - $di = require _dir($APP_DIR, 'bootstrap.php'); + $di = require _dir(self::ROOT_DIR, 'app', 'bootstrap.php'); $container = $di($config_array); // Use mock session handler - $container->set('session-handler', function() { + $container->set('session-handler', static function() { $session_handler = new TestSessionHandler(); session_set_save_handler($session_handler, TRUE); return $session_handler; @@ -139,7 +128,7 @@ class AnimeClientTestCase extends TestCase { array_merge($default, $supers) ); $this->container->setInstance('request', $request); - $this->container->set('response', function() { + $this->container->set('response', static function() { return new HttpResponse(); }); } @@ -154,7 +143,7 @@ class AnimeClientTestCase extends TestCase { public function getMockFile(): string { $args = func_get_args(); - array_unshift($args, TEST_DATA_DIR); + array_unshift($args, self::TEST_DATA_DIR); $filePath = implode(DIRECTORY_SEPARATOR, $args); return file_get_contents($filePath); @@ -165,6 +154,7 @@ class AnimeClientTestCase extends TestCase { * * Takes multiple path arguments * + * @param array $args * @return mixed - the decoded data */ public function getMockFileData(...$args) diff --git a/tests/Command/BaseCommandTest.php b/tests/AnimeClient/Command/BaseCommandTest.php similarity index 70% rename from tests/Command/BaseCommandTest.php rename to tests/AnimeClient/Command/BaseCommandTest.php index ac1d41a4..76b8555b 100644 --- a/tests/Command/BaseCommandTest.php +++ b/tests/AnimeClient/Command/BaseCommandTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,20 +20,24 @@ use Aviat\AnimeClient\Command\BaseCommand; use Aviat\AnimeClient\Tests\AnimeClientTestCase; use Aviat\Ion\Friend; use ConsoleKit\Console; +use Aviat\Ion\Di\Container; + +class Command extends BaseCommand { + +} class BaseCommandTest extends AnimeClientTestCase { protected $base; protected $friend; - - public function setUp() - { - $this->base = new BaseCommand(new Console()); + + public function setUp(): void { + $this->base = new Command(new Console()); $this->friend = new Friend($this->base); } - public function testSetupContainer() + public function testSetupContainer(): void { $container = $this->friend->setupContainer(); - $this->assertInstanceOf('Aviat\Ion\Di\Container', $container); + $this->assertInstanceOf(Container::class, $container); } } \ No newline at end of file diff --git a/tests/ControllerTest.php b/tests/AnimeClient/ControllerTest.php similarity index 94% rename from tests/ControllerTest.php rename to tests/AnimeClient/ControllerTest.php index 9bb418ff..5b07a40d 100644 --- a/tests/ControllerTest.php +++ b/tests/AnimeClient/ControllerTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -31,8 +31,7 @@ class ControllerTest extends AnimeClientTestCase { protected $BaseController; - public function setUp() - { + public function setUp(): void { parent::setUp(); // Create Request/Response Objects diff --git a/tests/DispatcherTest.php b/tests/AnimeClient/DispatcherTest.php similarity index 90% rename from tests/DispatcherTest.php rename to tests/AnimeClient/DispatcherTest.php index a0bcf6b0..c6e07645 100644 --- a/tests/DispatcherTest.php +++ b/tests/AnimeClient/DispatcherTest.php @@ -4,18 +4,19 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Tests; +use Aura\Router\Route; use Aviat\AnimeClient\Controller; use Aviat\AnimeClient\Dispatcher; use Aviat\AnimeClient\UrlGenerator; @@ -31,7 +32,7 @@ class DispatcherTest extends AnimeClientTestCase { protected $config; protected $urlGenerator; - protected function doSetUp($config, $uri, $host) + protected function doSetUp($config, $uri, $host): void { // Set up the environment $_SERVER = array_merge($_SERVER, [ @@ -63,13 +64,13 @@ class DispatcherTest extends AnimeClientTestCase { $this->container->setInstance('url-generator', $this->urlGenerator); } - public function testRouterSanity() + public function testRouterSanity(): void { $this->doSetUp([], '/', 'localhost'); - $this->assertInternalType('object', $this->router); + $this->assertIsObject($this->router); } - public function dataRoute() + public function dataRoute(): array { $defaultConfig = [ 'routes' => [ @@ -142,7 +143,7 @@ class DispatcherTest extends AnimeClientTestCase { /** * @dataProvider dataRoute */ - public function testRoute($config, $controller, $host, $uri) + public function testRoute($config, $controller, $host, $uri): void { $this->doSetUp($config, $uri, $host); @@ -150,7 +151,7 @@ class DispatcherTest extends AnimeClientTestCase { // Check route setup $this->assertEquals($config['routes'], $this->config->get('routes'), 'Incorrect route path'); - $this->assertInternalType('array', $this->router->getOutputRoutes()); + $this->assertIsArray($this->router->getOutputRoutes()); // Check environment variables $this->assertEquals($uri, $request->getServerParams()['REQUEST_URI']); @@ -162,10 +163,10 @@ class DispatcherTest extends AnimeClientTestCase { // Make sure the route matches, by checking that it is actually an object $route = $this->router->getRoute(); - $this->assertInstanceOf(\Aura\Router\Route::class, $route, 'Route is invalid, not matched'); + $this->assertInstanceOf(Route::class, $route, 'Route is invalid, not matched'); } - public function testDefaultRoute() + public function testDefaultRoute(): void { $config = [ 'config' => [ @@ -202,7 +203,7 @@ class DispatcherTest extends AnimeClientTestCase { $this->urlGenerator->defaultUrl('foo'); } - public function dataGetControllerList() + public function dataGetControllerList(): array { $expectedList = [ 'anime' => Controller\Anime::class, @@ -246,7 +247,7 @@ class DispatcherTest extends AnimeClientTestCase { /** * @dataProvider dataGetControllerList */ - public function testGetControllerList($config, $expected) + public function testGetControllerList($config, $expected): void { $this->doSetUp($config, '/', 'localhost'); $this->assertEquals($expected, $this->router->getControllerList()); diff --git a/tests/AnimeClient/FormGeneratorTest.php b/tests/AnimeClient/FormGeneratorTest.php new file mode 100644 index 00000000..b3096098 --- /dev/null +++ b/tests/AnimeClient/FormGeneratorTest.php @@ -0,0 +1,277 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\Tests; + +use Aviat\AnimeClient\FormGenerator; + +/** + * Map config settings to form fields + */ +const SETTINGS_MAP = [ + 'anilist' => [ + 'enabled' => [ + 'type' => 'boolean', + 'title' => 'Enable Anilist Integration', + 'default' => FALSE, + 'description' => 'Enable syncing data between Kitsu and Anilist. Requires appropriate API keys to be set in config', + ], + 'client_id' => [ + 'type' => 'string', + 'title' => 'Anilist API Client ID', + 'default' => '', + 'description' => 'The client id for your Anilist API application', + ], + 'client_secret' => [ + 'type' => 'string', + 'title' => 'Anilist API Client Secret', + 'default' => '', + 'description' => 'The client secret for your Anilist API application', + ], + 'username' => [ + 'type' => 'string', + 'title' => 'Anilist Username', + 'default' => '', + 'description' => 'Login username for Anilist account to integrate with', + ], + 'access_token' => [ + 'type' => 'hidden', + 'title' => 'API Access Token', + 'default' => '', + 'description' => 'The Access code for accessing the Anilist API', + 'readonly' => TRUE, + ], + 'access_token_expires' => [ + 'type' => 'string', + 'title' => 'Expiration timestamp of the access token', + 'default' => '0', + 'description' => 'The unix timestamp of when the access token expires.', + 'readonly' => TRUE, + ], + 'refresh_token' => [ + 'type' => 'string', + 'title' => 'API Refresh Token', + 'default' => '', + 'description' => 'Token to refresh the access token before it expires', + 'readonly' => TRUE, + ], + 'special_hidden_flag' => [ + 'type' => 'string', + 'title' => '', + 'display' => FALSE, + 'description' => '', + 'value' => 'foo_bar', + ] + ], + + 'cache' => [ + 'driver' => [ + 'type' => 'select', + 'title' => 'Cache Type', + 'description' => 'The Cache backend', + 'options' => [ + 'APCu' => 'apcu', + 'Memcached' => 'memcached', + 'Redis' => 'redis', + 'No Cache' => 'null' + ], + ], + 'connection' => [ + 'type' => 'subfield', + 'title' => 'Connection', + 'fields' => [ + 'host' => [ + 'type' => 'string', + 'title' => 'Cache Host', + 'description' => 'Host of the cache backend to connect to', + ], + 'port' => [ + 'type' => 'string', + 'title' => 'Cache Port', + 'description' => 'Port of the cache backend to connect to', + 'default' => NULL, + ], + 'password' => [ + 'type' => 'string', + 'title' => 'Cache Password', + 'description' => 'Password to connect to cache backend', + 'default' => NULL, + ], + 'persistent' => [ + 'type' => 'boolean', + 'title' => 'Persistent Cache Connection', + 'description' => 'Whether to have a persistent connection to the cache', + 'default' => FALSE, + ], + 'database' => [ + 'type' => 'string', + 'title' => 'Cache Database', + 'default' => '1', + 'description' => 'Cache database number for Redis', + ], + ], + ], + ], + 'config' => [ + 'kitsu_username' => [ + 'type' => 'string', + 'title' => 'Kitsu Username', + 'default' => '', + 'description' => 'Username of the account to pull list data from.', + ], + 'whose_list' => [ + 'type' => 'string', + 'title' => 'Whose List', + 'default' => 'Somebody', + 'description' => 'Name of the owner of the list data.', + ], + 'theme' => [ + 'type' => 'select', + 'title' => 'Theme', + 'default' => 'auto', + 'description' => 'Which color scheme to use?', + 'options' => [ + 'Automatically match OS theme' => 'auto', + 'Original Light Theme' => 'light', + 'Dark Theme' => 'dark', + ] + ], + 'show_anime_collection' => [ + 'type' => 'boolean', + 'title' => 'Show Anime Collection', + 'default' => FALSE, + 'description' => 'Should the anime collection be shown?', + ], + 'show_manga_collection' => [ + 'type' => 'boolean', + 'title' => 'Show Manga Collection', + 'default' => FALSE, + 'description' => 'Should the manga collection be shown?', + ], + 'default_list' => [ + 'type' => 'select', + 'title' => 'Default List', + 'description' => 'Which list to show by default.', + 'options' => [ + 'Anime' => 'anime', + 'Manga' => 'manga', + ], + ], + 'default_anime_list_path' => [ //watching|plan_to_watch|on_hold|dropped|completed|all + 'type' => 'select', + 'title' => 'Default Anime List Section', + 'description' => 'Which part of the anime list to show by default.', + 'options' => [ + 'Watching' => 'watching', + 'Plan to Watch' => 'plan_to_watch', + 'On Hold' => 'on_hold', + 'Dropped' => 'dropped', + 'Completed' => 'completed', + 'All' => 'all', + ] + ], + 'default_manga_list_path' => [ //reading|plan_to_read|on_hold|dropped|completed|all + 'type' => 'select', + 'title' => 'Default Manga List Section', + 'description' => 'Which part of the manga list to show by default.', + 'options' => [ + 'Reading' => 'reading', + 'Plan to Read' => 'plan_to_read', + 'On Hold' => 'on_hold', + 'Dropped' => 'dropped', + 'Completed' => 'completed', + 'All' => 'all', + ] + ] + ], + 'database' => [ + 'type' => [ + 'type' => 'select', + 'title' => 'Database Type', + 'options' => [ + 'MySQL' => 'mysql', + 'PostgreSQL' => 'pgsql', + 'SQLite' => 'sqlite', + ], + 'default' => 'sqlite', + 'description' => 'Type of database to connect to', + ], + 'host' => [ + 'type' => 'string', + 'title' => 'Host', + 'description' => 'The host of the database server', + ], + 'user' => [ + 'type' => 'string', + 'title' => 'User', + 'description' => 'Database connection user', + ], + 'pass' => [ + 'type' => 'string', + 'title' => 'Password', + 'description' => 'Database connection password' + ], + 'port' => [ + 'type' => 'string', + 'title' => 'Port', + 'description' => 'Database connection port', + 'default' => NULL, + ], + 'database' => [ + 'type' => 'string', + 'title' => 'Database Name', + 'description' => 'Name of the database/schema to connect to', + ], + 'file' => [ + 'type' => 'string', + 'title' => 'Database File', + 'description' => 'Path to the database file, if required by the current database type.', + 'default' => 'anime_collection.sqlite', + ], + ], +]; + + +class FormGeneratorTest extends AnimeClientTestCase { + protected $generator; + + public function setUp(): void + { + parent::setUp(); + + $this->generator = new FormGenerator($this->container); + } + + public function testSanity(): void + { + $generator = new FormGenerator($this->container); + $this->assertInstanceOf(FormGenerator::class, $generator); + } + + public function testGeneration(): void + { + // $html = $this->generator->generate('database', SETTINGS_MAP); + // $this->assertMatchesHtmlSnapshot($html); + foreach (SETTINGS_MAP as $section => $fields) + { + foreach ($fields as $name => $config) + { + $html = $this->generator->generate($name, $config); + $this->assertMatchesSnapshot($html); + } + } + } +} \ No newline at end of file diff --git a/tests/Helper/MenuHelperTest.php b/tests/AnimeClient/Helper/MenuHelperTest.php similarity index 94% rename from tests/Helper/MenuHelperTest.php rename to tests/AnimeClient/Helper/MenuHelperTest.php index d8c2e54c..9501e1a2 100644 --- a/tests/Helper/MenuHelperTest.php +++ b/tests/AnimeClient/Helper/MenuHelperTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -20,12 +20,11 @@ use Aviat\AnimeClient\Helper\Menu as MenuHelper; use Aviat\AnimeClient\Tests\AnimeClientTestCase; class MenuHelperTest extends AnimeClientTestCase { - + protected $helper; protected $urlGenerator; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->helper = $this->container->get('html-helper'); $this->urlGenerator = $this->container->get('url-generator'); diff --git a/tests/Helper/PictureHelperTest.php b/tests/AnimeClient/Helper/PictureHelperTest.php similarity index 97% rename from tests/Helper/PictureHelperTest.php rename to tests/AnimeClient/Helper/PictureHelperTest.php index 22869673..15d3a866 100644 --- a/tests/Helper/PictureHelperTest.php +++ b/tests/AnimeClient/Helper/PictureHelperTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php new file mode 100644 index 00000000..5348ee59 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php new file mode 100644 index 00000000..a6394993 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php new file mode 100644 index 00000000..7a373757 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php new file mode 100644 index 00000000..068b9d38 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php similarity index 55% rename from tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php rename to tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php index 054958a1..701fef7d 100644 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set png placeholder image__1.php @@ -1 +1 @@ -'; +'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php new file mode 100644 index 00000000..cd9e4d54 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php new file mode 100644 index 00000000..ef7f698a --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php @@ -0,0 +1 @@ +Example text'; diff --git a/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php new file mode 100644 index 00000000..0f6d63d4 --- /dev/null +++ b/tests/AnimeClient/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php @@ -0,0 +1 @@ +'; diff --git a/tests/MenuGeneratorTest.php b/tests/AnimeClient/MenuGeneratorTest.php similarity index 94% rename from tests/MenuGeneratorTest.php rename to tests/AnimeClient/MenuGeneratorTest.php index bf0b1922..193a26f2 100644 --- a/tests/MenuGeneratorTest.php +++ b/tests/AnimeClient/MenuGeneratorTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -24,8 +24,7 @@ class MenuGeneratorTest extends AnimeClientTestCase { protected $generator; protected $friend; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->generator = new MenuGenerator($this->container); } diff --git a/tests/RequirementsTest.php b/tests/AnimeClient/RequirementsTest.php similarity index 90% rename from tests/RequirementsTest.php rename to tests/AnimeClient/RequirementsTest.php index 64412c51..1acfa9fc 100644 --- a/tests/RequirementsTest.php +++ b/tests/AnimeClient/RequirementsTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/RoutingBaseTest.php b/tests/AnimeClient/RoutingBaseTest.php similarity index 94% rename from tests/RoutingBaseTest.php rename to tests/AnimeClient/RoutingBaseTest.php index 8ac1bb34..63cb48c8 100644 --- a/tests/RoutingBaseTest.php +++ b/tests/AnimeClient/RoutingBaseTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/TestSessionHandler.php b/tests/AnimeClient/TestSessionHandler.php similarity index 80% rename from tests/TestSessionHandler.php rename to tests/AnimeClient/TestSessionHandler.php index de61ffba..403bcf26 100644 --- a/tests/TestSessionHandler.php +++ b/tests/AnimeClient/TestSessionHandler.php @@ -4,29 +4,29 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ namespace Aviat\AnimeClient\Tests; class TestSessionHandler implements \SessionHandlerInterface { - + public $data = []; public $savePath = './test_data/sessions'; - - public function close() + + public function close() { return TRUE; } - - public function destroy($id) + + public function destroy($id) { $file = "$this->savePath/$id"; if (file_exists($file)) @@ -36,13 +36,13 @@ class TestSessionHandler implements \SessionHandlerInterface { $this->data[$id] = []; return TRUE; } - + public function gc($maxLifetime) { return TRUE; } - - public function open($savePath, $name) + + public function open($savePath, $name) { /*if ( ! array_key_exists($savePath, $this->data)) { @@ -51,19 +51,19 @@ class TestSessionHandler implements \SessionHandlerInterface { }*/ return TRUE; } - - public function read($id) + + public function read($id) { return json_decode(@file_get_contents("$this->savePath/$id"), TRUE); } - - public function write($id, $data) + + public function write($id, $data) { $file = "$this->savePath/$id"; file_put_contents($file, json_encode($data)); - + return TRUE; } - + } // End of TestSessionHandler.php \ No newline at end of file diff --git a/tests/UrlGeneratorTest.php b/tests/AnimeClient/UrlGeneratorTest.php similarity index 92% rename from tests/UrlGeneratorTest.php rename to tests/AnimeClient/UrlGeneratorTest.php index 4f3322ab..dfbb2ff7 100644 --- a/tests/UrlGeneratorTest.php +++ b/tests/AnimeClient/UrlGeneratorTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ diff --git a/tests/UtilTest.php b/tests/AnimeClient/UtilTest.php similarity index 93% rename from tests/UtilTest.php rename to tests/AnimeClient/UtilTest.php index aac2579f..5ceca47c 100644 --- a/tests/UtilTest.php +++ b/tests/AnimeClient/UtilTest.php @@ -4,13 +4,13 @@ * * An API client for Kitsu to manage anime and manga watch lists * - * PHP version 7.1 + * PHP version 7.3 * * @package HummingbirdAnimeClient * @author Timothy J. Warren - * @copyright 2015 - 2018 Timothy J. Warren + * @copyright 2015 - 2020 Timothy J. Warren * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 4.1 + * @version 4.2 * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient */ @@ -19,11 +19,10 @@ namespace Aviat\AnimeClient\Tests; use Aviat\AnimeClient\Util; class UtilTest extends AnimeClientTestCase { - + protected $util; - public function setUp() - { + public function setUp(): void { parent::setUp(); $this->util = new Util($this->container); } diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.html new file mode 100644 index 00000000..7baef2cd --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.html @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.php new file mode 100644 index 00000000..8206ba74 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__1.php @@ -0,0 +1,3 @@ + Yes + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.html new file mode 100644 index 00000000..0d6f05c3 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.php new file mode 100644 index 00000000..2fc21a3b --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__10.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.html new file mode 100644 index 00000000..9d0d056e --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.php new file mode 100644 index 00000000..ea5de9fd --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__11.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.html new file mode 100644 index 00000000..a7fe93fe --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.php new file mode 100644 index 00000000..b1e33914 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__12.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.html new file mode 100644 index 00000000..ce059c77 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.html @@ -0,0 +1,8 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.php new file mode 100644 index 00000000..d1f4af33 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__13.php @@ -0,0 +1,6 @@ + + + + + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.html new file mode 100644 index 00000000..ac95bc17 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.html @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.php new file mode 100644 index 00000000..d4346410 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__14.php @@ -0,0 +1,3 @@ + Yes + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.html new file mode 100644 index 00000000..0127f5f2 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.html @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.php new file mode 100644 index 00000000..b0f88bdd --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__15.php @@ -0,0 +1,3 @@ + Yes + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.html new file mode 100644 index 00000000..40801d06 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.html @@ -0,0 +1,7 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.php new file mode 100644 index 00000000..804a1a2e --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__16.php @@ -0,0 +1,5 @@ + + + + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.html new file mode 100644 index 00000000..5c7bd23a --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.html @@ -0,0 +1,11 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.php new file mode 100644 index 00000000..a82a2acb --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__17.php @@ -0,0 +1,9 @@ + + + + + + + + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.html new file mode 100644 index 00000000..89e6ab84 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.html @@ -0,0 +1,11 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.php new file mode 100644 index 00000000..0ce5af29 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__18.php @@ -0,0 +1,9 @@ + + + + + + + + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.html new file mode 100644 index 00000000..37b8332f --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.html @@ -0,0 +1,8 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.php new file mode 100644 index 00000000..8934dafb --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__19.php @@ -0,0 +1,6 @@ + + + + + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.html new file mode 100644 index 00000000..4a440040 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.php new file mode 100644 index 00000000..9fc4ac0e --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__2.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.html new file mode 100644 index 00000000..ec3c00cf --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.php new file mode 100644 index 00000000..bd5f0d42 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__20.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.html new file mode 100644 index 00000000..75248dc7 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.php new file mode 100644 index 00000000..2b561aef --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__21.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.html new file mode 100644 index 00000000..f7069230 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.php new file mode 100644 index 00000000..1b1ec486 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__22.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.html new file mode 100644 index 00000000..1074dd4c --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.php new file mode 100644 index 00000000..9085638f --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__23.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.html new file mode 100644 index 00000000..c0d27a30 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.php new file mode 100644 index 00000000..dfb792e8 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__24.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.html new file mode 100644 index 00000000..adcfd0b6 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.php new file mode 100644 index 00000000..982bef2e --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__25.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.html new file mode 100644 index 00000000..cf3a702f --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.php new file mode 100644 index 00000000..a3597a93 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__3.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.html new file mode 100644 index 00000000..7dc250d9 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.php new file mode 100644 index 00000000..3dcdd0be --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__4.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.html new file mode 100644 index 00000000..439fbd5c --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.php new file mode 100644 index 00000000..cd149af8 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__5.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.html new file mode 100644 index 00000000..d54b6cdc --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.php new file mode 100644 index 00000000..294d675b --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__6.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.html new file mode 100644 index 00000000..4e23b746 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.php new file mode 100644 index 00000000..c8650aa1 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__7.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.html new file mode 100644 index 00000000..1b30eee9 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.php new file mode 100644 index 00000000..05321fb5 --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__8.php @@ -0,0 +1,2 @@ + +'; diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.html b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.html new file mode 100644 index 00000000..c096fb1d --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.html @@ -0,0 +1,9 @@ + + + + diff --git a/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.php b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.php new file mode 100644 index 00000000..ee7f474c --- /dev/null +++ b/tests/AnimeClient/__snapshots__/FormGeneratorTest__testGeneration__9.php @@ -0,0 +1,7 @@ + + + + + + +'; diff --git a/tests/mocks.php b/tests/AnimeClient/mocks.php similarity index 100% rename from tests/mocks.php rename to tests/AnimeClient/mocks.php diff --git a/tests/test_data/JsonAPI/inlineIncluded.json b/tests/AnimeClient/test_data/JsonAPI/inlineIncluded.json similarity index 100% rename from tests/test_data/JsonAPI/inlineIncluded.json rename to tests/AnimeClient/test_data/JsonAPI/inlineIncluded.json diff --git a/tests/test_data/JsonAPI/jsonApiExample.json b/tests/AnimeClient/test_data/JsonAPI/jsonApiExample.json similarity index 100% rename from tests/test_data/JsonAPI/jsonApiExample.json rename to tests/AnimeClient/test_data/JsonAPI/jsonApiExample.json diff --git a/tests/test_data/JsonAPI/organizedIncludes.json b/tests/AnimeClient/test_data/JsonAPI/organizedIncludes.json similarity index 100% rename from tests/test_data/JsonAPI/organizedIncludes.json rename to tests/AnimeClient/test_data/JsonAPI/organizedIncludes.json diff --git a/tests/test_data/Kitsu/animeAfterTransform.json b/tests/AnimeClient/test_data/Kitsu/animeAfterTransform.json similarity index 100% rename from tests/test_data/Kitsu/animeAfterTransform.json rename to tests/AnimeClient/test_data/Kitsu/animeAfterTransform.json diff --git a/tests/test_data/Kitsu/animeBeforeTransform.json b/tests/AnimeClient/test_data/Kitsu/animeBeforeTransform.json similarity index 100% rename from tests/test_data/Kitsu/animeBeforeTransform.json rename to tests/AnimeClient/test_data/Kitsu/animeBeforeTransform.json diff --git a/tests/test_data/Kitsu/animeListItemAfterTransform.json b/tests/AnimeClient/test_data/Kitsu/animeListItemAfterTransform.json similarity index 100% rename from tests/test_data/Kitsu/animeListItemAfterTransform.json rename to tests/AnimeClient/test_data/Kitsu/animeListItemAfterTransform.json diff --git a/tests/test_data/Kitsu/animeListItemBeforeTransform.json b/tests/AnimeClient/test_data/Kitsu/animeListItemBeforeTransform.json similarity index 100% rename from tests/test_data/Kitsu/animeListItemBeforeTransform.json rename to tests/AnimeClient/test_data/Kitsu/animeListItemBeforeTransform.json diff --git a/tests/test_data/Kitsu/mangaAfterTransform.json b/tests/AnimeClient/test_data/Kitsu/mangaAfterTransform.json similarity index 100% rename from tests/test_data/Kitsu/mangaAfterTransform.json rename to tests/AnimeClient/test_data/Kitsu/mangaAfterTransform.json diff --git a/tests/test_data/Kitsu/mangaBeforeTransform.json b/tests/AnimeClient/test_data/Kitsu/mangaBeforeTransform.json similarity index 100% rename from tests/test_data/Kitsu/mangaBeforeTransform.json rename to tests/AnimeClient/test_data/Kitsu/mangaBeforeTransform.json diff --git a/tests/test_data/Kitsu/mangaListAfterTransform.json b/tests/AnimeClient/test_data/Kitsu/mangaListAfterTransform.json similarity index 100% rename from tests/test_data/Kitsu/mangaListAfterTransform.json rename to tests/AnimeClient/test_data/Kitsu/mangaListAfterTransform.json diff --git a/tests/test_data/Kitsu/mangaListBeforeTransform.json b/tests/AnimeClient/test_data/Kitsu/mangaListBeforeTransform.json similarity index 100% rename from tests/test_data/Kitsu/mangaListBeforeTransform.json rename to tests/AnimeClient/test_data/Kitsu/mangaListBeforeTransform.json diff --git a/tests/test_data/invalid_json.json b/tests/AnimeClient/test_data/invalid_json.json similarity index 100% rename from tests/test_data/invalid_json.json rename to tests/AnimeClient/test_data/invalid_json.json diff --git a/tests/test_data/valid_json.json b/tests/AnimeClient/test_data/valid_json.json similarity index 100% rename from tests/test_data/valid_json.json rename to tests/AnimeClient/test_data/valid_json.json diff --git a/tests/test_views/test_view.php b/tests/AnimeClient/test_views/test_view.php similarity index 100% rename from tests/test_views/test_view.php rename to tests/AnimeClient/test_views/test_view.php diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php deleted file mode 100644 index f852d0bc..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Full webp URL__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php deleted file mode 100644 index 4b6711e0..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set Partial webp URL__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php deleted file mode 100644 index ee4c502d..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set bmp with gif fallback__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php deleted file mode 100644 index 0cecd592..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set jpeg2000__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php deleted file mode 100644 index 2b3023ef..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set simple image with attributes__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php deleted file mode 100644 index a8900e93..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set svg with png fallback and lots of attributes__1.php +++ /dev/null @@ -1 +0,0 @@ -Example text'; diff --git a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php b/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php deleted file mode 100644 index d796ce75..00000000 --- a/tests/Helper/__snapshots__/PictureHelperTest__testPictureHelper with data set webp placeholder image__1.php +++ /dev/null @@ -1 +0,0 @@ -'; diff --git a/tests/Ion/BaseModelTest.php b/tests/Ion/BaseModelTest.php new file mode 100644 index 00000000..e5fe6562 --- /dev/null +++ b/tests/Ion/BaseModelTest.php @@ -0,0 +1,28 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\Model as BaseModel; + +class BaseModelTest extends IonTestCase { + + public function testBaseModelSanity() + { + $baseModel = new BaseModel(); + $this->assertTrue(is_object($baseModel)); + } +} \ No newline at end of file diff --git a/tests/Ion/ConfigTest.php b/tests/Ion/ConfigTest.php new file mode 100644 index 00000000..1cb2cf15 --- /dev/null +++ b/tests/Ion/ConfigTest.php @@ -0,0 +1,151 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\Config; + +class ConfigTest extends IonTestCase { + + protected $config; + + public function setUp(): void + { + $this->config = new Config([ + 'foo' => 'bar', + 'asset_path' => '/assets', + 'bar' => 'baz', + 'a' => [ + 'b' => [ + 'c' => TRUE, + ], + ], + ]); + } + + public function testConfigHas(): void + { + $this->assertTrue($this->config->has('foo')); + $this->assertTrue($this->config->has(['a', 'b', 'c'])); + + $this->assertFalse($this->config->has('baz')); + $this->assertFalse($this->config->has(['c', 'b', 'a'])); + } + + public function testConfigGet(): void + { + $this->assertEquals('bar', $this->config->get('foo')); + $this->assertEquals('baz', $this->config->get('bar')); + $this->assertNull($this->config->get('baz')); + $this->assertNull($this->config->get(['apple', 'sauce', 'is'])); + } + + public function testConfigSet(): void + { + $ret = $this->config->set('foo', 'foobar'); + $this->assertInstanceOf(Config::class, $ret); + $this->assertEquals('foobar', $this->config->get('foo')); + + $this->config->set(['apple', 'sauce', 'is'], 'great'); + $apple = $this->config->get('apple'); + $this->assertEquals('great', $apple['sauce']['is'], 'Config value not set correctly'); + + $this->assertEquals('great', $this->config->get(['apple', 'sauce', 'is']), "Array argument get for config failed."); + } + + public function testConfigBadSet(): void + { + $this->expectException('InvalidArgumentException'); + $this->config->set(NULL, FALSE); + } + + public function dataConfigDelete(): array + { + return [ + 'top level delete' => [ + 'key' => 'apple', + 'assertKeys' => [ + [ + 'path' => ['apple', 'sauce', 'is'], + 'expected' => NULL + ], + [ + 'path' => ['apple', 'sauce'], + 'expected' => NULL + ], + [ + 'path' => 'apple', + 'expected' => NULL + ] + ] + ], + 'mid level delete' => [ + 'key' => ['apple', 'sauce'], + 'assertKeys' => [ + [ + 'path' => ['apple', 'sauce', 'is'], + 'expected' => NULL + ], + [ + 'path' => ['apple', 'sauce'], + 'expected' => NULL + ], + [ + 'path' => 'apple', + 'expected' => [ + 'sauce' => NULL + ] + ] + ] + ], + 'deep delete' => [ + 'key' => ['apple', 'sauce', 'is'], + 'assertKeys' => [ + [ + 'path' => ['apple', 'sauce', 'is'], + 'expected' => NULL + ], + [ + 'path' => ['apple', 'sauce'], + 'expected' => [ + 'is' => NULL + ] + ] + ] + ] + ]; + } + + /** + * @dataProvider dataConfigDelete + */ + public function testConfigDelete($key, array $assertKeys): void + { + $config = new Config([]); + $config->set(['apple', 'sauce', 'is'], 'great'); + $config->delete($key); + + foreach($assertKeys as $pair) + { + $this->assertEquals($pair['expected'], $config->get($pair['path'])); + } + } + + public function testGetNonExistentConfigItem(): void + { + $this->assertNull($this->config->get('foobar')); + } +} \ No newline at end of file diff --git a/tests/Ion/Di/ContainerAwareTest.php b/tests/Ion/Di/ContainerAwareTest.php new file mode 100644 index 00000000..6279e9a3 --- /dev/null +++ b/tests/Ion/Di/ContainerAwareTest.php @@ -0,0 +1,55 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Di; + +use Aviat\Ion\Di\{Container, ContainerAware, ContainerInterface}; +use Aviat\Ion\Tests\IonTestCase; + +class Aware { + use ContainerAware; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } +} + + +class ContainerAwareTest extends IonTestCase { + + protected $aware; + + public function setUp(): void + { + $this->container = new Container(); + $this->aware = new Aware($this->container); + } + + public function testContainerAwareTrait(): void + { + // The container was set in setup + // check that the get method returns the same + $this->assertSame($this->container, $this->aware->getContainer()); + + $container2 = new Container([ + 'foo' => 'bar', + 'baz' => 'foobar' + ]); + $this->aware->setContainer($container2); + $this->assertSame($container2, $this->aware->getContainer()); + } +} \ No newline at end of file diff --git a/tests/Ion/Di/ContainerTest.php b/tests/Ion/Di/ContainerTest.php new file mode 100644 index 00000000..780de61d --- /dev/null +++ b/tests/Ion/Di/ContainerTest.php @@ -0,0 +1,205 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Di; + +use Aviat\Ion\Di\{Container, ContainerAware}; +use Aviat\Ion\Di\Exception\ContainerException; +use Aviat\Ion\Tests\IonTestCase; +use Monolog\Logger; +use Monolog\Handler\{TestHandler, NullHandler}; +use Aviat\Ion\Di\ContainerInterface; +use Aviat\Ion\Di\Exception\NotFoundException; + +class FooTest { + + public $item; + + public function __construct($item) { + $this->item = $item; + } +} + +class FooTest2 { + use ContainerAware; +} + +class ContainerTest extends IonTestCase { + + public function setUp(): void + { + $this->container = new Container(); + } + + public function dataGetWithException(): array + { + return [ + 'Bad index type: number' => [ + 'id' => 42, + 'exception' => ContainerException::class, + 'message' => 'Id must be a string' + ], + 'Bad index type: array' => [ + 'id' => [], + 'exception' => ContainerException::class, + 'message' => 'Id must be a string' + ], + 'Non-existent id' => [ + 'id' => 'foo', + 'exception' => NotFoundException::class, + 'message' => "Item 'foo' does not exist in container." + ] + ]; + } + + /** + * @dataProvider dataGetWithException + */ + public function testGetWithException($id, $exception, $message): void + { + try + { + $this->container->get($id); + } + catch(ContainerException $e) + { + $this->assertInstanceOf($exception, $e); + $this->assertEquals($message, $e->getMessage()); + } + } + + /** + * @dataProvider dataGetWithException + */ + public function testGetNewWithException($id, $exception, $message): void + { + $this->expectException($exception); + $this->expectExceptionMessage($message); + $this->container->getNew($id); + } + + public function dataSetInstanceWithException(): array + { + return [ + 'Non-existent id' => [ + 'id' => 'foo', + 'exception' => NotFoundException::class, + 'message' => "Factory 'foo' does not exist in container. Set that first.", + ], + 'Non-existent id 2' => [ + 'id' => 'foobarbaz', + 'exception' => NotFoundException::class, + 'message' => "Factory 'foobarbaz' does not exist in container. Set that first.", + ], + ]; + } + + /** + * @dataProvider dataSetInstanceWithException + */ + public function testSetInstanceWithException($id, $exception, $message): void + { + try + { + $this->container->setInstance($id, NULL); + } + catch(ContainerException $e) + { + $this->assertInstanceOf($exception, $e); + $this->assertEquals($message, $e->getMessage()); + } + } + + public function testGetNew(): void + { + $this->container->set('footest', static function($item) { + return new FooTest($item); + }); + + // Check that the item is the container, if called without arguments + $footest1 = $this->container->getNew('footest'); + $this->assertInstanceOf(ContainerInterface::class, $footest1->item); + + $footest2 = $this->container->getNew('footest', ['Test String']); + $this->assertEquals('Test String', $footest2->item); + } + + public function testSetContainerInInstance(): void + { + $this->container->set('footest2', function() { + return new FooTest2(); + }); + + $footest2 = $this->container->get('footest2'); + $this->assertEquals($this->container, $footest2->getContainer()); + } + + public function testGetNewReturnCallable(): void + { + $this->container->set('footest', static function($item) { + return static function() use ($item) { + return $item; + }; + }); + + // Check that the item is the container, if called without arguments + $footest1 = $this->container->getNew('footest'); + $this->assertInstanceOf(ContainerInterface::class, $footest1()); + + $footest2 = $this->container->getNew('footest', ['Test String']); + $this->assertEquals('Test String', $footest2()); + } + + public function testGetSet(): void + { + $container = $this->container->set('foo', static function() { + return static function() {}; + }); + + $this->assertInstanceOf(Container::class, $container); + $this->assertInstanceOf(ContainerInterface::class, $container); + + // The factory returns a callable + $this->assertTrue(is_callable($container->get('foo'))); + } + + public function testLoggerMethods(): void + { + // Does the container have the default logger? + $this->assertFalse($this->container->hasLogger()); + $this->assertFalse($this->container->hasLogger('default')); + + $logger1 = new Logger('default'); + $logger2 = new Logger('testing'); + $logger1->pushHandler(new NullHandler()); + $logger2->pushHandler(new TestHandler()); + + // Set the logger channels + $container = $this->container->setLogger($logger1); + $container2 = $this->container->setLogger($logger2, 'test'); + + $this->assertInstanceOf(ContainerInterface::class, $container); + $this->assertInstanceOf(Container::class, $container2); + + $this->assertEquals($logger1, $this->container->getLogger('default')); + $this->assertEquals($logger2, $this->container->getLogger('test')); + $this->assertNull($this->container->getLogger('foo')); + + $this->assertTrue($this->container->hasLogger()); + $this->assertTrue($this->container->hasLogger('default')); + $this->assertTrue($this->container->hasLogger('test')); + } +} \ No newline at end of file diff --git a/tests/Ion/EnumTest.php b/tests/Ion/EnumTest.php new file mode 100644 index 00000000..dfbd81a7 --- /dev/null +++ b/tests/Ion/EnumTest.php @@ -0,0 +1,83 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\Enum; + +class EnumTest extends IonTestCase { + + protected $expectedConstList = [ + 'FOO' => 'bar', + 'BAR' => 'foo', + 'FOOBAR' => 'baz' + ]; + + public function setUp(): void { + parent::setUp(); + $this->enum = new TestEnum(); + } + + public function testStaticGetConstList() + { + $actual = TestEnum::getConstList(); + $this->assertEquals($this->expectedConstList, $actual); + } + + public function testGetConstList() + { + $actual = $this->enum->getConstList(); + $this->assertEquals($this->expectedConstList, $actual); + } + + public function dataIsValid() + { + return [ + 'Valid' => [ + 'value' => 'baz', + 'expected' => TRUE, + 'static' => FALSE + ], + 'ValidStatic' => [ + 'value' => 'baz', + 'expected' => TRUE, + 'static' => TRUE + ], + 'Invalid' => [ + 'value' => 'foobar', + 'expected' => FALSE, + 'static' => FALSE + ], + 'InvalidStatic' => [ + 'value' => 'foobar', + 'expected' => FALSE, + 'static' => TRUE + ] + ]; + } + + /** + * @dataProvider dataIsValid + */ + public function testIsValid($value, $expected, $static) + { + $actual = ($static) + ? TestEnum::isValid($value) + : $this->enum->isValid($value); + + $this->assertEquals($expected, $actual); + } +} \ No newline at end of file diff --git a/tests/Ion/Exception/DoubleRenderExceptionTest.php b/tests/Ion/Exception/DoubleRenderExceptionTest.php new file mode 100644 index 00000000..f6bdfb42 --- /dev/null +++ b/tests/Ion/Exception/DoubleRenderExceptionTest.php @@ -0,0 +1,31 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Exception; + +use Aviat\Ion\Exception\DoubleRenderException; +use Aviat\Ion\Tests\IonTestCase; + +class DoubleRenderExceptionTest extends IonTestCase { + + public function testDefaultMessage() + { + $this->expectException(DoubleRenderException::class); + $this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.'); + + throw new DoubleRenderException(); + } +} \ No newline at end of file diff --git a/tests/Ion/FriendTest.php b/tests/Ion/FriendTest.php new file mode 100644 index 00000000..2fd12ca7 --- /dev/null +++ b/tests/Ion/FriendTest.php @@ -0,0 +1,77 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\Friend; +use Aviat\Ion\Tests\FriendTestClass; + +class FriendTest extends IonTestCase { + + protected $friend; + + public function setUp(): void { + parent::setUp(); + $obj = new FriendTestClass(); + $this->friend = new Friend($obj); + } + + public function testPrivateMethod():void + { + $actual = $this->friend->getPrivate(); + $this->assertEquals(23, $actual); + } + + public function testProtectedMethod():void + { + $actual = $this->friend->getProtected(); + $this->assertEquals(4, $actual); + } + + public function testGet():void + { + $this->assertEquals(356, $this->friend->protected); + $this->assertNull($this->friend->foo); // Return NULL for non-existent properties + $this->assertEquals(47, $this->friend->parentProtected); + $this->assertEquals(84, $this->friend->grandParentProtected); + $this->assertNull($this->friend->parentPrivate); // Can't get a parent's privates + } + + public function testSet(): void + { + $this->friend->private = 123; + $this->assertEquals(123, $this->friend->private); + + $this->friend->foo = 32; + $this->assertNull($this->friend->foo); + } + + public function testBadInvokation():void + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Friend must be an object'); + + $friend = new Friend('foo'); + } + + public function testBadMethod():void + { + $this->expectException('BadMethodCallException'); + $this->expectExceptionMessage("Method 'foo' does not exist"); + + $this->friend->foo(); + } +} \ No newline at end of file diff --git a/tests/Ion/IonTestCase.php b/tests/Ion/IonTestCase.php new file mode 100644 index 00000000..00cf234d --- /dev/null +++ b/tests/Ion/IonTestCase.php @@ -0,0 +1,128 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use function Aviat\Ion\_dir; + +use PHPUnit\Framework\TestCase; +use Laminas\Diactoros\ServerRequestFactory; + +/** + * Base class for TestCases + */ +class IonTestCase extends TestCase { + // Test directory constants + public const ROOT_DIR = ROOT_DIR; + public const SRC_DIR = SRC_DIR; + public const TEST_DATA_DIR = __DIR__ . '/test_data'; + public const TEST_VIEW_DIR = __DIR__ . '/test_views'; + + protected $container; + protected static $staticContainer; + protected static $session_handler; + + /*public static function setUpBeforeClass() + { + // Use mock session handler + $session_handler = new TestSessionHandler(); + session_set_save_handler($session_handler, TRUE); + self::$session_handler = $session_handler; + }*/ + + public function setUp(): void + { + parent::setUp(); + + $ROOT_DIR = realpath(_dir(__DIR__, '/../')); + $APP_DIR = _dir($ROOT_DIR, 'app'); + + $config_array = [ + 'asset_path' => '//localhost/assets/', + 'img_cache_path' => _dir(ROOT_DIR, 'public/images'), + 'database' => [ + 'collection' => [ + 'type' => 'sqlite', + 'host' => '', + 'user' => '', + 'pass' => '', + 'port' => '', + 'name' => 'default', + 'database' => '', + 'file' => ':memory:', + ], + 'cache' => [ + 'type' => 'sqlite', + 'host' => '', + 'user' => '', + 'pass' => '', + 'port' => '', + 'name' => 'default', + 'database' => '', + 'file' => ':memory:', + ] + ], + 'routes' => [ + 'route_config' => [ + 'asset_path' => '/assets' + ], + 'routes' => [ + + ] + ], + 'redis' => [ + 'host' => (array_key_exists('REDIS_HOST', $_ENV)) ? $_ENV['REDIS_HOST'] : 'localhost', + 'database' => 13 + ] + ]; + + // Set up DI container + $di = require('di.php'); + $container = $di($config_array); + $container->set('session-handler', static function() { + // Use mock session handler + $session_handler = new TestSessionHandler(); + session_set_save_handler($session_handler, TRUE); + return $session_handler; + }); + + $this->container = $container; + } + + /** + * Set arbitrary superglobal values for testing purposes + * + * @param array $supers + * @return void + */ + public function setSuperGlobals(array $supers = []): void + { + $default = [ + '_SERVER' => $_SERVER, + '_GET' => $_GET, + '_POST' => $_POST, + '_COOKIE' => $_COOKIE, + '_FILES' => $_FILES + ]; + + $request = call_user_func_array( + [ServerRequestFactory::class, 'fromGlobals'], + array_merge($default, $supers) + ); + $this->container->setInstance('request', $request); + } +} +// End of IonTestCase.php \ No newline at end of file diff --git a/tests/Ion/JsonTest.php b/tests/Ion/JsonTest.php new file mode 100644 index 00000000..ac72643f --- /dev/null +++ b/tests/Ion/JsonTest.php @@ -0,0 +1,89 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use function Aviat\Ion\_dir; + +use Aviat\Ion\{Json, JsonException}; + +class JsonTest extends IonTestCase { + + public function testEncode() + { + $data = (object) [ + 'foo' => [1, 2, 3, 4] + ]; + $expected = '{"foo":[1,2,3,4]}'; + $this->assertEquals($expected, Json::encode($data)); + } + + public function dataEncodeDecode() + { + return [ + 'set1' => [ + 'data' => [ + 'apple' => [ + 'sauce' => ['foo','bar','baz'] + ] + ], + 'expected_size' => 39, + 'expected_json' => '{"apple":{"sauce":["foo","bar","baz"]}}' + ] + ]; + } + + /** + * @dataProvider dataEncodeDecode + */ + public function testEncodeDecodeFile($data, $expected_size, $expected_json) + { + $target_file = _dir(self::TEST_DATA_DIR, 'json_write.json'); + + $actual_size = Json::encodeFile($target_file, $data); + $actual_json = file_get_contents($target_file); + + $this->assertTrue(Json::isJson($actual_json)); + $this->assertEquals($expected_size, $actual_size); + $this->assertEquals($expected_json, $actual_json); + + $this->assertEquals($data, Json::decodeFile($target_file)); + + unlink($target_file); + } + + public function testDecode() + { + $json = '{"foo":[1,2,3,4]}'; + $expected = [ + 'foo' => [1, 2, 3, 4] + ]; + $this->assertEquals($expected, Json::decode($json)); + $this->assertEquals((object)$expected, Json::decode($json, false)); + + $badJson = '{foo:{1|2}}'; + $this->expectException('Aviat\Ion\JsonException'); + $this->expectExceptionMessage('JSON_ERROR_SYNTAX - Syntax error'); + $this->expectExceptionCode(JSON_ERROR_SYNTAX); + + Json::decode($badJson); + } + + public function testDecodeNull() + { + $this->assertNull(Json::decode(NULL)); + } +} \ No newline at end of file diff --git a/tests/Ion/Model/BaseDBModelTest.php b/tests/Ion/Model/BaseDBModelTest.php new file mode 100644 index 00000000..593f4f87 --- /dev/null +++ b/tests/Ion/Model/BaseDBModelTest.php @@ -0,0 +1,29 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Model; + +use Aviat\Ion\Model\DB as BaseDBModel; +use Aviat\Ion\Tests\IonTestCase; + +class BaseDBModelTest extends IonTestCase { + + public function testBaseDBModelSanity() + { + $baseDBModel = new BaseDBModel($this->container->get('config')); + $this->assertTrue(is_object($baseDBModel)); + } +} \ No newline at end of file diff --git a/tests/Ion/StringWrapperTest.php b/tests/Ion/StringWrapperTest.php new file mode 100644 index 00000000..05a7070a --- /dev/null +++ b/tests/Ion/StringWrapperTest.php @@ -0,0 +1,39 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\StringWrapper; +use Aviat\Ion\Type\StringType; +use PHPUnit\Framework\TestCase; + +class StringWrapperTest extends TestCase { + + protected $wrapper; + + public function setUp(): void { + $this->wrapper = new class { + use StringWrapper; + }; + } + + public function testString() + { + $str = $this->wrapper->string('foo'); + $this->assertInstanceOf(StringType::class, $str); + } + +} \ No newline at end of file diff --git a/tests/Ion/TestSessionHandler.php b/tests/Ion/TestSessionHandler.php new file mode 100644 index 00000000..04caadcd --- /dev/null +++ b/tests/Ion/TestSessionHandler.php @@ -0,0 +1,71 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use SessionHandlerInterface; + +class TestSessionHandler implements SessionHandlerInterface { + + public $data = []; + public $save_path = './test_data/sessions'; + + public function close() + { + return TRUE; + } + + public function destroy($id) + { + $file = "$this->save_path/$id"; + if (file_exists($file)) + { + @unlink($file); + } + $this->data[$id] = []; + return TRUE; + } + + public function gc($maxLifetime) + { + return TRUE; + } + + public function open($save_path, $name) + { + /*if ( ! array_key_exists($save_path, $this->data)) + { + $this->save_path = $save_path; + $this->data = []; + }*/ + return TRUE; + } + + public function read($id) + { + return json_decode(@file_get_contents("$this->save_path/$id"), TRUE); + } + + public function write($id, $data) + { + $file = "$this->save_path/$id"; + file_put_contents($file, json_encode($data)); + + return TRUE; + } + +} +// End of TestSessionHandler.php \ No newline at end of file diff --git a/tests/Ion/Transformer/AbstractTransformerTest.php b/tests/Ion/Transformer/AbstractTransformerTest.php new file mode 100644 index 00000000..aeb8c221 --- /dev/null +++ b/tests/Ion/Transformer/AbstractTransformerTest.php @@ -0,0 +1,157 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Transformer; + +use Aviat\Ion\Tests\IonTestCase; +use Aviat\Ion\Tests\{TestTransformer, TestTransformerUntransform}; + +class AbstractTransformerTest extends IonTestCase { + + protected $transformer; + protected $untransformer; + + + public function setUp(): void { + $this->transformer = new TestTransformer(); + $this->untransformer = new TestTransformerUntransform(); + } + + public function dataTransformCollection() + { + return [ + 'object' => [ + 'original' => [ + (object)[ + ['name' => 'Comedy'], + ['name' => 'Romance'], + ['name' => 'School'], + ['name' => 'Harem'] + ], + (object)[ + ['name' => 'Action'], + ['name' => 'Comedy'], + ['name' => 'Magic'], + ['name' => 'Fantasy'], + ['name' => 'Mahou Shoujo'] + ], + (object)[ + ['name' => 'Comedy'], + ['name' => 'Sci-Fi'] + ] + ], + 'expected' => [ + ['Comedy', 'Romance', 'School', 'Harem'], + ['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + ['Comedy', 'Sci-Fi'] + ] + ], + 'array' => [ + 'original' => [ + [ + ['name' => 'Comedy'], + ['name' => 'Romance'], + ['name' => 'School'], + ['name' => 'Harem'] + ], + [ + ['name' => 'Action'], + ['name' => 'Comedy'], + ['name' => 'Magic'], + ['name' => 'Fantasy'], + ['name' => 'Mahou Shoujo'] + ], + [ + ['name' => 'Comedy'], + ['name' => 'Sci-Fi'] + ] + ], + 'expected' => [ + ['Comedy', 'Romance', 'School', 'Harem'], + ['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + ['Comedy', 'Sci-Fi'] + ] + ], + ]; + } + + public function dataUnTransformCollection() + { + return [ + 'object' => [ + 'original' => [ + (object)['Comedy', 'Romance', 'School', 'Harem'], + (object)['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + (object)['Comedy', 'Sci-Fi'] + ], + 'expected' => [ + ['Comedy', 'Romance', 'School', 'Harem'], + ['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + ['Comedy', 'Sci-Fi'] + ] + ], + 'array' => [ + 'original' => [ + ['Comedy', 'Romance', 'School', 'Harem'], + ['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + ['Comedy', 'Sci-Fi'] + ], + 'expected' => [ + ['Comedy', 'Romance', 'School', 'Harem'], + ['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'], + ['Comedy', 'Sci-Fi'] + ] + ] + ]; + } + + public function testTransform() + { + $data = $this->dataTransformCollection(); + $original = $data['object']['original'][0]; + $expected = $data['object']['expected'][0]; + + $actual = $this->transformer->transform($original); + $this->assertEquals($expected, $actual); + } + + /** + * @dataProvider dataTransformCollection + */ + public function testTransformCollection($original, $expected) + { + $actual = $this->transformer->transformCollection($original); + $this->assertEquals($expected, $actual); + } + + /** + * @dataProvider dataUnTransformCollection + */ + public function testUntransformCollection($original, $expected) + { + $actual = $this->untransformer->untransformCollection($original); + $this->assertEquals($expected, $actual); + } + + /** + * @dataProvider dataUnTransformCollection + */ + public function testUntransformCollectionWithException($original, $expected) + { + $this->expectException(\BadMethodCallException::class); + $this->transformer->untransformCollection($original); + } +} \ No newline at end of file diff --git a/tests/Ion/Type/ArrayTypeTest.php b/tests/Ion/Type/ArrayTypeTest.php new file mode 100644 index 00000000..55152ee7 --- /dev/null +++ b/tests/Ion/Type/ArrayTypeTest.php @@ -0,0 +1,215 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Type; + +use Aviat\Ion\ArrayWrapper; +use Aviat\Ion\Tests\IonTestCase; + +class ArrayTypeTest extends IonTestCase { + use ArrayWrapper; + + public function setUp(): void { + parent::setUp(); + } + + public function dataCall() + { + $method_map = [ + 'chunk' => 'array_chunk', + 'pluck' => 'array_column', + 'assoc_diff' => 'array_diff_assoc', + 'key_diff' => 'array_diff_key', + 'diff' => 'array_diff', + 'filter' => 'array_filter', + 'flip' => 'array_flip', + 'intersect' => 'array_intersect', + 'keys' => 'array_keys', + 'merge' => 'array_merge', + 'pad' => 'array_pad', + 'random' => 'array_rand', + 'reduce' => 'array_reduce', + ]; + + return [ + 'array_merge' => [ + 'method' => 'merge', + 'array' => [1, 3, 5, 7], + 'args' => [[2, 4, 6, 8]], + 'expected' => [1, 3, 5, 7, 2, 4, 6, 8] + ], + 'array_product' => [ + 'method' => 'product', + 'array' => [1, 2, 3], + 'args' => [], + 'expected' => 6 + ], + 'array_reverse' => [ + 'method' => 'reverse', + 'array' => [1, 2, 3, 4, 5], + 'args' => [], + 'expected' => [5, 4, 3, 2, 1] + ], + 'array_sum' => [ + 'method' => 'sum', + 'array' => [1, 2, 3, 4, 5, 6], + 'args' => [], + 'expected' => 21 + ], + 'array_unique' => [ + 'method' => 'unique', + 'array' => [1, 1, 3, 2, 2, 2, 3, 3, 5], + 'args' => [SORT_REGULAR], + 'expected' => [0 => 1, 2 => 3, 3 => 2, 8 => 5] + ], + 'array_values' => [ + 'method' => 'values', + 'array' => ['foo' => 'bar', 'baz' => 'foobar'], + 'args' => [], + 'expected' => ['bar', 'foobar'] + ] + ]; + } + + /** + * Test the array methods defined for the __Call method + * + * @dataProvider dataCall + */ + public function testCall($method, $array, $args, $expected) + { + $obj = $this->arr($array); + $actual = $obj->__call($method, $args); + $this->assertEquals($expected, $actual); + } + + public function testSet() + { + $obj = $this->arr([]); + $arraytype = $obj->set('foo', 'bar'); + + $this->assertInstanceOf('Aviat\Ion\Type\ArrayType', $arraytype); + $this->assertEquals('bar', $obj->get('foo')); + } + + public function testGet() + { + $array = [1, 2, 3, 4, 5]; + $obj = $this->arr($array); + $this->assertEquals($array, $obj->get()); + $this->assertEquals(1, $obj->get(0)); + $this->assertEquals(5, $obj->get(4)); + } + + public function testGetDeepKey() + { + $arr = [ + 'foo' => 'bar', + 'baz' => [ + 'bar' => 'foobar' + ] + ]; + $obj = $this->arr($arr); + $this->assertEquals('foobar', $obj->getDeepKey(['baz', 'bar'])); + $this->assertNull($obj->getDeepKey(['foo', 'bar', 'baz'])); + } + + public function testMap() + { + $obj = $this->arr([1, 2, 3]); + $actual = $obj->map(function($item) { + return $item * 2; + }); + + $this->assertEquals([2, 4, 6], $actual); + } + + public function testBadCall() + { + $obj = $this->arr([]); + + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage("Method 'foo' does not exist"); + + $obj->foo(); + } + + public function testShuffle() + { + $original = [1, 2, 3, 4]; + $test = [1, 2, 3, 4]; + $obj = $this->arr($test); + $actual = $obj->shuffle(); + + //$this->assertNotEquals($actual, $original); + $this->assertTrue(is_array($actual)); + } + + public function testHasKey() + { + $obj = $this->arr([ + 'a' => 'b', + 'z' => 'y' + ]); + $this->assertTrue($obj->hasKey('a')); + $this->assertFalse($obj->hasKey('b')); + } + + public function testHasKeyArray() + { + $obj = $this->arr([ + 'foo' => [ + 'bar' => [ + 'baz' => [ + 'foobar' => NULL, + 'one' => 1, + ], + ], + ], + ]); + + $this->assertTrue($obj->hasKey(['foo'])); + $this->assertTrue($obj->hasKey(['foo', 'bar'])); + $this->assertTrue($obj->hasKey(['foo', 'bar', 'baz'])); + $this->assertTrue($obj->hasKey(['foo', 'bar', 'baz', 'one'])); + $this->assertTrue($obj->hasKey(['foo', 'bar', 'baz', 'foobar'])); + + $this->assertFalse($obj->hasKey(['foo', 'baz'])); + $this->assertFalse($obj->hasKey(['bar', 'baz'])); + } + + public function testHas() + { + $obj = $this->arr([1, 2, 6, 8, 11]); + $this->assertTrue($obj->has(8)); + $this->assertFalse($obj->has(8745)); + } + + public function testSearch() + { + $obj = $this->arr([1, 2, 5, 7, 47]); + $actual = $obj->search(47); + $this->assertEquals(4, $actual); + } + + public function testFill() + { + $obj = $this->arr([]); + $expected = ['?', '?', '?']; + $actual = $obj->fill(0, 3, '?'); + $this->assertEquals($actual, $expected); + } +} \ No newline at end of file diff --git a/tests/Ion/Type/StringTypeTest.php b/tests/Ion/Type/StringTypeTest.php new file mode 100644 index 00000000..7a25eb78 --- /dev/null +++ b/tests/Ion/Type/StringTypeTest.php @@ -0,0 +1,66 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\Type; + +use Aviat\Ion\StringWrapper; +use Aviat\Ion\Tests\IonTestCase; + +class StringTypeTest extends IonTestCase { + use StringWrapper; + + + public function dataFuzzyCaseMatch() + { + return [ + 'space separated' => [ + 'str1' => 'foo bar baz', + 'str2' => 'foo-bar-baz', + 'expected' => true + ], + 'camelCase' => [ + 'str1' => 'fooBarBaz', + 'str2' => 'foo-bar-baz', + 'expected' => true + ], + 'PascalCase' => [ + 'str1' => 'FooBarBaz', + 'str2' => 'foo-bar-baz', + 'expected' => true + ], + 'snake_case' => [ + 'str1' => 'foo_bar_baz', + 'str2' => 'foo-bar-baz', + 'expected' => true + ], + 'mEsSYcAse' => [ + 'str1' => 'fOObArBAZ', + 'str2' => 'foo-bar-baz', + 'expected' => false + ], + ]; + } + + /** + * @dataProvider dataFuzzyCaseMatch + */ + public function testFuzzyCaseMatch($str1, $str2, $expected) + { + $actual = $this->string($str1)->fuzzyCaseMatch($str2); + $this->assertEquals($expected, $actual); + } + +} \ No newline at end of file diff --git a/tests/Ion/View/HtmlViewTest.php b/tests/Ion/View/HtmlViewTest.php new file mode 100644 index 00000000..4c854d02 --- /dev/null +++ b/tests/Ion/View/HtmlViewTest.php @@ -0,0 +1,42 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\View; + +use function Aviat\Ion\_dir; + +use Aviat\Ion\Tests\TestHtmlView; + +class HtmlViewTest extends HttpViewTest { + + protected $template_path; + + public function setUp(): void { + parent::setUp(); + $this->view = new TestHtmlView($this->container); + } + + public function testRenderTemplate() + { + $path = _dir(self::TEST_VIEW_DIR, 'test_view.php'); + $expected = 'foo'; + $actual = $this->view->renderTemplate($path, [ + 'var' => 'foo' + ]); + $this->assertEquals($expected, $actual); + } + +} \ No newline at end of file diff --git a/tests/Ion/View/HttpViewTest.php b/tests/Ion/View/HttpViewTest.php new file mode 100644 index 00000000..369e4a25 --- /dev/null +++ b/tests/Ion/View/HttpViewTest.php @@ -0,0 +1,95 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\View; + +use Aviat\Ion\Friend; +use Aviat\Ion\Exception\DoubleRenderException; +use Aviat\Ion\Tests\IonTestCase; +use Aviat\Ion\Tests\TestHttpView; + +class HttpViewTest extends IonTestCase { + + protected $view; + protected $friend; + + public function setUp(): void { + parent::setUp(); + $this->view = new TestHttpView($this->container); + $this->friend = new Friend($this->view); + } + + public function testGetOutput() + { + $this->friend->setOutput('foo'); + $this->assertEquals('foo', $this->friend->getOutput()); + $this->assertFalse($this->friend->hasRendered); + + $this->assertEquals($this->friend->getOutput(), $this->friend->__toString()); + $this->assertTrue($this->friend->hasRendered); + } + + public function testSetOutput() + { + $same = $this->view->setOutput('

'); + $this->assertEquals($same, $this->view); + $this->assertEquals('

', $this->view->getOutput()); + } + + public function testAppendOutput() + { + $this->view->setOutput('

'); + $this->view->appendOutput('

'); + $this->assertEquals('

', $this->view->getOutput()); + } + + public function testSetStatusCode() + { + $view = $this->view->setStatusCode(404); + $this->assertEquals(404, $view->response->getStatusCode()); + } + + public function testAddHeader() + { + $view = $this->view->addHeader('foo', 'bar'); + $this->assertTrue($view->response->hasHeader('foo')); + $this->assertEquals(['bar'], $view->response->getHeader('foo')); + } + + public function testSendDoubleRenderException() + { + $this->expectException(DoubleRenderException::class); + $this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.'); + + // First render + $this->view->__toString(); + + // Second render + $this->view->send(); + } + + public function test__toStringDoubleRenderException() + { + $this->expectException(DoubleRenderException::class); + $this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.'); + + // First render + $this->view->send(); + + // Second render + $this->view->__toString(); + } +} \ No newline at end of file diff --git a/tests/Ion/View/JsonViewTest.php b/tests/Ion/View/JsonViewTest.php new file mode 100644 index 00000000..b0691104 --- /dev/null +++ b/tests/Ion/View/JsonViewTest.php @@ -0,0 +1,57 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests\View; + +use Aviat\Ion\Friend; +use Aviat\Ion\Tests\TestJsonView; + +class JsonViewTest extends HttpViewTest { + + public function setUp(): void { + parent::setUp(); + + $this->view = new TestJsonView($this->container); + $this->friend = new Friend($this->view); + } + + public function testSetOutputJSON() + { + // Extend view class to remove destructor which does output + $view = new TestJsonView($this->container); + + // Json encode non-string + $content = ['foo' => 'bar']; + $expected = json_encode($content); + $view->setOutput($content); + $this->assertEquals($expected, $this->view->getOutput()); + } + + public function testSetOutput() + { + // Directly set string + $view = new TestJsonView($this->container); + $content = '{}'; + $expected = '{}'; + $view->setOutput($content); + $this->assertEquals($expected, $view->getOutput()); + } + + public function testOutput() + { + $this->assertEquals('application/json', $this->friend->contentType); + } +} \ No newline at end of file diff --git a/tests/Ion/di.php b/tests/Ion/di.php new file mode 100644 index 00000000..13caf6f0 --- /dev/null +++ b/tests/Ion/di.php @@ -0,0 +1,48 @@ +set('config', static function() { + return new Config([]); + }); + + $container->setInstance('config', new Config($config_array)); + + $container->set('request', static function() { + return ServerRequestFactory::fromGlobals( + $_SERVER, + $_GET, + $_POST, + $_COOKIE, + $_FILES + ); + }); + + $container->set('response', static function() { + return new Response(); + }); + + // Create session Object + $container->set('session', static function() { + return (new SessionFactory())->newInstance($_COOKIE); + }); + + // Create Html helper Object + $container->set('html-helper', static function() { + return (new HelperLocatorFactory)->newInstance(); + }); + + return $container; +}; \ No newline at end of file diff --git a/tests/Ion/functionsTest.php b/tests/Ion/functionsTest.php new file mode 100644 index 00000000..cae8fdab --- /dev/null +++ b/tests/Ion/functionsTest.php @@ -0,0 +1,33 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use function Aviat\Ion\_dir; + +use PHPUnit\Framework\TestCase; + +class functionsTest extends TestCase { + + + public function test_dir() + { + $args = ['foo', 'bar', 'baz']; + $expected = implode(\DIRECTORY_SEPARATOR, $args); + + $this->assertEquals(_dir(...$args), $expected); + } +} \ No newline at end of file diff --git a/tests/Ion/mocks.php b/tests/Ion/mocks.php new file mode 100644 index 00000000..900325d8 --- /dev/null +++ b/tests/Ion/mocks.php @@ -0,0 +1,191 @@ + + * @copyright 2015 - 2020 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.2 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\Ion\Tests; + +use Aviat\Ion\Enum; +use Aviat\Ion\Exception\DoubleRenderException; +use Aviat\Ion\Friend; +use Aviat\Ion\Transformer\AbstractTransformer; +use Aviat\Ion\View; +use Aviat\Ion\View\{HtmlView, HttpView, JsonView}; + +// ----------------------------------------------------------------------------- +// Mock the default error handler +// ----------------------------------------------------------------------------- + +class MockErrorHandler { + public function addDataTable($name, array $values=[]) {} +} + +// ----------------------------------------------------------------------------- +// Ion Mocks +// ----------------------------------------------------------------------------- + +class TestEnum extends Enum { + const FOO = 'bar'; + const BAR = 'foo'; + const FOOBAR = 'baz'; +} + +class FriendGrandParentTestClass { + protected $grandParentProtected = 84; +} + +class FriendParentTestClass extends FriendGrandParentTestClass { + protected $parentProtected = 47; + private $parentPrivate = 654; +} + +class FriendTestClass extends FriendParentTestClass { + protected $protected = 356; + private $private = 486; + + protected function getProtected() + { + return 4; + } + + private function getPrivate() + { + return 23; + } +} + +class TestTransformer extends AbstractTransformer { + + public function transform($item) + { + $out = []; + $genre_list = (array) $item; + + foreach($genre_list as $genre) + { + $out[] = $genre['name']; + } + + return $out; + } +} + +class TestTransformerUntransform extends TestTransformer { + public function untransform($item) + { + return (array)$item; + } +} + +trait MockViewOutputTrait { + /*protected function output() { + $reflect = new ReflectionClass($this); + $properties = $reflect->getProperties(); + $props = []; + + foreach($properties as $reflectProp) + { + $reflectProp->setAccessible(TRUE); + $props[$reflectProp->getName()] = $reflectProp->getValue($this); + } + + $view = new TestView($this->container); + $friend = new Friend($view); + foreach($props as $name => $val) + { + $friend->__set($name, $val); + } + + //$friend->output(); + }*/ + + public function send(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->hasRendered = TRUE; + } +} + +class TestView extends View { + public function send(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->hasRendered = TRUE; + } + public function output() {} +} + +class TestHtmlView extends HtmlView { + protected function output(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->hasRendered = TRUE; + } +} + +class TestHttpView extends HttpView { + protected function output(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->hasRendered = TRUE; + } +} + +class TestJsonView extends JsonView { + public function __destruct() {} + + protected function output(): void + { + if ($this->hasRendered) + { + throw new DoubleRenderException(); + } + + $this->hasRendered = TRUE; + } +} + +// ----------------------------------------------------------------------------- +// AnimeClient Mocks +// ----------------------------------------------------------------------------- + +trait MockInjectionTrait { + public function __get($key) + { + return $this->$key; + } + + public function __set($key, $value) + { + $this->$key = $value; + return $this; + } +} +// End of mocks.php \ No newline at end of file diff --git a/tests/Ion/test_data/invalid_json.json b/tests/Ion/test_data/invalid_json.json new file mode 100644 index 00000000..8a3cefa6 --- /dev/null +++ b/tests/Ion/test_data/invalid_json.json @@ -0,0 +1 @@ +[}] \ No newline at end of file diff --git a/tests/Ion/test_data/valid_json.json b/tests/Ion/test_data/valid_json.json new file mode 100644 index 00000000..56b0789b --- /dev/null +++ b/tests/Ion/test_data/valid_json.json @@ -0,0 +1,5 @@ +[{ + "foo": { + "bar": [1,2,3] + } +}] \ No newline at end of file diff --git a/tests/Ion/test_views/test_view.php b/tests/Ion/test_views/test_view.php new file mode 100644 index 00000000..3b7e2f71 --- /dev/null +++ b/tests/Ion/test_views/test_view.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 27878b14..f7f942a0 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,4 @@ -