diff --git a/.github/workflows/symfony.yml b/.github/workflows/symfony.yml index b24ffb4a..4aa0f773 100644 --- a/.github/workflows/symfony.yml +++ b/.github/workflows/symfony.yml @@ -37,11 +37,7 @@ jobs: run: | mkdir -p data touch data/database.sqlite - - name: Execute tests (Unit and Feature tests) via PHPUnit + - name: Execute tests env: DATABASE_URL: sqlite:///%kernel.project_dir%/data/database.sqlite - run: vendor/bin/phpunit - - name: Execute PHPSTAN - env: - DATABASE_URL: sqlite:///%kernel.project_dir%/data/database.sqlite - run: composer test-phpstan + run: composer test diff --git a/.gitignore b/.gitignore index 5cd83b5d..c5c469fc 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,8 @@ docker-compose.override.yml npm-debug.log yarn-error.log ###< symfony/webpack-encore-bundle ### + +###> friendsofphp/php-cs-fixer ### +/.php-cs-fixer.php +/.php-cs-fixer.cache +###< friendsofphp/php-cs-fixer ### diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 00000000..03c77128 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,31 @@ +in(__DIR__.'/src') + ->in(__DIR__.'/tests') +; + +$config = new PhpCsFixer\Config('Biblioteca'); +$config->setLineEnding(PHP_EOL); +$config->setFinder($finder); +$config->setRiskyAllowed(true); +$config->setRules([ + '@Symfony' => true, + 'increment_style' => false, + 'logical_operators' => true, + 'no_superfluous_phpdoc_tags' => false, + 'phpdoc_align' => [ + 'align' => 'left', + ], + 'phpdoc_separation' => false, + 'phpdoc_summary' => false, + 'visibility_required' => [ + 'elements' => ['property', 'method', 'const'], + ], + 'yoda_style' => false, +]); + +return $config; diff --git a/composer.json b/composer.json index 8d799196..da04439e 100644 --- a/composer.json +++ b/composer.json @@ -99,6 +99,21 @@ "test-phpstan": [ "Composer\\Config::disableProcessTimeout", "env XDEBUG_MODE=off ./vendor/bin/phpstan analyse --memory-limit=-1" + ], + "test-phpcs": [ + "Composer\\Config::disableProcessTimeout", + "env XDEBUG_MODE=off ./vendor/bin/php-cs-fixer fix ./src --dry-run --verbose --config=.php-cs-fixer.dist.php" + ], + "phpcs": [ + "Composer\\Config::disableProcessTimeout", + "env XDEBUG_MODE=off ./vendor/bin/php-cs-fixer fix ./src -vv --verbose --config=.php-cs-fixer.dist.php" + ], + "test-phpunit": [ + "Composer\\Config::disableProcessTimeout", + "env XDEBUG_MODE=off ./vendor/bin/phpunit --colors=always" + ], + "test": [ + "composer test-phpcs && composer test-phpunit && composer test-phpstan" ] }, "conflict": { @@ -111,6 +126,11 @@ } }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.25", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-doctrine": "^1.3", + "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-symfony": "^1.2", "phpunit/phpunit": "^10.0", "symfony/browser-kit": "^6.2", "symfony/css-selector": "^6.2", @@ -118,10 +138,6 @@ "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^6.2", "symfony/stopwatch": "^6.2", - "symfony/web-profiler-bundle": "^6.2", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-strict-rules": "^1.0", - "phpstan/phpstan-doctrine": "^1.3", - "phpstan/phpstan-symfony": "^1.2" + "symfony/web-profiler-bundle": "^6.2" } } diff --git a/composer.lock b/composer.lock index fa4bfd46..f8c39478 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d30a4e0f616c33f6e67c11fe43432f1c", + "content-hash": "e6827fcf4e6d64babc528f8b27154082", "packages": [ { "name": "behat/transliterator", @@ -1864,16 +1864,16 @@ }, { "name": "kiwilan/php-archive", - "version": "2.1.0", + "version": "2.1.01", "source": { "type": "git", "url": "https://github.com/kiwilan/php-archive.git", - "reference": "04b2fba86df1aef38319e7ee04174bd6a6999ed4" + "reference": "e43ca65d1f57e895a6ea2bdfc24951daee36e084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kiwilan/php-archive/zipball/04b2fba86df1aef38319e7ee04174bd6a6999ed4", - "reference": "04b2fba86df1aef38319e7ee04174bd6a6999ed4", + "url": "https://api.github.com/repos/kiwilan/php-archive/zipball/e43ca65d1f57e895a6ea2bdfc24951daee36e084", + "reference": "e43ca65d1f57e895a6ea2bdfc24951daee36e084", "shasum": "" }, "require": { @@ -1929,7 +1929,7 @@ ], "support": { "issues": "https://github.com/kiwilan/php-archive/issues", - "source": "https://github.com/kiwilan/php-archive/tree/v2.1.0" + "source": "https://github.com/kiwilan/php-archive/tree/v2.1.01" }, "funding": [ { @@ -1937,7 +1937,7 @@ "type": "github" } ], - "time": "2023-08-28T16:24:51+00:00" + "time": "2023-08-30T11:28:56+00:00" }, { "name": "kiwilan/php-audio", @@ -2023,20 +2023,20 @@ }, { "name": "kiwilan/php-ebook", - "version": "2.1.01", + "version": "2.1.02", "source": { "type": "git", "url": "https://github.com/kiwilan/php-ebook.git", - "reference": "9068cb8d7e1108852a5d587cc5d5913079de7e8b" + "reference": "5917e47a9a6a88884cfed433a7d7264a58c0e2ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kiwilan/php-ebook/zipball/9068cb8d7e1108852a5d587cc5d5913079de7e8b", - "reference": "9068cb8d7e1108852a5d587cc5d5913079de7e8b", + "url": "https://api.github.com/repos/kiwilan/php-ebook/zipball/5917e47a9a6a88884cfed433a7d7264a58c0e2ac", + "reference": "5917e47a9a6a88884cfed433a7d7264a58c0e2ac", "shasum": "" }, "require": { - "kiwilan/php-archive": "^2.1.0", + "kiwilan/php-archive": "^2.1.01", "kiwilan/php-audio": "^3.0.0", "kiwilan/php-xml-reader": "^1.0.1", "php": "^8.1" @@ -2090,7 +2090,7 @@ ], "support": { "issues": "https://github.com/kiwilan/php-ebook/issues", - "source": "https://github.com/kiwilan/php-ebook/tree/v2.1.01" + "source": "https://github.com/kiwilan/php-ebook/tree/v2.1.02" }, "funding": [ { @@ -2098,7 +2098,7 @@ "type": "github" } ], - "time": "2023-08-29T07:02:06+00:00" + "time": "2023-08-30T11:40:15+00:00" }, { "name": "kiwilan/php-xml-reader", @@ -9295,6 +9295,319 @@ } ], "packages-dev": [ + { + "name": "composer/pcre", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-11-17T09:50:14+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.25.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d", + "reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d", + "shasum": "" + }, + "require": { + "composer/semver": "^3.3", + "composer/xdebug-handler": "^3.0.3", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0 || ^5.0", + "symfony/console": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0", + "symfony/finder": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/polyfill-mbstring": "^1.27", + "symfony/polyfill-php80": "^1.27", + "symfony/polyfill-php81": "^1.27", + "symfony/process": "^5.4 || ^6.0", + "symfony/stopwatch": "^5.4 || ^6.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.0", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.0", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.5.3", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.16", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.6", + "phpunitgoodpractices/traits": "^1.9.2", + "symfony/phpunit-bridge": "^6.2.3", + "symfony/yaml": "^5.4 || ^6.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.25.0" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2023-08-31T21:27:18+00:00" + }, { "name": "masterminds/html5", "version": "2.8.1", @@ -9652,16 +9965,16 @@ }, { "name": "phpstan/phpstan-doctrine", - "version": "1.3.42", + "version": "1.3.43", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-doctrine.git", - "reference": "e4678fa1055bfd7fad052506b422aeae35fc6f63" + "reference": "c5015035755ad2d5013bd6bf98ff423ca6150822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/e4678fa1055bfd7fad052506b422aeae35fc6f63", - "reference": "e4678fa1055bfd7fad052506b422aeae35fc6f63", + "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/c5015035755ad2d5013bd6bf98ff423ca6150822", + "reference": "c5015035755ad2d5013bd6bf98ff423ca6150822", "shasum": "" }, "require": { @@ -9716,9 +10029,9 @@ "description": "Doctrine extensions for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-doctrine/issues", - "source": "https://github.com/phpstan/phpstan-doctrine/tree/1.3.42" + "source": "https://github.com/phpstan/phpstan-doctrine/tree/1.3.43" }, - "time": "2023-08-09T08:21:24+00:00" + "time": "2023-09-01T15:01:13+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -9842,16 +10155,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.3", + "version": "10.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d" + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cd59bb34756a16ca8253ce9b2909039c227fff71", + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71", "shasum": "" }, "require": { @@ -9908,7 +10221,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.4" }, "funding": [ { @@ -9916,20 +10229,20 @@ "type": "github" } ], - "time": "2023-07-26T13:45:28+00:00" + "time": "2023-08-31T14:04:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.0.2", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "5647d65443818959172645e7ed999217360654b6" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", - "reference": "5647d65443818959172645e7ed999217360654b6", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { @@ -9969,7 +10282,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -9977,7 +10290,7 @@ "type": "github" } ], - "time": "2023-05-07T09:13:23+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", @@ -10044,16 +10357,16 @@ }, { "name": "phpunit/php-text-template", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { @@ -10091,7 +10404,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -10099,7 +10413,7 @@ "type": "github" } ], - "time": "2023-02-03T06:56:46+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", @@ -10507,16 +10821,16 @@ }, { "name": "sebastian/complexity", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a", + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a", "shasum": "" }, "require": { @@ -10552,7 +10866,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1" }, "funding": [ { @@ -10560,7 +10875,7 @@ "type": "github" } ], - "time": "2023-02-03T06:59:47+00:00" + "time": "2023-08-31T09:55:53+00:00" }, { "name": "sebastian/diff", @@ -10834,16 +11149,16 @@ }, { "name": "sebastian/lines-of-code", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", "shasum": "" }, "require": { @@ -10879,7 +11194,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" }, "funding": [ { @@ -10887,7 +11203,7 @@ "type": "github" } ], - "time": "2023-02-03T07:08:02+00:00" + "time": "2023-08-31T09:25:50+00:00" }, { "name": "sebastian/object-enumerator", diff --git a/src/Command/BooksRelocateCommand.php b/src/Command/BooksRelocateCommand.php index 05d289f6..55a650d3 100644 --- a/src/Command/BooksRelocateCommand.php +++ b/src/Command/BooksRelocateCommand.php @@ -4,17 +4,13 @@ use App\Repository\BookRepository; use App\Service\BookFileSystemManager; -use App\Service\BookManager; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Filesystem\Filesystem; #[AsCommand( name: 'books:relocate', @@ -26,7 +22,7 @@ class BooksRelocateCommand extends Command private EntityManagerInterface $entityManager; private BookFileSystemManager $fileSystemManager; - public function __construct(BookFileSystemManager$fileSystemManager, BookRepository $bookRepository, EntityManagerInterface $entityManager) + public function __construct(BookFileSystemManager $fileSystemManager, BookRepository $bookRepository, EntityManagerInterface $entityManager) { parent::__construct(); $this->bookRepository = $bookRepository; @@ -36,7 +32,6 @@ public function __construct(BookFileSystemManager$fileSystemManager, BookReposit protected function configure(): void { - } /** @@ -53,11 +48,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int foreach ($allBooks as $book) { $progressBar->advance(); try { - $book = $this->fileSystemManager->renameFiles($book); $this->entityManager->persist($book); - - }catch (\Exception $e) { + } catch (\Exception $e) { $io->error($e->getMessage()); continue; } diff --git a/src/Command/BooksScanCommand.php b/src/Command/BooksScanCommand.php index 2682a57a..9c662adf 100644 --- a/src/Command/BooksScanCommand.php +++ b/src/Command/BooksScanCommand.php @@ -2,11 +2,9 @@ namespace App\Command; -use App\Entity\Book; use App\Repository\BookRepository; use App\Service\BookFileSystemManager; use App\Service\BookManager; -use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -37,19 +35,17 @@ public function __construct(BookManager $bookManager, BookFileSystemManager $fil protected function configure(): void { - } protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $io->writeln('Scanning books directory'); $allBooks = $this->bookRepository->findAll(); $unprocessedBooks = []; - foreach ($allBooks as $book){ + foreach ($allBooks as $book) { $unprocessedBooks[$book->getChecksum()] = $book; } $files = $this->fileSystemManager->getAllBooksFiles(); @@ -58,14 +54,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $progressBar->start(); foreach ($files as $file) { $progressBar->advance(); - try{ - $flush=false; + try { + $flush = false; $progressBar->setMessage($file->getFilename()); $checksum = $this->fileSystemManager->getFileChecksum($file); $book = $this->bookRepository->findOneBy(['checksum' => $checksum]); - if($book=== null){ + if (null === $book) { $book = $this->bookManager->createBook($file); - $flush=true; + $flush = true; } else { $previousPath = $book->getBookPath(); $previousName = $book->getBookFilename(); @@ -77,12 +73,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int unset($unprocessedBooks[$checksum]); - if($flush===true) { + if (true === $flush) { $this->entityManager->persist($book); $this->entityManager->flush(); } - - }catch (\Exception $e){ + } catch (\Exception $e) { $io->error($e->getMessage()); continue; } @@ -94,7 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $progressBar = new ProgressBar($output, count($unprocessedBooks)); $progressBar->start(); - foreach ($unprocessedBooks as $book){ + foreach ($unprocessedBooks as $book) { $progressBar->advance(); $this->entityManager->remove($book); } diff --git a/src/Command/CreateUserCommand.php b/src/Command/CreateUserCommand.php index fe671f85..13fea30f 100644 --- a/src/Command/CreateUserCommand.php +++ b/src/Command/CreateUserCommand.php @@ -35,7 +35,6 @@ protected function configure(): void ->addArgument('password', InputArgument::REQUIRED, 'password'); } - /** * @throws \Exception */ @@ -44,12 +43,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io = new SymfonyStyle($input, $output); $username = $input->getArgument('username'); - if(!is_string($username)){ + if (!is_string($username)) { throw new \Exception('username must be a string'); } $plaintextPassword = $input->getArgument('password'); - if(!is_string($plaintextPassword)){ + if (!is_string($plaintextPassword)) { throw new \Exception('username must be a string'); } @@ -68,7 +67,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->success('User created'); - return Command::SUCCESS; } } diff --git a/src/Controller/Admin/BookCrudController.php b/src/Controller/Admin/BookCrudController.php index 24b31f55..de9758f5 100644 --- a/src/Controller/Admin/BookCrudController.php +++ b/src/Controller/Admin/BookCrudController.php @@ -6,10 +6,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField; -use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField; -use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; -use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField; use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; @@ -34,19 +31,17 @@ public function configureCrud(Crud $crud): Crud public function configureFields(string $pageName): iterable { return [ - TextField::new('title',)->setTemplatePath('admin/field/linkedit.html.twig'), - TextEditorField::new('summary',)->hideOnIndex(), - TextField::new('serie',), - NumberField::new('serieIndex',), - TextField::new('mainAuthor',), - TextField::new('language',), - TextField::new('publisher',)->hideOnIndex(), - DateField::new('publishDate',)->hideOnIndex(), - ArrayField::new('authors',)->setRequired(false)->hideOnIndex(), - ArrayField::new('tags',)->setRequired(false), - DateField::new('created',)->onlyOnIndex(), - + TextField::new('title')->setTemplatePath('admin/field/linkedit.html.twig'), + TextEditorField::new('summary')->hideOnIndex(), + TextField::new('serie'), + NumberField::new('serieIndex'), + TextField::new('mainAuthor'), + TextField::new('language'), + TextField::new('publisher')->hideOnIndex(), + DateField::new('publishDate')->hideOnIndex(), + ArrayField::new('authors')->setRequired(false)->hideOnIndex(), + ArrayField::new('tags')->setRequired(false), + DateField::new('created')->onlyOnIndex(), ]; } - } diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php index e8d8d4a2..5d492a6b 100644 --- a/src/Controller/Admin/DashboardController.php +++ b/src/Controller/Admin/DashboardController.php @@ -8,13 +8,11 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController; use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class DashboardController extends AbstractDashboardController { - public function configureDashboard(): Dashboard { return Dashboard::new() @@ -31,9 +29,9 @@ public function configureDashboard(): Dashboard #[Route('/admin', name: 'admin')] public function index(): Response { - /** @var AdminUrlGenerator $adminUrlGenerator */ $adminUrlGenerator = $this->container->get(AdminUrlGenerator::class); + return $this->redirect($adminUrlGenerator->setController(BookCrudController::class)->generateUrl()); // Option 2. You can make your dashboard redirect to different pages depending on the user @@ -48,7 +46,6 @@ public function index(): Response // return $this->render('some/path/my-dashboard.html.twig'); } - public function configureMenuItems(): iterable { return [ @@ -61,6 +58,4 @@ public function configureMenuItems(): iterable MenuItem::linkToRoute('Back', 'fa fa-user', 'app_homepage'), ]; } - - } diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index 06917a1d..a6ed974d 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -5,12 +5,7 @@ use App\Entity\User; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; -use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField; -use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; -use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; -use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField; -use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use Symfony\Component\Form\Extension\Core\Type\PasswordType; @@ -29,18 +24,17 @@ public function configureCrud(Crud $crud): Crud ->setEntityLabelInPlural('Utilisatrices/eurs') ->setPageTitle('index', 'Toutes les %entity_label_plural%') ->setPageTitle('new', 'Nouveau') - ; + ; } public function configureFields(string $pageName): iterable { return [ - TextField::new('username','Nom pour se connecter')->setTemplatePath('admin/field/linkedit.html.twig'), - TextField::new('displayName','Nom à afficher'), + TextField::new('username', 'Nom pour se connecter')->setTemplatePath('admin/field/linkedit.html.twig'), + TextField::new('displayName', 'Nom à afficher'), EmailField::new('email') ->setRequired(true), TextField::new('password')->setFormType(PasswordType::class)->onlyOnForms(), ]; } - } diff --git a/src/Controller/AuthorController.php b/src/Controller/AuthorController.php index 81f7b3ce..75a6c3e2 100644 --- a/src/Controller/AuthorController.php +++ b/src/Controller/AuthorController.php @@ -2,7 +2,6 @@ namespace App\Controller; -use App\Entity\Book; use App\Repository\BookRepository; use Knp\Component\Pager\PaginatorInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -10,36 +9,34 @@ use Symfony\Component\Routing\Annotation\Route; #[Route('/authors')] - class AuthorController extends AbstractController { #[Route('/{page}', name: 'app_authors', requirements: ['page' => '\d+'])] - public function index(BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function index(BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $authors = $bookRepository->getAllAuthors()->getResult(); - $pagination = $paginator->paginate($authors,$page, 18); + $pagination = $paginator->paginate($authors, $page, 18); return $this->render('group/index.html.twig', [ 'pagination' => $pagination, - 'page'=> $page, - 'type'=> 'mainAuthor', + 'page' => $page, + 'type' => 'mainAuthor', ]); } #[Route('/{slug}/{page}', name: 'app_mainAuthor_detail', requirements: ['page' => '\d+'])] - public function detail(string $slug, BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function detail(string $slug, BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $authors = $bookRepository->getAllAuthors()->getResult(); - if(!is_array($authors)){ + if (!is_array($authors)) { throw $this->createNotFoundException('No authors found'); } - $author = array_filter($authors, static fn($serie) => $serie['slug'] === $slug); - + $author = array_filter($authors, static fn ($serie) => $serie['slug'] === $slug); - $author= current($author); + $author = current($author); - if($author===false){ + if (false === $author) { return $this->redirectToRoute('app_authors'); } @@ -51,7 +48,7 @@ public function detail(string $slug, BookRepository $bookRepository, PaginatorIn return $this->render('author/detail.html.twig', [ 'pagination' => $pagination, - 'author' =>$author + 'author' => $author, ]); } } diff --git a/src/Controller/BookController.php b/src/Controller/BookController.php index d8ea5cdb..6031e96e 100644 --- a/src/Controller/BookController.php +++ b/src/Controller/BookController.php @@ -3,7 +3,6 @@ namespace App\Controller; use App\Entity\Book; -use App\Repository\BookRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; @@ -14,10 +13,10 @@ class BookController extends AbstractController #[Route('/{authorSlug}/{book}/{slug}', name: 'app_book')] public function index(string $authorSlug, Book $book, string $slug): Response { - if($authorSlug!==$book->getAuthorSlug()||$slug!==$book->getSlug()){ + if ($authorSlug !== $book->getAuthorSlug() || $slug !== $book->getSlug()) { return $this->redirectToRoute('app_book', [ 'authorSlug' => $book->getAuthorSlug(), - 'book'=> $book->getId(), + 'book' => $book->getId(), 'slug' => $book->getSlug(), ], 301); } diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php index 54617ae9..3356d24a 100644 --- a/src/Controller/DefaultController.php +++ b/src/Controller/DefaultController.php @@ -11,54 +11,58 @@ class DefaultController extends AbstractController { #[Route('/{page}', name: 'app_homepage', requirements: ['page' => '\d+'])] - public function index(BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function index(BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $pagination = $paginator->paginate( $bookRepository->getAllBooksQuery(), $page, 18 ); + return $this->render('default/index.html.twig', [ 'pagination' => $pagination, ]); } + #[Route('/favorites/{page}', name: 'app_favorites', requirements: ['page' => '\d+'])] - public function favorites(BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function favorites(BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $pagination = $paginator->paginate( $bookRepository->getFavoriteBooksQuery(), $page, 18 ); + return $this->render('default/index.html.twig', [ 'pagination' => $pagination, ]); } #[Route('/finished/{read}/{page}', name: 'app_read', requirements: ['page' => '\d+'])] - public function finished(BookRepository $bookRepository, PaginatorInterface $paginator, int $read, int $page=1): Response + public function finished(BookRepository $bookRepository, PaginatorInterface $paginator, int $read, int $page = 1): Response { $pagination = $paginator->paginate( - $bookRepository->getBooksByReadStatus((bool)$read), + $bookRepository->getBooksByReadStatus((bool) $read), $page, 18 ); + return $this->render('default/index.html.twig', [ 'pagination' => $pagination, ]); } #[Route('/unverified/{page}', name: 'app_unverified', requirements: ['page' => '\d+'])] - public function unverified(BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function unverified(BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $pagination = $paginator->paginate( $bookRepository->getUnverifiedBooksQuery(), $page, 18 ); + return $this->render('default/index.html.twig', [ 'pagination' => $pagination, ]); } - } diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php index b92ddb11..efaa8392 100644 --- a/src/Controller/SearchController.php +++ b/src/Controller/SearchController.php @@ -11,18 +11,17 @@ class SearchController extends AbstractController { #[Route('/search/{query}', name: 'app_search')] - public function index( BookRepository $bookRepository, PaginatorInterface $paginator, ?string $query = null,int $page=1): Response + public function index(BookRepository $bookRepository, PaginatorInterface $paginator, string $query = null, int $page = 1): Response { - if($query===null){ - $books=[]; + if (null === $query) { + $books = []; } else { $books = $bookRepository->search($query, 5000); } - return $this->render('search/index.html.twig', [ 'query' => $query, - 'pagination' => $paginator->paginate($books, $page,18), + 'pagination' => $paginator->paginate($books, $page, 18), ]); } } diff --git a/src/Controller/SerieController.php b/src/Controller/SerieController.php index 5b155cdc..17276f0e 100644 --- a/src/Controller/SerieController.php +++ b/src/Controller/SerieController.php @@ -13,30 +13,30 @@ class SerieController extends AbstractController { #[Route('/{page}', name: 'app_serie', requirements: ['page' => '\d+'])] - public function index(BookRepository $bookRepository,PaginatorInterface $paginator, int $page=1): Response + public function index(BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $series = $bookRepository->getAllSeries()->getResult(); - $pagination = $paginator->paginate($series,$page, 18); + $pagination = $paginator->paginate($series, $page, 18); return $this->render('group/index.html.twig', [ 'pagination' => $pagination, - 'page'=> $page, - 'type'=> 'serie', + 'page' => $page, + 'type' => 'serie', ]); } #[Route('/{slug}/{page}', name: 'app_serie_detail', requirements: ['page' => '\d+'])] - public function detail(string $slug, BookRepository $bookRepository, PaginatorInterface $paginator, int $page=1): Response + public function detail(string $slug, BookRepository $bookRepository, PaginatorInterface $paginator, int $page = 1): Response { $series = $bookRepository->getAllSeries()->getResult(); - if(!is_array($series)){ + if (!is_array($series)) { throw $this->createNotFoundException('No series found'); } - $serie = array_filter($series, static fn($serie) => $serie['slug'] === $slug); + $serie = array_filter($series, static fn ($serie) => $serie['slug'] === $slug); - $serie= current($serie); + $serie = current($serie); $pagination = $paginator->paginate( $bookRepository->getBySerieQuery($slug), @@ -45,6 +45,7 @@ public function detail(string $slug, BookRepository $bookRepository, PaginatorIn ); /** @var Book $firstBook */ $firstBook = current($pagination->getItems()); + return $this->render('serie/detail.html.twig', [ 'pagination' => $pagination, 'serie' => $serie, diff --git a/src/Controller/ShelfController.php b/src/Controller/ShelfController.php index 7c0fb906..0e386b9b 100644 --- a/src/Controller/ShelfController.php +++ b/src/Controller/ShelfController.php @@ -3,19 +3,21 @@ namespace App\Controller; use App\Entity\Shelf; -use App\Repository\ShelfRepository; +use Knp\Component\Pager\PaginatorInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class ShelfController extends AbstractController { - #[Route('/shelf/{slug}', name: 'app_shelf')] - public function index(Shelf $shelf): Response + #[Route('/shelf/{slug}/{page}', name: 'app_shelf', requirements: ['page' => '\d+'])] + public function index(Shelf $shelf, PaginatorInterface $paginator, int $page = 1): Response { + $pagination = $paginator->paginate($shelf->getBooks(), $page, 10); return $this->render('shelf/index.html.twig', [ - 'controller_name' => 'ShelfController', + 'shelf' => $shelf, + 'pagination' => $pagination, ]); } } diff --git a/src/Entity/Book.php b/src/Entity/Book.php index 7c04083e..3474686f 100644 --- a/src/Entity/Book.php +++ b/src/Entity/Book.php @@ -78,7 +78,7 @@ class Book private ?\DateTimeInterface $publishDate = null; /** - * @var array + * @var array */ #[ORM\Column(type: Types::ARRAY)] private array $authors = []; @@ -87,7 +87,7 @@ class Book private string $extension; #[ORM\Column(length: 5, nullable: true)] - private ?string $imageExtension=null; + private ?string $imageExtension = null; /** * @var Collection @@ -107,7 +107,7 @@ class Book /** * @var Collection */ - #[ORM\ManyToMany(targetEntity: Shelf::class, mappedBy: 'books')] + #[ORM\ManyToMany(targetEntity: Shelf::class, mappedBy: 'books', cascade: ['persist'])] private Collection $shelves; public function __construct() @@ -116,7 +116,6 @@ public function __construct() $this->shelves = new ArrayCollection(); } - public function getId(): ?int { return $this->id; @@ -129,17 +128,16 @@ public function getTitle(): string public function setTitle(string $title): self { - $this->title = trim($title); - if($title===''){ - $this->title='unknown'; + if ($title === '') { + $this->title = 'unknown'; } return $this; } - public function getSlug():string + public function getSlug(): string { return $this->slug; } @@ -248,9 +246,9 @@ public function getSerie(): ?string public function setSerie(?string $serie): static { - $serie = trim($serie??''); - if($serie===''){ - $serie=null; + $serie = trim($serie ?? ''); + if ($serie === '') { + $serie = null; } $this->serie = $serie; @@ -277,8 +275,8 @@ public function getMainAuthor(): string public function setMainAuthor(string $mainAuthor): static { $this->mainAuthor = trim($mainAuthor); - if($mainAuthor===''){ - $this->mainAuthor='unknown'; + if ($mainAuthor === '') { + $this->mainAuthor = 'unknown'; } return $this; @@ -321,7 +319,7 @@ public function setPublishDate(?\DateTimeInterface $publishDate): static } /** - * @return array + * @return array */ public function getAuthors(): array { diff --git a/src/Entity/BookInteraction.php b/src/Entity/BookInteraction.php index 1330fd51..3da25e70 100644 --- a/src/Entity/BookInteraction.php +++ b/src/Entity/BookInteraction.php @@ -79,6 +79,4 @@ public function setFavorite(bool $favorite): static return $this; } - - } diff --git a/src/Entity/Shelf.php b/src/Entity/Shelf.php index 339f6e68..30024abd 100644 --- a/src/Entity/Shelf.php +++ b/src/Entity/Shelf.php @@ -46,6 +46,7 @@ public function getId(): int public function setId(int $id): static { $this->id = $id; + return $this; } diff --git a/src/Entity/User.php b/src/Entity/User.php index 13a929bc..72642243 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -81,7 +81,7 @@ public function setUsername(string $username): self */ public function getUserIdentifier(): string { - return (string)$this->username; + return (string) $this->username; } /** @@ -98,6 +98,7 @@ public function getRoles(): array /** * @param array $roles + * * @return $this */ public function setRoles(array $roles): self diff --git a/src/EventSubscriber/DisplayModeSubscriber.php b/src/EventSubscriber/DisplayModeSubscriber.php index 02397ce7..2a72d160 100644 --- a/src/EventSubscriber/DisplayModeSubscriber.php +++ b/src/EventSubscriber/DisplayModeSubscriber.php @@ -1,36 +1,29 @@ displayMode = $event->getRequest()->cookies->get('displayMode','gallery'); - $this->displayMode = $event->getRequest()->query->get('displayMode',$this->displayMode); - + $this->displayMode = $event->getRequest()->cookies->get('displayMode', 'gallery'); + $this->displayMode = $event->getRequest()->query->get('displayMode', $this->displayMode); } public function onKernelResponse(ResponseEvent $event): void { $response = $event->getResponse(); - $response->headers->setCookie(new Cookie('displayMode', $this->displayMode, time() + 30*24*3600, '/', null, false, false)); + $response->headers->setCookie(new Cookie('displayMode', $this->displayMode, time() + 30 * 24 * 3600, '/', null, false, false)); } - /** - * @return string - */ public function getDisplayMode(): string { return $this->displayMode; @@ -43,5 +36,4 @@ public static function getSubscribedEvents(): array KernelEvents::RESPONSE => 'onKernelResponse', ]; } - -} \ No newline at end of file +} diff --git a/src/EventSubscriber/EasyAdminSubscriber.php b/src/EventSubscriber/EasyAdminSubscriber.php index d9ffd26a..481a086a 100644 --- a/src/EventSubscriber/EasyAdminSubscriber.php +++ b/src/EventSubscriber/EasyAdminSubscriber.php @@ -1,5 +1,7 @@ getEntityInstance(); @@ -33,7 +35,7 @@ public function hashPassword(BeforeEntityPersistedEvent|BeforeEntityUpdatedEvent return; } - $hash = $this->passwordHasher->hashPassword($entity,$entity->getPassword()); + $hash = $this->passwordHasher->hashPassword($entity, $entity->getPassword()); $entity->setPassword($hash); } -} \ No newline at end of file +} diff --git a/src/Menu/MenuBuilder.php b/src/Menu/MenuBuilder.php index e4a9ee06..5f2df47d 100644 --- a/src/Menu/MenuBuilder.php +++ b/src/Menu/MenuBuilder.php @@ -1,4 +1,5 @@ + * @var array */ - private array $defaultAttr = ['attributes' => ['class' => 'nav-item'],'linkAttributes'=>['class'=>'nav-link icon-link'], 'icon'=>'fa-book']; + private array $defaultAttr = ['attributes' => ['class' => 'nav-item'], 'linkAttributes' => ['class' => 'nav-link icon-link'], 'icon' => 'fa-book']; /** * Add any other dependency you need... */ - public function __construct(private FactoryInterface $factory, private Security $security) + public function __construct(private readonly FactoryInterface $factory, private readonly Security $security) { - } /** @@ -30,27 +30,26 @@ public function createMainMenu(array $options): ItemInterface $menu = $this->factory->createItem('root'); $menu->setChildrenAttribute('class', 'nav flex-column'); - $menu->addChild('Home', ['route' => 'app_homepage', ...$this->defaultAttr])->setExtra('icon','house-fill'); - $menu->addChild('Favorites', ['route' => 'app_favorites', ...$this->defaultAttr])->setExtra('icon','heart-fill'); - $menu->addChild('Read', ['route' => 'app_read', 'routeParameters' => ['read' => 1], ...$this->defaultAttr])->setExtra('icon','journal-check'); - $menu->addChild('Not read', ['route' => 'app_read', 'routeParameters' => ['read' => 0], ...$this->defaultAttr])->setExtra('icon','journal'); - $menu->addChild('Series', ['route' => 'app_serie', ...$this->defaultAttr])->setExtra('icon','list'); - $menu->addChild('Authors', ['route' => 'app_authors', ...$this->defaultAttr])->setExtra('icon','people-fill'); - $menu->addChild('Unverified', ['route' => 'app_unverified', ...$this->defaultAttr])->setExtra('icon','question-circle-fill'); - $menu->addChild('setting_divider',['label'=>'Others'])->setExtra('divider',true); - $menu->addChild('Settings',['route' => 'admin', ...$this->defaultAttr ])->setExtra('icon','gear-fill'); - - $menu->addChild('shelves_divider',['label'=>'Shelves'])->setExtra('divider',true); + $menu->addChild('Home', ['route' => 'app_homepage', ...$this->defaultAttr])->setExtra('icon', 'house-fill'); + $menu->addChild('Favorites', ['route' => 'app_favorites', ...$this->defaultAttr])->setExtra('icon', 'heart-fill'); + $menu->addChild('Read', ['route' => 'app_read', 'routeParameters' => ['read' => 1], ...$this->defaultAttr])->setExtra('icon', 'journal-check'); + $menu->addChild('Not read', ['route' => 'app_read', 'routeParameters' => ['read' => 0], ...$this->defaultAttr])->setExtra('icon', 'journal'); + $menu->addChild('Series', ['route' => 'app_serie', ...$this->defaultAttr])->setExtra('icon', 'list'); + $menu->addChild('Authors', ['route' => 'app_authors', ...$this->defaultAttr])->setExtra('icon', 'people-fill'); + $menu->addChild('Unverified', ['route' => 'app_unverified', ...$this->defaultAttr])->setExtra('icon', 'question-circle-fill'); + $menu->addChild('setting_divider', ['label' => 'Others'])->setExtra('divider', true); + $menu->addChild('Settings', ['route' => 'admin', ...$this->defaultAttr])->setExtra('icon', 'gear-fill'); + $user = $this->security->getUser(); - if($user instanceof User){ - foreach ($user->getShelves() as $shelf){ - $menu->addChild($shelf->getSlug(), ['label'=>$shelf->getName(),'route' => 'app_shelf', 'routeParameters' => ['slug' => $shelf->getSlug()], ...$this->defaultAttr]) - ->setExtra('icon','bookshelf'); + + if ($user instanceof User && $user->getShelves()->count() > 0) { + $menu->addChild('shelves_divider', ['label' => 'Shelves'])->setExtra('divider', true); + foreach ($user->getShelves() as $shelf) { + $menu->addChild($shelf->getSlug(), ['label' => $shelf->getName(), 'route' => 'app_shelf', 'routeParameters' => ['slug' => $shelf->getSlug()], ...$this->defaultAttr]) + ->setExtra('icon', 'bookshelf'); } } - - return $menu; } -} \ No newline at end of file +} diff --git a/src/Repository/BookInteractionRepository.php b/src/Repository/BookInteractionRepository.php index 73bf4df8..569af32c 100644 --- a/src/Repository/BookInteractionRepository.php +++ b/src/Repository/BookInteractionRepository.php @@ -11,8 +11,8 @@ * * @method BookInteraction|null find($id, $lockMode = null, $lockVersion = null) * @method BookInteraction|null findOneBy(array $criteria, array $orderBy = null) - * @method BookInteraction[] findAll() - * @method BookInteraction[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method BookInteraction[] findAll() + * @method BookInteraction[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class BookInteractionRepository extends ServiceEntityRepository { @@ -21,28 +21,28 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, BookInteraction::class); } -// /** -// * @return BookInteraction[] Returns an array of BookInteraction objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('b') -// ->andWhere('b.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('b.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } + // /** + // * @return BookInteraction[] Returns an array of BookInteraction objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('b') + // ->andWhere('b.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('b.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } -// public function findOneBySomeField($value): ?BookInteraction -// { -// return $this->createQueryBuilder('b') -// ->andWhere('b.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } + // public function findOneBySomeField($value): ?BookInteraction + // { + // return $this->createQueryBuilder('b') + // ->andWhere('b.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } } diff --git a/src/Repository/BookRepository.php b/src/Repository/BookRepository.php index 2296f510..173130a7 100644 --- a/src/Repository/BookRepository.php +++ b/src/Repository/BookRepository.php @@ -10,9 +10,10 @@ /** * @extends ServiceEntityRepository + * * @phpstan-type SeriesType array{ serie:string, serieSlug:string, bookCount:int, booksFinished:int, lastBookIndex:int } * @phpstan-type AuthorsType array{ mainAuthor:string, authorSlug:string, bookCount:int, booksFinished:int } -*/ + */ class BookRepository extends ServiceEntityRepository { private Security $security; @@ -23,13 +24,14 @@ public function __construct(ManagerRegistry $registry, Security $security) $this->security = $security; } - public function getAllBooksQuery():Query + public function getAllBooksQuery(): Query { return $this->createQueryBuilder('b') ->select('b') ->getQuery(); } - public function getFavoriteBooksQuery():Query + + public function getFavoriteBooksQuery(): Query { return $this->createQueryBuilder('b') ->select('b') @@ -37,30 +39,33 @@ public function getFavoriteBooksQuery():Query ->setParameter('user', $this->security->getUser()) ->getQuery(); } - public function getUnverifiedBooksQuery():Query + + public function getUnverifiedBooksQuery(): Query { return $this->createQueryBuilder('b') ->select('b') ->where('b.verified = false') ->getQuery(); } - public function getBooksByReadStatus(bool $read):Query + + public function getBooksByReadStatus(bool $read): Query { $q = $this->createQueryBuilder('b') ->select('b') ->leftJoin('b.bookInteractions', 'bookInteraction', 'WITH', 'bookInteraction.user=:user') ->andWhere('bookInteraction.finished = :read'); - if(!$read){ + if (!$read) { $q->orWhere('bookInteraction.finished IS NULL'); } - $q->setParameter('user', $this->security->getUser()) - ->setParameter('read', (int)$read); - ; + $q->setParameter('user', $this->security->getUser()) + ->setParameter('read', (int) $read); + return $q->getQuery(); } - public function getByAuthorQuery(string $authorSlug):Query + + public function getByAuthorQuery(string $authorSlug): Query { return $this->createQueryBuilder('b') ->select('b') @@ -68,34 +73,35 @@ public function getByAuthorQuery(string $authorSlug):Query ->setParameter('authorSlug', $authorSlug) ->getQuery(); } - public function getBySerieQuery(string $serieSlug):Query + + public function getBySerieQuery(string $serieSlug): Query { return $this->createQueryBuilder('b') ->select('b') ->where('b.serieSlug = :serieSlug') ->setParameter('serieSlug', $serieSlug) - ->addOrderBy('b.serieIndex','ASC') + ->addOrderBy('b.serieIndex', 'ASC') ->getQuery(); } /** - * @param string $query * @return array */ - public function search(string $query, int $results=5):array + public function search(string $query, int $results = 5): array { $return = $this->createQueryBuilder('b') ->select('b') ->where('b.serie like :query') ->orWhere('b.title like :query') ->orWhere('b.mainAuthor like :query') - ->setParameter('query', "%".$query.'%') + ->setParameter('query', '%'.$query.'%') ->setMaxResults($results) - ->addOrderBy('b.title','ASC') + ->addOrderBy('b.title', 'ASC') ->getQuery()->getResult(); - if(!is_array($return)){ + if (!is_array($return)) { return []; } + return $return; } @@ -117,10 +123,7 @@ public function remove(Book $entity, bool $flush = false): void } } - /** - * @return Query - */ - public function getAllSeries():Query + public function getAllSeries(): Query { return $this->createQueryBuilder('serie') ->select('serie.serie as item') @@ -134,10 +137,7 @@ public function getAllSeries():Query ->addGroupBy('serie.serie')->getQuery(); } - /** - * @return Query - */ - public function getAllAuthors():Query + public function getAllAuthors(): Query { $qb = $this->createQueryBuilder('author') ->select('author.mainAuthor as item') @@ -147,6 +147,7 @@ public function getAllAuthors():Query ->leftJoin('author.bookInteractions', 'bookInteraction', 'WITH', 'bookInteraction.finished = true and bookInteraction.user=:user') ->setParameter('user', $this->security->getUser()) ->addGroupBy('author.mainAuthor'); - return $qb->getQuery(); + + return $qb->getQuery(); } } diff --git a/src/Repository/ShelfRepository.php b/src/Repository/ShelfRepository.php index b894a1e0..2927c9cc 100644 --- a/src/Repository/ShelfRepository.php +++ b/src/Repository/ShelfRepository.php @@ -11,8 +11,8 @@ * * @method Shelf|null find($id, $lockMode = null, $lockVersion = null) * @method Shelf|null findOneBy(array $criteria, array $orderBy = null) - * @method Shelf[] findAll() - * @method Shelf[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method Shelf[] findAll() + * @method Shelf[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ShelfRepository extends ServiceEntityRepository { @@ -21,28 +21,28 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, Shelf::class); } -// /** -// * @return Shelf[] Returns an array of Shelf objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('s') -// ->andWhere('s.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('s.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } + // /** + // * @return Shelf[] Returns an array of Shelf objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('s') + // ->andWhere('s.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('s.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } -// public function findOneBySomeField($value): ?Shelf -// { -// return $this->createQueryBuilder('s') -// ->andWhere('s.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } + // public function findOneBySomeField($value): ?Shelf + // { + // return $this->createQueryBuilder('s') + // ->andWhere('s.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 2098fbc0..70cb66da 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -14,8 +14,8 @@ * * @method User|null find($id, $lockMode = null, $lockVersion = null) * @method User|null findOneBy(array $criteria, array $orderBy = null) - * @method User[] findAll() - * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method User[] findAll() + * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface { @@ -56,28 +56,28 @@ public function save(User $entity, bool $flush = false): void } } -// /** -// * @return User[] Returns an array of User objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('u') -// ->andWhere('u.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('u.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } + // /** + // * @return User[] Returns an array of User objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('u') + // ->andWhere('u.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('u.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } -// public function findOneBySomeField($value): ?User -// { -// return $this->createQueryBuilder('u') -// ->andWhere('u.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } + // public function findOneBySomeField($value): ?User + // { + // return $this->createQueryBuilder('u') + // ->andWhere('u.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } } diff --git a/src/Security/Voter/BookInteractionVoter.php b/src/Security/Voter/BookInteractionVoter.php index fdcc2100..141b75e9 100644 --- a/src/Security/Voter/BookInteractionVoter.php +++ b/src/Security/Voter/BookInteractionVoter.php @@ -2,7 +2,6 @@ namespace App\Security\Voter; -use App\Entity\Book; use App\Entity\BookInteraction; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; @@ -29,6 +28,4 @@ protected function voteOnAttribute(string $attribute, mixed $subject, TokenInter return $subject->getUser() === $user; } - - } diff --git a/src/Service/BookFileSystemManager.php b/src/Service/BookFileSystemManager.php index acaf2464..ef8e80d6 100644 --- a/src/Service/BookFileSystemManager.php +++ b/src/Service/BookFileSystemManager.php @@ -3,19 +3,15 @@ namespace App\Service; use App\Entity\Book; -use Exception; -use Iterator; -use RuntimeException; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; -use \SplFileInfo; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\String\Slugger\SluggerInterface; class BookFileSystemManager { public const ALLOWED_FILE_EXTENSIONS = [ - '*.epub','*.cbr','*.cbz','*.pdf','*.mobi' + '*.epub', '*.cbr', '*.cbz', '*.pdf', '*.mobi', ]; public const CHUNK = 65536; @@ -29,106 +25,105 @@ public function __construct(KernelInterface $appKernel, SluggerInterface $slugge $this->slugger = $slugger; } - - public function getBooksDirectory():string + public function getBooksDirectory(): string { - return $this->appKernel->getProjectDir() . '/public/books/'; + return $this->appKernel->getProjectDir().'/public/books/'; } - - public function getCoverDirectory():string + public function getCoverDirectory(): string { - return $this->appKernel->getProjectDir() . '/public/covers/'; + return $this->appKernel->getProjectDir().'/public/covers/'; } - /** - * @return Iterator + * @return \Iterator<\SplFileInfo> */ - public function getAllBooksFiles(): Iterator + public function getAllBooksFiles(): \Iterator { - try{ + try { $finder = new Finder(); $finder->files()->name(self::ALLOWED_FILE_EXTENSIONS)->in($this->getBooksDirectory()); $iterator = $finder->getIterator(); - }catch(Exception $e){ + } catch (\Exception $e) { $iterator = new \ArrayIterator(); } + return $iterator; } /** - * @throws Exception + * @throws \Exception */ - public function getBookFile(Book $book): SplFileInfo + public function getBookFile(Book $book): \SplFileInfo { $finder = new Finder(); $finder->files()->name($book->getBookFilename())->in($this->getBooksDirectory().$book->getBookPath()); - $return =iterator_to_array($finder->getIterator()); + $return = iterator_to_array($finder->getIterator()); - if(count($return)===0){ - throw new RuntimeException('Book file not found '.$book->getBookPath().$book->getBookFilename()); + if (0 === count($return)) { + throw new \RuntimeException('Book file not found '.$book->getBookPath().$book->getBookFilename()); } return current($return); } /** - * @throws Exception + * @throws \Exception */ - public function getCoverFile(Book $book): ?SplFileInfo + public function getCoverFile(Book $book): ?\SplFileInfo { - if($book->getImageFilename()===null){ + if (null === $book->getImageFilename()) { return null; } $finder = new Finder(); $finder->files()->name($book->getImageFilename())->in($this->getCoverDirectory().$book->getImagePath()); - $return =iterator_to_array($finder->getIterator()); - if(count($return)===0){ - throw new RuntimeException('Cover file not found:'.$this->getCoverDirectory().$book->getImagePath().'/'.$book->getImageFilename()); + $return = iterator_to_array($finder->getIterator()); + if (0 === count($return)) { + throw new \RuntimeException('Cover file not found:'.$this->getCoverDirectory().$book->getImagePath().'/'.$book->getImageFilename()); } + return current($return); } /** * Calculates the checksum of a given file. * - * @param SplFileInfo $file The file for which to calculate the checksum. + * @param \SplFileInfo $file the file for which to calculate the checksum * - * @return string The checksum of the file. + * @return string the checksum of the file * - * @throws RuntimeException If the checksum calculation fails. + * @throws \RuntimeException if the checksum calculation fails */ - public function getFileChecksum(SplFileInfo $file): string + public function getFileChecksum(\SplFileInfo $file): string { - $checkSum = shell_exec('sha1sum -b ' . escapeshellarg($file->getRealPath())); + $checkSum = shell_exec('sha1sum -b '.escapeshellarg($file->getRealPath())); - if ($checkSum === null || $checkSum === false) { - throw new RuntimeException('Could not calculate file Checksum'); + if (null === $checkSum || false === $checkSum) { + throw new \RuntimeException('Could not calculate file Checksum'); } - [$checkSum,] = explode(' ', $checkSum); + [$checkSum] = explode(' ', $checkSum); return $checkSum; } - public function getFolderName(SplFileInfo $file, bool $absolute=false):string + public function getFolderName(\SplFileInfo $file, bool $absolute = false): string { - $path = $absolute? $file->getRealPath():str_replace($this->getBooksDirectory(),'',$file->getRealPath()); - return str_replace($file->getFilename(),'', $path); + $path = $absolute ? $file->getRealPath() : str_replace($this->getBooksDirectory(), '', $file->getRealPath()); + return str_replace($file->getFilename(), '', $path); } - private function calculateFilePath(Book $book):string + private function calculateFilePath(Book $book): string { $author = mb_strtolower($this->slugger->slug($book->getMainAuthor())); $title = mb_strtolower($this->slugger->slug($book->getTitle())); - $serie = $book->getSerie()!==null?mb_strtolower($this->slugger->slug($book->getSerie())):null; + $serie = null !== $book->getSerie() ? mb_strtolower($this->slugger->slug($book->getSerie())) : null; $letter = $author[0]; $path = [$letter]; - if($serie!==null) { + if (null !== $serie) { $path[] = $serie; } @@ -136,48 +131,50 @@ private function calculateFilePath(Book $book):string $path[] = $title; $expectedPath = implode(DIRECTORY_SEPARATOR, $path); + return $expectedPath.DIRECTORY_SEPARATOR; } - public function getCalculatedFilePath(Book $book, bool $realpath):string + + public function getCalculatedFilePath(Book $book, bool $realpath): string { $expectedPath = $this->calculateFilePath($book); - return ($realpath?$this->getBooksDirectory():'').$expectedPath; + return ($realpath ? $this->getBooksDirectory() : '').$expectedPath; } - public function getCalculatedImagePath(Book $book, bool $realpath):string + public function getCalculatedImagePath(Book $book, bool $realpath): string { $expectedFilepath = $this->calculateFilePath($book); - return ($realpath?$this->getCoverDirectory():'').$expectedFilepath; - } + return ($realpath ? $this->getCoverDirectory() : '').$expectedFilepath; + } - private function calculateFileName(Book $book):string + private function calculateFileName(Book $book): string { $expectedFilename = ''; - if($book->getSerie()!==null){ - $expectedFilename.=$book->getSerie().' '.$book->getSerieIndex().' - '; + if (null !== $book->getSerie()) { + $expectedFilename .= $book->getSerie().' '.$book->getSerieIndex().' - '; } - $expectedFilename.= $book->getTitle(); + $expectedFilename .= $book->getTitle(); - return str_replace('/','',$expectedFilename); + return str_replace('/', '', $expectedFilename); } - public function getCalculatedFileName(Book $book):string + public function getCalculatedFileName(Book $book): string { return $this->calculateFileName($book).'.'.$book->getExtension(); } - public function getCalculatedImageName(Book $book):string + public function getCalculatedImageName(Book $book): string { return $this->calculateFileName($book).'.'.$book->getImageExtension(); } - public function renameFiles(Book $book):Book + public function renameFiles(Book $book): Book { $filesystem = new Filesystem(); - if($book->getBookPath().'/'!==$this->getCalculatedFilePath($book,false)){ + if ($book->getBookPath().'/' !== $this->getCalculatedFilePath($book, false)) { $filesystem->mkdir($this->getCalculatedFilePath($book, true)); $filesystem->rename( $this->getBooksDirectory().$book->getBookPath().$book->getBookFilename(), @@ -188,8 +185,7 @@ public function renameFiles(Book $book):Book $book->setBookFilename($this->getCalculatedFileName($book)); } - - if($book->getImagePath()!==null && $book->getImagePath().'/'!==$this->getCalculatedImagePath($book,false)){ + if (null !== $book->getImagePath() && $book->getImagePath().'/' !== $this->getCalculatedImagePath($book, false)) { $filesystem->mkdir($this->getCalculatedImagePath($book, true)); $filesystem->rename( $this->getCoverDirectory().$book->getImagePath().'/'.$book->getImageFilename(), @@ -203,33 +199,28 @@ public function renameFiles(Book $book):Book return $book; } - - - public function removeEmptySubFolders(?string $path=null):bool + public function removeEmptySubFolders(string $path = null): bool { - if($path===null) { + if (null === $path) { $path = $this->getBooksDirectory(); } - $empty=true; - $files = glob($path.DIRECTORY_SEPARATOR."*"); - if($files!==false && count($files)>0){ - foreach ($files as $file) - { - if (is_dir($file)) - { + $empty = true; + $files = glob($path.DIRECTORY_SEPARATOR.'*'); + if (false !== $files && count($files) > 0) { + foreach ($files as $file) { + if (is_dir($file)) { if (!$this->removeEmptySubFolders($file)) { $empty = false; } - } - else - { - $empty=false; + } else { + $empty = false; } } } if ($empty) { rmdir($path); } + return $empty; } -} \ No newline at end of file +} diff --git a/src/Service/BookManager.php b/src/Service/BookManager.php index 20884063..fad56962 100644 --- a/src/Service/BookManager.php +++ b/src/Service/BookManager.php @@ -3,15 +3,11 @@ namespace App\Service; use App\Entity\Book; -use Exception; use Kiwilan\Ebook\Ebook; use Kiwilan\Ebook\EbookCover; use Kiwilan\Ebook\Tools\BookAuthor; -use RuntimeException; -use \SplFileInfo; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\KernelInterface; -use ZipArchive; /** * @phpstan-type MetadataType array{ title:string, authors: BookAuthor[], main_author: ?BookAuthor, description: ?string, publisher: ?string, publish_date: ?\DateTime, language: ?string, tags: string[], serie:?string, serie_index: ?int, cover: ?EbookCover } @@ -27,12 +23,10 @@ public function __construct(KernelInterface $appKernel, BookFileSystemManager $f $this->fileSystemManager = $fileSystemManager; } - - /** - * @throws Exception + * @throws \Exception */ - public function createBook(SplFileInfo $file):Book + public function createBook(\SplFileInfo $file): Book { $book = new Book(); @@ -40,21 +34,21 @@ public function createBook(SplFileInfo $file):Book $book->setTitle($extractedMetadata['title']); $book->setChecksum($this->fileSystemManager->getFileChecksum($file)); $book->setMainAuthor('unknown'); - if($extractedMetadata['main_author']!==null) { - $book->setMainAuthor($extractedMetadata['main_author']->getName()??'unknown'); + if (null !== $extractedMetadata['main_author']) { + $book->setMainAuthor($extractedMetadata['main_author']->getName() ?? 'unknown'); } - foreach ($extractedMetadata['authors'] as $author){ - $book->addAuthor($author->getName()??'unknown'); + foreach ($extractedMetadata['authors'] as $author) { + $book->addAuthor($author->getName() ?? 'unknown'); } $book->setSummary($extractedMetadata['description']); - if($extractedMetadata['serie']!==null) { + if (null !== $extractedMetadata['serie']) { $book->setSerie($extractedMetadata['serie']); $book->setSerieIndex($extractedMetadata['serie_index']); } $book->setPublisher($extractedMetadata['publisher']); $book->setPublishDate($extractedMetadata['publish_date']); - if(strlen($extractedMetadata['language']??'')===2){ + if (2 === strlen($extractedMetadata['language'] ?? '')) { $book->setLanguage($extractedMetadata['language']); } @@ -63,21 +57,20 @@ public function createBook(SplFileInfo $file):Book $book->setBookPath(''); $book->setBookFilename(''); - $book = $this->updateBookLocation($book,$file); + $book = $this->updateBookLocation($book, $file); /** @var ?EbookCover $cover */ $cover = $extractedMetadata['cover']; - if($cover!==null && $cover->getPath()!==null) { - + if (null !== $cover && null !== $cover->getPath()) { $coverContent = $cover->getContent(); - $coverFileName = explode('/',$cover->getPath()); + $coverFileName = explode('/', $cover->getPath()); $coverFileName = end($coverFileName); $ext = explode('.', $coverFileName); $book->setImageExtension(end($ext)); - $coverPath = $this->fileSystemManager->getCalculatedImagePath($book,true); + $coverPath = $this->fileSystemManager->getCalculatedImagePath($book, true); $coverFileName = $this->fileSystemManager->getCalculatedImageName($book); $filesystem = new Filesystem(); @@ -85,23 +78,22 @@ public function createBook(SplFileInfo $file):Book $coverFile = file_put_contents($coverPath.$coverFileName, $coverContent); - if ($coverFile !== false) { - $book->setImagePath($this->fileSystemManager->getCalculatedImagePath($book,false)); + if (false !== $coverFile) { + $book->setImagePath($this->fileSystemManager->getCalculatedImagePath($book, false)); $book->setImageFilename($coverFileName); } - } return $book; } - public function updateBookLocation(Book $book, SplFileInfo $file):Book + public function updateBookLocation(Book $book, \SplFileInfo $file): Book { $path = $this->fileSystemManager->getFolderName($file); - if($path!==$book->getBookPath()){ + if ($path !== $book->getBookPath()) { $book->setBookPath($path); } - if($file->getFilename()!==$book->getBookFilename()){ + if ($file->getFilename() !== $book->getBookFilename()) { $book->setBookFilename($file->getFilename()); } @@ -109,51 +101,49 @@ public function updateBookLocation(Book $book, SplFileInfo $file):Book } /** - * @param SplFileInfo $file * @return MetadataType - * @throws Exception + * + * @throws \Exception */ - public function extractEbookMetadata(SplFileInfo $file):array + public function extractEbookMetadata(\SplFileInfo $file): array { try { - - if(!Ebook::isValid($file->getRealPath())){ - throw new RuntimeException('Could not read ebook' . $file->getRealPath()); + if (!Ebook::isValid($file->getRealPath())) { + throw new \RuntimeException('Could not read ebook'.$file->getRealPath()); } $ebook = Ebook::read($file->getRealPath()); - if ($ebook === null) { - - throw new RuntimeException('Could not read ebook'); + if (null === $ebook) { + throw new \RuntimeException('Could not read ebook'); } - }catch (\Exception $e){ + } catch (\Exception $e) { return [ - 'title'=>$file->getFilename(), - 'authors'=>[new BookAuthor('unknown')], // BookAuthor[] (`name`: string, `role`: string) - 'main_author'=>new BookAuthor('unknown'), // ?BookAuthor => First BookAuthor (`name`: string, `role`: string) - 'description'=>null, // ?string - 'publisher'=>null, // ?string - 'publish_date'=>null, // ?DateTime - 'language'=>null, // ?string - 'tags'=>[], // string[] => `subject` in EPUB, `keywords` in PDF, `genres` in CBA - 'serie'=>null, // ?string => `calibre:series` in EPUB, `series` in CBA - 'serie_index'=>null, // ?int => `calibre:series_index` in EPUB, `number` in CBA - 'cover'=>null, // ?EbookCover => cover of book + 'title' => $file->getFilename(), + 'authors' => [new BookAuthor('unknown')], // BookAuthor[] (`name`: string, `role`: string) + 'main_author' => new BookAuthor('unknown'), // ?BookAuthor => First BookAuthor (`name`: string, `role`: string) + 'description' => null, // ?string + 'publisher' => null, // ?string + 'publish_date' => null, // ?DateTime + 'language' => null, // ?string + 'tags' => [], // string[] => `subject` in EPUB, `keywords` in PDF, `genres` in CBA + 'serie' => null, // ?string => `calibre:series` in EPUB, `series` in CBA + 'serie_index' => null, // ?int => `calibre:series_index` in EPUB, `number` in CBA + 'cover' => null, // ?EbookCover => cover of book ]; } + return [ - 'title'=>$ebook->getTitle()??$file->getFilename(), // string - 'authors'=>$ebook->getAuthors(), // BookAuthor[] (`name`: string, `role`: string) - 'main_author'=>$ebook->getAuthorMain(), // ?BookAuthor => First BookAuthor (`name`: string, `role`: string) - 'description'=>$ebook->getDescription(), // ?string - 'publisher'=>$ebook->getPublisher(), // ?string - 'publish_date'=>$ebook->getPublishDate(), // ?DateTime - 'language'=>$ebook->getLanguage(), // ?string - 'tags'=>$ebook->getTags(), // string[] => `subject` in EPUB, `keywords` in PDF, `genres` in CBA - 'serie'=>$ebook->getSeries(), // ?string => `calibre:series` in EPUB, `series` in CBA - 'serie_index'=>$ebook->getVolume(), // ?int => `calibre:series_index` in EPUB, `number` in CBA - 'cover'=>$ebook->getCover(), // ?EbookCover => cover of book + 'title' => $ebook->getTitle() ?? $file->getFilename(), // string + 'authors' => $ebook->getAuthors(), // BookAuthor[] (`name`: string, `role`: string) + 'main_author' => $ebook->getAuthorMain(), // ?BookAuthor => First BookAuthor (`name`: string, `role`: string) + 'description' => $ebook->getDescription(), // ?string + 'publisher' => $ebook->getPublisher(), // ?string + 'publish_date' => $ebook->getPublishDate(), // ?DateTime + 'language' => $ebook->getLanguage(), // ?string + 'tags' => $ebook->getTags(), // string[] => `subject` in EPUB, `keywords` in PDF, `genres` in CBA + 'serie' => $ebook->getSeries(), // ?string => `calibre:series` in EPUB, `series` in CBA + 'serie_index' => $ebook->getVolume(), // ?int => `calibre:series_index` in EPUB, `number` in CBA + 'cover' => $ebook->getCover(), // ?EbookCover => cover of book ]; - } -} \ No newline at end of file +} diff --git a/src/Twig/AddBookToShelf.php b/src/Twig/AddBookToShelf.php new file mode 100644 index 00000000..b16a7b83 --- /dev/null +++ b/src/Twig/AddBookToShelf.php @@ -0,0 +1,80 @@ +getRepository(Shelf::class); + + $this->shelves = $shelfRepository->findBy(['user' => $security->getUser()]); + } + + #[LiveAction] + public function add(EntityManagerInterface $entityManager, #[LiveArg] int $shelfId): void + { + $shelfRepository = $entityManager->getRepository(Shelf::class); + + $shelf = $shelfRepository->find($shelfId); + + if (null === $shelf) { + throw new RuntimeException('Shelf not found'); + } + + $this->book->addShelf($shelf); + + $entityManager->flush(); + + $this->flashMessage = 'Added to shelf'; + } + + #[LiveAction] + public function remove(EntityManagerInterface $entityManager, #[LiveArg] int $shelfId): void + { + $shelfRepository = $entityManager->getRepository(Shelf::class); + + $shelf = $shelfRepository->find($shelfId); + + if (null === $shelf) { + throw new RuntimeException('Shelf not found'); + } + + $this->book->removeShelf($shelf); + + $entityManager->flush(); + + $this->flashMessage = 'Removed from shelf'; + } +} diff --git a/src/Twig/InlineEditBook.php b/src/Twig/InlineEditBook.php index 89d627e9..0ccc9b0c 100644 --- a/src/Twig/InlineEditBook.php +++ b/src/Twig/InlineEditBook.php @@ -1,4 +1,5 @@ isEditing = true; } #[LiveAction] - public function save(EntityManagerInterface $entityManager):void + public function save(EntityManagerInterface $entityManager): void { - $entityManager->flush(); $this->dispatchBrowserEvent('manager:flush'); $this->isEditing = false; - $this->flashMessage = ' book updated'; } } diff --git a/src/Twig/InlineEditGroup.php b/src/Twig/InlineEditGroup.php index 699fe35c..0c485c4e 100644 --- a/src/Twig/InlineEditGroup.php +++ b/src/Twig/InlineEditGroup.php @@ -1,9 +1,9 @@ isEditing = true; } /** - * @throws RuntimeException + * @throws \RuntimeException */ #[LiveAction] - public function save(EntityManagerInterface $entityManager):void + public function save(EntityManagerInterface $entityManager): void { $thisItem = $this->item; $bookRepo = $entityManager->getRepository(Book::class); - $books = $bookRepo->findBy([$this->type=>$this->original['item']]); + $books = $bookRepo->findBy([$this->type => $this->original['item']]); - foreach($books as $book) { - switch ($this->type){ + foreach ($books as $book) { + switch ($this->type) { case 'mainAuthor': $book->setMainAuthor($this->item['item']); break; @@ -75,7 +75,7 @@ public function save(EntityManagerInterface $entityManager):void $entityManager->flush(); $items = []; - switch ($this->type){ + switch ($this->type) { case 'mainAuthor': $items = $bookRepo->getAllAuthors()->getResult(); break; @@ -84,20 +84,17 @@ public function save(EntityManagerInterface $entityManager):void break; } - if(!is_array($items)){ - throw new RuntimeException('No items found'); + if (!is_array($items)) { + throw new \RuntimeException('No items found'); } - - $item = array_filter($items, static function($s) use ($thisItem) { + $item = array_filter($items, static function ($s) use ($thisItem) { return $s['item'] === $thisItem['item']; - } ); - - + }); - $item= current($item); - if ($item === false) { - throw new RuntimeException($this->type.' not found'); + $item = current($item); + if (false === $item) { + throw new \RuntimeException($this->type.' not found'); } $this->original = $item; diff --git a/src/Twig/InlineEditInteraction.php b/src/Twig/InlineEditInteraction.php index 5b45d3f9..fd8ec1b3 100644 --- a/src/Twig/InlineEditInteraction.php +++ b/src/Twig/InlineEditInteraction.php @@ -1,4 +1,5 @@ interaction; - if($interaction===null) { + if (null === $interaction) { $bookInteractionRepo = $entityManager->getRepository(BookInteraction::class); $interaction = $bookInteractionRepo->findOneBy(['user' => $this->user, 'book' => $this->book]); - if ($interaction === null) { + if (null === $interaction) { $interaction = new BookInteraction(); $interaction->setUser($this->user); $interaction->setBook($this->book); } } + return $interaction; } #[LiveAction] - public function toggle(EntityManagerInterface $entityManager):void + public function toggle(EntityManagerInterface $entityManager): void { $interaction = $this->getInteraction($entityManager); @@ -59,8 +59,9 @@ public function toggle(EntityManagerInterface $entityManager):void $this->flashMessage = 'Saved'; } + #[LiveAction] - public function toggleFavorite(EntityManagerInterface $entityManager):void + public function toggleFavorite(EntityManagerInterface $entityManager): void { $interaction = $this->getInteraction($entityManager); diff --git a/src/Twig/Search.php b/src/Twig/Search.php index 271ccf8f..11ceaeb3 100644 --- a/src/Twig/Search.php +++ b/src/Twig/Search.php @@ -25,9 +25,10 @@ public function __construct(private BookRepository $bookRepository) */ public function getBooks(): array { - if($this->query===null){ + if (null === $this->query) { return []; } + return $this->bookRepository->search($this->query); } -} \ No newline at end of file +} diff --git a/symfony.lock b/symfony.lock index 1f8ccf71..2079b4b4 100644 --- a/symfony.lock +++ b/symfony.lock @@ -44,6 +44,18 @@ "ref": "b131e6cbfe1b898a508987851963fff485986285" } }, + "friendsofphp/php-cs-fixer": { + "version": "3.25", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.0", + "ref": "be2103eb4a20942e28a6dd87736669b757132435" + }, + "files": [ + ".php-cs-fixer.dist.php" + ] + }, "knplabs/knp-markdown-bundle": { "version": "1.10.0" }, diff --git a/templates/book/index.html.twig b/templates/book/index.html.twig index 97ca9443..af2debf0 100644 --- a/templates/book/index.html.twig +++ b/templates/book/index.html.twig @@ -12,6 +12,9 @@ {% else %} No picture for {{ book.title }} {% endif %} + {{ include('book/_interaction.html.twig') }} + + {{ component('AddBookToShelf',{'book':book, 'user':app.user}) }}
@@ -56,10 +59,7 @@ -
Verified{{ component('InlineEditBook', {'book':book, 'field':'verified', inline: true}) }}
- {{ include('book/_interaction.html.twig') }} -
diff --git a/templates/components/AddBookToShelf.html.twig b/templates/components/AddBookToShelf.html.twig new file mode 100644 index 00000000..1dd4b0c7 --- /dev/null +++ b/templates/components/AddBookToShelf.html.twig @@ -0,0 +1,33 @@ +
+
Shelves
+
+ {% for shelf in shelves %} + + {% if shelf in book.shelves %} + + {% else %} + + {% endif %} + {% endfor %} +
+ {% if flashMessage %} +
+ {{ flashMessage }} +
+ {% endif %} + +
diff --git a/templates/shelf/index.html.twig b/templates/shelf/index.html.twig index 9e56e837..88638c23 100644 --- a/templates/shelf/index.html.twig +++ b/templates/shelf/index.html.twig @@ -1,20 +1,8 @@ {% extends 'base.html.twig' %} -{% block title %}Hello ShelfController!{% endblock %} +{% block title %}{{ shelf.name }}{% endblock %} {% block body %} - -
-

Hello {{ controller_name }}! ✅

- - This friendly message is coming from: - -
+ {% include 'book/_pagination.html.twig' %} {% endblock %}