diff --git a/.env.php b/.env.php new file mode 100644 index 0000000..0e08751 --- /dev/null +++ b/.env.php @@ -0,0 +1,7 @@ + 'dev', +]; diff --git a/.gitignore b/.gitignore index 166a16a..42743fc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ /data/logs/* !/data/logs/.gitkeep -/config/config.local.php \ No newline at end of file +.env.local.php.dist \ No newline at end of file diff --git a/README.md b/README.md index 1e3b3ae..f82124d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ docker-compose exec php php bin/console.php app:database-fixture ```bash # Create prod config and change needed values -cp ./config/config.local.php.dist ./config/config.local.php +cp ./.env.local.php.dist ./.env.local.php # Docker docker-compose -f docker-compose.prod.yml up -d --build diff --git a/bin/console.php b/bin/console.php index cbdcda3..0c5508d 100644 --- a/bin/console.php +++ b/bin/console.php @@ -3,16 +3,13 @@ declare(strict_types=1); use Jesperbeisner\Fwstats\Command\AbstractCommand; -use Jesperbeisner\Fwstats\Stdlib\ServiceContainer; +use Jesperbeisner\Fwstats\Stdlib\Container; -/** @var ServiceContainer $serviceContainer */ -$serviceContainer = require __DIR__ . '/../bootstrap.php'; +/** @var Container $container */ +$container = require __DIR__ . '/../bootstrap.php'; -/** @var mixed[] $config */ -$config = $serviceContainer->get('config'); - -/** @var string[] $commandStrings */ -$commandStrings = $config['commands']; +/** @var array> $commands */ +$commandStrings = require __DIR__ . '/../config/commands.php'; if (!isset($argv[1])) { echo 'Available commands: ' . PHP_EOL . PHP_EOL; @@ -41,13 +38,13 @@ exit(1); } -if (!$serviceContainer->has($commandClass)) { +if (!$container->has($commandClass)) { echo "Command '$commandClass' not found in the service container. Did you forget to register it?" . PHP_EOL; exit(1); } /** @var AbstractCommand $command */ -$command = $serviceContainer->get($commandClass); +$command = $container->get($commandClass); $command->setArguments($argv); exit($command->execute()); diff --git a/bootstrap.php b/bootstrap.php index 5bf7b5f..35b852b 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -2,21 +2,21 @@ declare(strict_types=1); -use Jesperbeisner\Fwstats\Stdlib\ServiceContainer; +use Jesperbeisner\Fwstats\Stdlib\Config; +use Jesperbeisner\Fwstats\Stdlib\DotEnvPhpLoader; +use Jesperbeisner\Fwstats\Stdlib\Container; +use Jesperbeisner\Fwstats\Stdlib\Router; require __DIR__ . '/vendor/autoload.php'; -$config = require __DIR__ . '/config/config.php'; +DotEnvPhpLoader::load([__DIR__ . '/.env.php', __DIR__ . '/.env.local.php']); -if (file_exists(__DIR__ . '/config/config.local.php')) { - $configLocal = require __DIR__ . '/config/config.local.php'; - $config = array_merge($config, $configLocal); -} +$config = new Config(__DIR__ . '/config/config.php'); +$router = new Router(__DIR__ . '/config/routes.php'); -$serviceContainer = new ServiceContainer($config['services']); +$serviceContainer = new Container(__DIR__ . '/config/services.php'); -$serviceContainer->set('config', $config); -$serviceContainer->set('appEnv', $config['app_env']); -$serviceContainer->set('rootDir', __DIR__); +$serviceContainer->set(Config::class, $config); +$serviceContainer->set(Router::class, $router); return $serviceContainer; diff --git a/composer.json b/composer.json index 409def7..e8c3ee4 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "jesperbeisner/fwstats", - "description": "Statistics website for the world 'ActionFreewar' in the browser game freewar.de", + "description": "Statistics website for the worlds 'ActionFreewar' and 'ChaosFreewar' in the browser game 'freewar.de'.", "type": "project", "license": "MIT", "authors": [ @@ -12,9 +12,7 @@ ], "require": { "php": "^8.1", - "nikic/fast-route": "^1.3", - "psr/container": "^2.0", - "psr/log": "^3.0" + "nikic/fast-route": "^1.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.9", diff --git a/composer.lock b/composer.lock index 13b8909..34172f0 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": "f097d3199f006f0fa648cbaea777821c", + "content-hash": "fd41ac03221ff1fc9710d20f9310d97e", "packages": [ { "name": "nikic/fast-route", @@ -55,109 +55,6 @@ "source": "https://github.com/nikic/FastRoute/tree/master" }, "time": "2018-02-13T20:26:39+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/log", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" } ], "packages-dev": [ @@ -600,16 +497,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.9.5", + "version": "v3.11.0", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "4465d70ba776806857a1ac2a6f877e582445ff36" + "reference": "7dcdea3f2f5f473464e835be9be55283ff8cfdc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/4465d70ba776806857a1ac2a6f877e582445ff36", - "reference": "4465d70ba776806857a1ac2a6f877e582445ff36", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/7dcdea3f2f5f473464e835be9be55283ff8cfdc3", + "reference": "7dcdea3f2f5f473464e835be9be55283ff8cfdc3", "shasum": "" }, "require": { @@ -619,7 +516,7 @@ "ext-json": "*", "ext-tokenizer": "*", "php": "^7.4 || ^8.0", - "php-cs-fixer/diff": "^2.0", + "sebastian/diff": "^4.0", "symfony/console": "^5.4 || ^6.0", "symfony/event-dispatcher": "^5.4 || ^6.0", "symfony/filesystem": "^5.4 || ^6.0", @@ -677,7 +574,7 @@ "description": "A tool to automatically fix PHP code style", "support": { "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.9.5" + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.11.0" }, "funding": [ { @@ -685,7 +582,7 @@ "type": "github" } ], - "time": "2022-07-22T08:43:51+00:00" + "time": "2022-09-01T18:24:51+00:00" }, { "name": "myclabs/deep-copy", @@ -748,16 +645,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.14.0", + "version": "v4.15.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", "shasum": "" }, "require": { @@ -798,9 +695,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" }, - "time": "2022-05-31T20:59:12+00:00" + "time": "2022-09-04T07:30:47+00:00" }, { "name": "phar-io/manifest", @@ -913,297 +810,18 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "php-cs-fixer/diff", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "sebastian/diff v3 backport support for PHP 5.6+", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" - }, - "time": "2020-10-14T08:32:19+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" - }, { "name": "phpstan/phpstan", - "version": "1.8.2", + "version": "1.8.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" + "reference": "08310ce271984587e2a4cda94e1ac66510a6ea07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/08310ce271984587e2a4cda94e1ac66510a6ea07", + "reference": "08310ce271984587e2a4cda94e1ac66510a6ea07", "shasum": "" }, "require": { @@ -1227,9 +845,13 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.2" + "source": "https://github.com/phpstan/phpstan/tree/1.8.8" }, "funding": [ { @@ -1240,36 +862,32 @@ "url": "https://github.com/phpstan", "type": "github" }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, { "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", "type": "tidelift" } ], - "time": "2022-07-20T09:57:31+00:00" + "time": "2022-10-06T12:51:57+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.15", + "version": "9.2.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8", + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.14", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -1318,7 +936,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" }, "funding": [ { @@ -1326,7 +944,7 @@ "type": "github" } ], - "time": "2022-03-07T09:28:20+00:00" + "time": "2022-08-30T12:24:04+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1571,16 +1189,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.21", + "version": "9.5.25", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", "shasum": "" }, "require": { @@ -1595,7 +1213,6 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", @@ -1603,19 +1220,16 @@ "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", + "sebastian/comparator": "^4.0.8", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", + "sebastian/exporter": "^4.0.5", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", + "sebastian/type": "^3.2", "sebastian/version": "^3.0.2" }, - "require-dev": { - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" @@ -1657,7 +1271,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25" }, "funding": [ { @@ -1667,9 +1281,13 @@ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2022-06-19T12:14:25+00:00" + "time": "2022-09-25T03:44:45+00:00" }, { "name": "psr/cache", @@ -1720,6 +1338,59 @@ }, "time": "2021-02-03T23:26:27+00:00" }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, { "name": "psr/event-dispatcher", "version": "1.0.0", @@ -1770,6 +1441,56 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.1", @@ -1939,16 +1660,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -2001,7 +1722,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -2009,7 +1730,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -2199,16 +1920,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -2264,7 +1985,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -2272,7 +1993,7 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -2627,16 +2348,16 @@ }, { "name": "sebastian/type", - "version": "3.0.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", "shasum": "" }, "require": { @@ -2648,7 +2369,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2671,7 +2392,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" }, "funding": [ { @@ -2679,7 +2400,7 @@ "type": "github" } ], - "time": "2022-03-15T09:54:48+00:00" + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", @@ -2736,16 +2457,16 @@ }, { "name": "symfony/console", - "version": "v6.1.3", + "version": "v6.1.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8" + "reference": "17524a64ebcfab68d237bbed247e9a9917747096" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/43fcb5c5966b43c56bcfa481368d90d748936ab8", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8", + "url": "https://api.github.com/repos/symfony/console/zipball/17524a64ebcfab68d237bbed247e9a9917747096", + "reference": "17524a64ebcfab68d237bbed247e9a9917747096", "shasum": "" }, "require": { @@ -2812,7 +2533,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.1.3" + "source": "https://github.com/symfony/console/tree/v6.1.5" }, "funding": [ { @@ -2828,7 +2549,7 @@ "type": "tidelift" } ], - "time": "2022-07-22T14:17:57+00:00" + "time": "2022-09-03T14:24:42+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3061,16 +2782,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.1.3", + "version": "v6.1.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9" + "reference": "4d216a2beef096edf040a070117c39ca2abce307" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c780e677cddda78417fa5187a7c6cd2f21110db9", - "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d216a2beef096edf040a070117c39ca2abce307", + "reference": "4d216a2beef096edf040a070117c39ca2abce307", "shasum": "" }, "require": { @@ -3104,7 +2825,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.1.3" + "source": "https://github.com/symfony/filesystem/tree/v6.1.5" }, "funding": [ { @@ -3120,7 +2841,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T14:45:06+00:00" + "time": "2022-09-21T20:29:40+00:00" }, { "name": "symfony/finder", @@ -3893,16 +3614,16 @@ }, { "name": "symfony/stopwatch", - "version": "v6.1.0", + "version": "v6.1.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d" + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/77dedae82ce2a26e2e9b481855473fc3b3e4e54d", - "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", "shasum": "" }, "require": { @@ -3935,7 +3656,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.1.0" + "source": "https://github.com/symfony/stopwatch/tree/v6.1.5" }, "funding": [ { @@ -3951,20 +3672,20 @@ "type": "tidelift" } ], - "time": "2022-02-25T11:15:52+00:00" + "time": "2022-09-28T16:00:52+00:00" }, { "name": "symfony/string", - "version": "v6.1.3", + "version": "v6.1.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b" + "reference": "17c08b068176996a1d7db8d00ffae3c248267016" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f35241f45c30bcd9046af2bb200a7086f70e1d6b", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b", + "url": "https://api.github.com/repos/symfony/string/zipball/17c08b068176996a1d7db8d00ffae3c248267016", + "reference": "17c08b068176996a1d7db8d00ffae3c248267016", "shasum": "" }, "require": { @@ -4020,7 +3741,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.1.3" + "source": "https://github.com/symfony/string/tree/v6.1.5" }, "funding": [ { @@ -4036,7 +3757,7 @@ "type": "tidelift" } ], - "time": "2022-07-27T15:50:51+00:00" + "time": "2022-09-02T08:05:20+00:00" }, { "name": "theseer/tokenizer", @@ -4087,64 +3808,6 @@ } ], "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], diff --git a/config/config.local.php.dist b/config/config.local.php.dist deleted file mode 100644 index 25b8c09..0000000 --- a/config/config.local.php.dist +++ /dev/null @@ -1,8 +0,0 @@ - 'prod', - 'logs_password' => 'change-me', -]; diff --git a/config/config.php b/config/config.php index 656abf8..57d426f 100644 --- a/config/config.php +++ b/config/config.php @@ -3,9 +3,6 @@ declare(strict_types=1); return [ - 'app_env' => 'dev', - 'logs_password' => 'placeholder', - 'routes' => require __DIR__ . '/routes.php', - 'commands' => require __DIR__ . '/commands.php', - 'services' => require __DIR__ . '/services.php', + 'app_env' => $_ENV['APP_ENV'] ?? 'prod', + 'root_dir' => dirname(__DIR__), ]; diff --git a/config/routes.php b/config/routes.php index 092f392..1e40e69 100644 --- a/config/routes.php +++ b/config/routes.php @@ -8,51 +8,61 @@ [ 'route' => '/', 'methods' => ['GET'], - 'controller' => [Controller\IndexController::class, 'index'], + 'controller' => Controller\IndexController::class, + 'action' => 'index', ], [ 'route' => '/profile/{world}/{id}', 'methods' => ['GET'], - 'controller' => [Controller\ProfileController::class, 'profile'], + 'controller' => Controller\ProfileController::class, + 'action' => 'profile', ], [ 'route' => '/playtime', 'methods' => ['GET'], - 'controller' => [Controller\PlaytimeController::class, 'playtime'], + 'controller' => Controller\PlaytimeController::class, + 'action' => 'playtime', ], [ 'route' => '/changes/names', 'methods' => ['GET'], - 'controller' => [Controller\ChangeController::class, 'name'], + 'controller' => Controller\ChangeController::class, + 'action' => 'name', ], [ 'route' => '/images/ranking', 'methods' => ['GET'], - 'controller' => [Controller\ImageController::class, 'ranking'], + 'controller' => Controller\ImageController::class, + 'action' => 'ranking', ], [ 'route' => '/images/{world}-ranking.png', 'methods' => ['GET'], - 'controller' => [Controller\ImageController::class, 'image'], + 'controller' => Controller\ImageController::class, + 'action' => 'image', ], [ 'route' => '/ping', 'methods' => ['GET'], - 'controller' => [Controller\PingController::class, 'ping'], + 'controller' => Controller\PingController::class, + 'action' => 'ping', ], [ 'route' => '/admin/logs', 'methods' => ['GET'], - 'controller' => [Controller\LogController::class, 'logs'], + 'controller' => Controller\LogController::class, + 'action' => 'logs', ], [ 'route' => '/login', 'methods' => ['GET', 'POST'], - 'controller' => [Controller\SecurityController::class, 'login'], + 'controller' => Controller\SecurityController::class, + 'action' => 'login', ], [ 'route' => '/logout', 'methods' => ['GET', 'POST'], - 'controller' => [Controller\SecurityController::class, 'logout'], + 'controller' => Controller\SecurityController::class, + 'action' => 'logout', ], ]; diff --git a/config/services.php b/config/services.php index 0599106..c711022 100644 --- a/config/services.php +++ b/config/services.php @@ -10,7 +10,6 @@ use Jesperbeisner\Fwstats\Repository; use Jesperbeisner\Fwstats\Service; use Jesperbeisner\Fwstats\Stdlib; -use Psr\Log\LoggerInterface; return [ // Controller @@ -64,14 +63,11 @@ Repository\AchievementRepository::class => Repository\Factory\RepositoryFactory::class, Repository\LogRepository::class => Repository\Factory\RepositoryFactory::class, - - Repository\UserRepository::class => Repository\Factory\UserRepositoryFactory::class, + Repository\UserRepository::class => Repository\Factory\RepositoryFactory::class, // Stdlib - PDO::class => Stdlib\Factory\PdoFactory::class, - LoggerInterface::class => Stdlib\Factory\LoggerFactory::class, Stdlib\Request::class => Stdlib\Factory\RequestFactory::class, - Stdlib\Router::class => Stdlib\Factory\RouterFactory::class, + Stdlib\Interface\LoggerInterface::class => Stdlib\Factory\LoggerFactory::class, Stdlib\Interface\SessionInterface::class => Stdlib\Factory\SessionFactory::class, Stdlib\Interface\DatabaseInterface::class => Stdlib\Factory\DatabaseFactory::class, ]; diff --git a/data/database/.gitkeep b/data/database/.gitkeep old mode 100644 new mode 100755 diff --git a/data/logs/.gitkeep b/data/logs/.gitkeep old mode 100644 new mode 100755 diff --git a/src/Action/Factory/CreateUserActionFactory.php b/src/Action/Factory/CreateUserActionFactory.php index ab63ae3..db9a92c 100644 --- a/src/Action/Factory/CreateUserActionFactory.php +++ b/src/Action/Factory/CreateUserActionFactory.php @@ -6,18 +6,16 @@ use Jesperbeisner\Fwstats\Action\CreateUserAction; use Jesperbeisner\Fwstats\Repository\UserRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class CreateUserActionFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): CreateUserAction + public function build(ContainerInterface $container, string $serviceId): CreateUserAction { /** @var UserRepository $userRepository */ - $userRepository = $serviceContainer->get(UserRepository::class); + $userRepository = $container->get(UserRepository::class); - return new CreateUserAction( - $userRepository, - ); + return new CreateUserAction($userRepository); } } diff --git a/src/App.php b/src/App.php index 5eb9ddd..01bcebe 100644 --- a/src/App.php +++ b/src/App.php @@ -9,37 +9,41 @@ use Jesperbeisner\Fwstats\Controller\AbstractController; use Jesperbeisner\Fwstats\Model\Log; use Jesperbeisner\Fwstats\Repository\LogRepository; +use Jesperbeisner\Fwstats\Stdlib\Config; use Jesperbeisner\Fwstats\Stdlib\Exception\NotFoundException; use Jesperbeisner\Fwstats\Stdlib\Exception\RedirectException; use Jesperbeisner\Fwstats\Stdlib\Exception\UnauthorizedException; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\LoggerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\ResponseInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\SessionInterface; use Jesperbeisner\Fwstats\Stdlib\Request; use Jesperbeisner\Fwstats\Stdlib\Response\HtmlResponse; use Jesperbeisner\Fwstats\Stdlib\Router; -use Jesperbeisner\Fwstats\Stdlib\ServiceContainer; -use Psr\Log\LoggerInterface; use Throwable; final class App { public function __construct( - private readonly ServiceContainer $serviceContainer, + private readonly ContainerInterface $container, ) { $this->registerExceptionHandler(); } public function run(): never { - $this->logRequestToDatabase(); + /** @var Request $request */ + $request = $this->container->get(Request::class); + + $this->logRequestToDatabase($request); /** @var SessionInterface $session */ - $session = $this->serviceContainer->get(SessionInterface::class); + $session = $this->container->get(SessionInterface::class); $session->start(); /** @var Router $router */ - $router = $this->serviceContainer->get(Router::class); - $routeResult = $router->match(); + $router = $this->container->get(Router::class); + $routeResult = $router->match($request); if ($routeResult[0] === Dispatcher::NOT_FOUND) { $response = new HtmlResponse('error.phtml', ['message' => '404 - Page not found'], 404); @@ -56,7 +60,7 @@ public function run(): never } /** @var Request $request */ - $request = $this->serviceContainer->get(Request::class); + $request = $this->container->get(Request::class); /** @var array $routeParameters */ $routeParameters = $routeResult[2]; @@ -69,7 +73,7 @@ public function run(): never $controllerAction = $handler[1]; /** @var AbstractController $controller */ - $controller = $this->serviceContainer->get($controllerClassName); + $controller = $this->container->get($controllerClassName); try { /** @var ResponseInterface $response */ @@ -103,15 +107,15 @@ public function run(): never private function registerExceptionHandler(): void { set_exception_handler(function (Throwable $e): never { - /** @var string $appEnv */ - $appEnv = $this->serviceContainer->get('appEnv'); + /** @var Config $config */ + $config = $this->container->get(Config::class); - if ($appEnv === 'prod') { - /** @var LoggerInterface $logger */ - $logger = $this->serviceContainer->get(LoggerInterface::class); + /** @var LoggerInterface $logger */ + $logger = $this->container->get(LoggerInterface::class); - $logger->error($e->getMessage()); + $logger->error($e->getMessage()); + if ($config->getAppEnv() === 'prod') { (new HtmlResponse('error.phtml', ['message' => '500 - Server error'], 500))->send(); } @@ -119,13 +123,10 @@ private function registerExceptionHandler(): void }); } - private function logRequestToDatabase(): void + private function logRequestToDatabase(Request $request): void { - /** @var Request $request */ - $request = $this->serviceContainer->get(Request::class); - /** @var LogRepository $logRepository */ - $logRepository = $this->serviceContainer->get(LogRepository::class); + $logRepository = $this->container->get(LogRepository::class); $log = new Log($request->fullUri, new DateTimeImmutable()); diff --git a/src/Command/DatabaseFixtureCommand.php b/src/Command/DatabaseFixtureCommand.php index 2cdb4e0..131141c 100644 --- a/src/Command/DatabaseFixtureCommand.php +++ b/src/Command/DatabaseFixtureCommand.php @@ -21,6 +21,7 @@ use Jesperbeisner\Fwstats\Repository\PlayerRaceHistoryRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; use Jesperbeisner\Fwstats\Repository\UserRepository; +use Jesperbeisner\Fwstats\Stdlib\Config; final class DatabaseFixtureCommand extends AbstractCommand { @@ -28,8 +29,7 @@ final class DatabaseFixtureCommand extends AbstractCommand public static string $description = 'Loads fixtures for local development into the database.'; public function __construct( - private readonly string $appEnv, - private readonly string $rootDir, + private readonly Config $config, private readonly PlayerRepository $playerRepository, private readonly ClanRepository $clanRepository, private readonly PlayerActiveSecondRepository $playerActiveSecondRepository, @@ -44,7 +44,7 @@ public function __construct( public function execute(): int { - if ($this->appEnv !== 'dev') { + if ($this->config->getAppEnv() !== 'dev') { $this->writeLine("The 'app:database-fixture' command can only be executed in the dev environment."); return self::FAILURE; @@ -84,7 +84,7 @@ public function execute(): int private function createPlayers(): void { - $playersFixtureData = require $this->rootDir . '/data/fixtures/players.php'; + $playersFixtureData = require $this->config->getRootDir() . '/data/fixtures/players.php'; $this->playerRepository->deleteAll(); @@ -120,7 +120,7 @@ private function createPlayers(): void private function createClans(): void { - $clansFixtureData = require $this->rootDir . '/data/fixtures/clans.php'; + $clansFixtureData = require $this->config->getRootDir() . '/data/fixtures/clans.php'; $this->clanRepository->deleteAll(); @@ -157,7 +157,7 @@ private function createClans(): void private function createPlayerPlaytimes(): void { - $playerPlaytimesFixtureData = require $this->rootDir . '/data/fixtures/player-playtimes.php'; + $playerPlaytimesFixtureData = require $this->config->getRootDir() . '/data/fixtures/player-playtimes.php'; $this->playerActiveSecondRepository->deleteAll(); @@ -182,7 +182,7 @@ private function createPlayerPlaytimes(): void private function createPlayerNameHistories(): void { - $playerNameHistoriesFixtureData = require $this->rootDir . '/data/fixtures/player-name-histories.php'; + $playerNameHistoriesFixtureData = require $this->config->getRootDir() . '/data/fixtures/player-name-histories.php'; $this->playerNameHistoryRepository->deleteAll(); @@ -209,7 +209,7 @@ private function createPlayerNameHistories(): void private function createPlayerRaceHistories(): void { - $playerRaceHistoriesFixtureData = require $this->rootDir . '/data/fixtures/player-race-histories.php'; + $playerRaceHistoriesFixtureData = require $this->config->getRootDir() . '/data/fixtures/player-race-histories.php'; $this->playerRaceHistoryRepository->deleteAll(); @@ -236,7 +236,7 @@ private function createPlayerRaceHistories(): void private function createPlayerProfessionHistories(): void { - $playerProfessionHistoriesFixtureData = require $this->rootDir . '/data/fixtures/player-profession-histories.php'; + $playerProfessionHistoriesFixtureData = require $this->config->getRootDir() . '/data/fixtures/player-profession-histories.php'; $this->playerProfessionHistoryRepository->deleteAll(); diff --git a/src/Command/Factory/AppCommandFactory.php b/src/Command/Factory/AppCommandFactory.php index f98b5d7..c211acc 100644 --- a/src/Command/Factory/AppCommandFactory.php +++ b/src/Command/Factory/AppCommandFactory.php @@ -10,27 +10,27 @@ use Jesperbeisner\Fwstats\Importer\ClanImporter; use Jesperbeisner\Fwstats\Importer\PlayerImporter; use Jesperbeisner\Fwstats\Importer\PlaytimeImporter; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class AppCommandFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): AppCommand + public function build(ContainerInterface $container, string $serviceId): AppCommand { /** @var ClanImporter $clanImporter */ - $clanImporter = $serviceContainer->get(ClanImporter::class); + $clanImporter = $container->get(ClanImporter::class); /** @var PlayerImporter $playerImporter */ - $playerImporter = $serviceContainer->get(PlayerImporter::class); + $playerImporter = $container->get(PlayerImporter::class); /** @var AchievementImporter $achievementImporter */ - $achievementImporter = $serviceContainer->get(AchievementImporter::class); + $achievementImporter = $container->get(AchievementImporter::class); /** @var RankingImageService $rankingImageService */ - $rankingImageService = $serviceContainer->get(RankingImageService::class); + $rankingImageService = $container->get(RankingImageService::class); /** @var PlaytimeImporter $playtimeImporter */ - $playtimeImporter = $serviceContainer->get(PlaytimeImporter::class); + $playtimeImporter = $container->get(PlaytimeImporter::class); return new AppCommand( $clanImporter, diff --git a/src/Command/Factory/CreateUserCommandFactory.php b/src/Command/Factory/CreateUserCommandFactory.php index 5308141..7c4d42e 100644 --- a/src/Command/Factory/CreateUserCommandFactory.php +++ b/src/Command/Factory/CreateUserCommandFactory.php @@ -6,18 +6,16 @@ use Jesperbeisner\Fwstats\Action\CreateUserAction; use Jesperbeisner\Fwstats\Command\CreateUserCommand; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class CreateUserCommandFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): CreateUserCommand + public function build(ContainerInterface $container, string $serviceId): CreateUserCommand { /** @var CreateUserAction $createUserAction */ - $createUserAction = $serviceContainer->get(CreateUserAction::class); + $createUserAction = $container->get(CreateUserAction::class); - return new CreateUserCommand( - $createUserAction, - ); + return new CreateUserCommand($createUserAction); } } diff --git a/src/Command/Factory/DatabaseFixtureCommandFactory.php b/src/Command/Factory/DatabaseFixtureCommandFactory.php index 22dcee6..8531483 100644 --- a/src/Command/Factory/DatabaseFixtureCommandFactory.php +++ b/src/Command/Factory/DatabaseFixtureCommandFactory.php @@ -14,49 +14,46 @@ use Jesperbeisner\Fwstats\Repository\PlayerRaceHistoryRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; use Jesperbeisner\Fwstats\Repository\UserRepository; +use Jesperbeisner\Fwstats\Stdlib\Config; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class DatabaseFixtureCommandFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): DatabaseFixtureCommand + public function build(ContainerInterface $container, string $serviceId): DatabaseFixtureCommand { - /** @var string $appEnv */ - $appEnv = $serviceContainer->get('appEnv'); - - /** @var string $rootDir */ - $rootDir = $serviceContainer->get('rootDir'); + /** @var Config $config */ + $config = $container->get(Config::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var ClanRepository $clanRepository */ - $clanRepository = $serviceContainer->get(ClanRepository::class); + $clanRepository = $container->get(ClanRepository::class); /** @var PlayerActiveSecondRepository $playerActiveSecondRepository */ - $playerActiveSecondRepository = $serviceContainer->get(PlayerActiveSecondRepository::class); + $playerActiveSecondRepository = $container->get(PlayerActiveSecondRepository::class); /** @var PlayerNameHistoryRepository $playerNameHistoryRepository */ - $playerNameHistoryRepository = $serviceContainer->get(PlayerNameHistoryRepository::class); + $playerNameHistoryRepository = $container->get(PlayerNameHistoryRepository::class); /** @var PlayerRaceHistoryRepository $playerRaceHistoryRepository */ - $playerRaceHistoryRepository = $serviceContainer->get(PlayerRaceHistoryRepository::class); + $playerRaceHistoryRepository = $container->get(PlayerRaceHistoryRepository::class); /** @var PlayerProfessionHistoryRepository $playerProfessionHistoryRepository */ - $playerProfessionHistoryRepository = $serviceContainer->get(PlayerProfessionHistoryRepository::class); + $playerProfessionHistoryRepository = $container->get(PlayerProfessionHistoryRepository::class); /** @var RankingImageService $rankingImageService */ - $rankingImageService = $serviceContainer->get(RankingImageService::class); + $rankingImageService = $container->get(RankingImageService::class); /** @var UserRepository $userRepository */ - $userRepository = $serviceContainer->get(UserRepository::class); + $userRepository = $container->get(UserRepository::class); /** @var CreateUserAction $createUserAction */ - $createUserAction = $serviceContainer->get(CreateUserAction::class); + $createUserAction = $container->get(CreateUserAction::class); return new DatabaseFixtureCommand( - $appEnv, - $rootDir, + $config, $playerRepository, $clanRepository, $playerActiveSecondRepository, diff --git a/src/Command/Factory/DatabaseMigrationCommandFactory.php b/src/Command/Factory/DatabaseMigrationCommandFactory.php index 0179637..7867034 100644 --- a/src/Command/Factory/DatabaseMigrationCommandFactory.php +++ b/src/Command/Factory/DatabaseMigrationCommandFactory.php @@ -6,15 +6,15 @@ use Jesperbeisner\Fwstats\Command\DatabaseMigrationCommand; use Jesperbeisner\Fwstats\Repository\MigrationRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class DatabaseMigrationCommandFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): DatabaseMigrationCommand + public function build(ContainerInterface $container, string $serviceId): DatabaseMigrationCommand { /** @var MigrationRepository $migrationRepository */ - $migrationRepository = $serviceContainer->get(MigrationRepository::class); + $migrationRepository = $container->get(MigrationRepository::class); return new DatabaseMigrationCommand($migrationRepository); } diff --git a/src/Controller/Factory/ChangeControllerFactory.php b/src/Controller/Factory/ChangeControllerFactory.php index 1eb6a22..9877469 100644 --- a/src/Controller/Factory/ChangeControllerFactory.php +++ b/src/Controller/Factory/ChangeControllerFactory.php @@ -6,15 +6,15 @@ use Jesperbeisner\Fwstats\Controller\ChangeController; use Jesperbeisner\Fwstats\Repository\PlayerNameHistoryRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class ChangeControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): ChangeController + public function build(ContainerInterface $container, string $serviceId): ChangeController { /** @var PlayerNameHistoryRepository $playerNameHistoryRepository */ - $playerNameHistoryRepository = $serviceContainer->get(PlayerNameHistoryRepository::class); + $playerNameHistoryRepository = $container->get(PlayerNameHistoryRepository::class); return new ChangeController($playerNameHistoryRepository); } diff --git a/src/Controller/Factory/ImageControllerFactory.php b/src/Controller/Factory/ImageControllerFactory.php index 15bfb8e..a1acdc0 100644 --- a/src/Controller/Factory/ImageControllerFactory.php +++ b/src/Controller/Factory/ImageControllerFactory.php @@ -5,22 +5,23 @@ namespace Jesperbeisner\Fwstats\Controller\Factory; use Jesperbeisner\Fwstats\Controller\ImageController; +use Jesperbeisner\Fwstats\Stdlib\Config; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Request; -use Psr\Container\ContainerInterface; final class ImageControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): ImageController + public function build(ContainerInterface $container, string $serviceId): ImageController { - /** @var string $rootDir */ - $rootDir = $serviceContainer->get('rootDir'); + /** @var Config $config */ + $config = $container->get(Config::class); /** @var Request $request */ - $request = $serviceContainer->get(Request::class); + $request = $container->get(Request::class); return new ImageController( - $rootDir, + $config, $request, ); } diff --git a/src/Controller/Factory/IndexControllerFactory.php b/src/Controller/Factory/IndexControllerFactory.php index 2b8940f..1a78e09 100644 --- a/src/Controller/Factory/IndexControllerFactory.php +++ b/src/Controller/Factory/IndexControllerFactory.php @@ -7,22 +7,22 @@ use Jesperbeisner\Fwstats\Controller\IndexController; use Jesperbeisner\Fwstats\Repository\ClanRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Request; -use Psr\Container\ContainerInterface; final class IndexControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): IndexController + public function build(ContainerInterface $container, string $serviceId): IndexController { /** @var Request $request */ - $request = $serviceContainer->get(Request::class); + $request = $container->get(Request::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var ClanRepository $clanRepository */ - $clanRepository = $serviceContainer->get(ClanRepository::class); + $clanRepository = $container->get(ClanRepository::class); return new IndexController( $request, diff --git a/src/Controller/Factory/LogControllerFactory.php b/src/Controller/Factory/LogControllerFactory.php index a421fd5..c45068b 100644 --- a/src/Controller/Factory/LogControllerFactory.php +++ b/src/Controller/Factory/LogControllerFactory.php @@ -6,19 +6,19 @@ use Jesperbeisner\Fwstats\Controller\LogController; use Jesperbeisner\Fwstats\Repository\LogRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\SessionInterface; -use Psr\Container\ContainerInterface; final class LogControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): LogController + public function build(ContainerInterface $container, string $serviceId): LogController { /** @var SessionInterface $session */ - $session = $serviceContainer->get(SessionInterface::class); + $session = $container->get(SessionInterface::class); /** @var LogRepository $logRepository */ - $logRepository = $serviceContainer->get(LogRepository::class); + $logRepository = $container->get(LogRepository::class); return new LogController( $session, diff --git a/src/Controller/Factory/PingControllerFactory.php b/src/Controller/Factory/PingControllerFactory.php index 3d3c659..24395a0 100644 --- a/src/Controller/Factory/PingControllerFactory.php +++ b/src/Controller/Factory/PingControllerFactory.php @@ -5,12 +5,12 @@ namespace Jesperbeisner\Fwstats\Controller\Factory; use Jesperbeisner\Fwstats\Controller\PingController; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class PingControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PingController + public function build(ContainerInterface $container, string $serviceId): PingController { return new PingController(); } diff --git a/src/Controller/Factory/PlaytimeControllerFactory.php b/src/Controller/Factory/PlaytimeControllerFactory.php index 05fa8b5..02d170e 100644 --- a/src/Controller/Factory/PlaytimeControllerFactory.php +++ b/src/Controller/Factory/PlaytimeControllerFactory.php @@ -6,15 +6,15 @@ use Jesperbeisner\Fwstats\Controller\PlaytimeController; use Jesperbeisner\Fwstats\Repository\PlayerActiveSecondRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class PlaytimeControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PlaytimeController + public function build(ContainerInterface $container, string $serviceId): PlaytimeController { /** @var PlayerActiveSecondRepository $playerActiveSecondRepository */ - $playerActiveSecondRepository = $serviceContainer->get(PlayerActiveSecondRepository::class); + $playerActiveSecondRepository = $container->get(PlayerActiveSecondRepository::class); return new PlaytimeController($playerActiveSecondRepository); } diff --git a/src/Controller/Factory/ProfileControllerFactory.php b/src/Controller/Factory/ProfileControllerFactory.php index f812741..82006fa 100644 --- a/src/Controller/Factory/ProfileControllerFactory.php +++ b/src/Controller/Factory/ProfileControllerFactory.php @@ -10,31 +10,31 @@ use Jesperbeisner\Fwstats\Repository\PlayerRaceHistoryRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; use Jesperbeisner\Fwstats\Service\PlaytimeService; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Request; -use Psr\Container\ContainerInterface; final class ProfileControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): ProfileController + public function build(ContainerInterface $container, string $serviceId): ProfileController { /** @var Request $request */ - $request = $serviceContainer->get(Request::class); + $request = $container->get(Request::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var PlaytimeService $playtimeService */ - $playtimeService = $serviceContainer->get(PlaytimeService::class); + $playtimeService = $container->get(PlaytimeService::class); /** @var PlayerNameHistoryRepository $playerNameHistoryRepository */ - $playerNameHistoryRepository = $serviceContainer->get(PlayerNameHistoryRepository::class); + $playerNameHistoryRepository = $container->get(PlayerNameHistoryRepository::class); /** @var PlayerRaceHistoryRepository $playerRaceHistoryRepository */ - $playerRaceHistoryRepository = $serviceContainer->get(PlayerRaceHistoryRepository::class); + $playerRaceHistoryRepository = $container->get(PlayerRaceHistoryRepository::class); /** @var PlayerProfessionHistoryRepository $playerProfessionHistoryRepository */ - $playerProfessionHistoryRepository = $serviceContainer->get(PlayerProfessionHistoryRepository::class); + $playerProfessionHistoryRepository = $container->get(PlayerProfessionHistoryRepository::class); return new ProfileController( $request, diff --git a/src/Controller/Factory/SecurityControllerFactory.php b/src/Controller/Factory/SecurityControllerFactory.php index 009d98c..3192f22 100644 --- a/src/Controller/Factory/SecurityControllerFactory.php +++ b/src/Controller/Factory/SecurityControllerFactory.php @@ -6,23 +6,23 @@ use Jesperbeisner\Fwstats\Controller\SecurityController; use Jesperbeisner\Fwstats\Repository\UserRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\SessionInterface; use Jesperbeisner\Fwstats\Stdlib\Request; -use Psr\Container\ContainerInterface; final class SecurityControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): SecurityController + public function build(ContainerInterface $container, string $serviceId): SecurityController { /** @var Request $request */ - $request = $serviceContainer->get(Request::class); + $request = $container->get(Request::class); /** @var SessionInterface $session */ - $session = $serviceContainer->get(SessionInterface::class); + $session = $container->get(SessionInterface::class); /** @var UserRepository $userRepository */ - $userRepository = $serviceContainer->get(UserRepository::class); + $userRepository = $container->get(UserRepository::class); return new SecurityController( $request, diff --git a/src/Controller/ImageController.php b/src/Controller/ImageController.php index ffea650..475a17a 100644 --- a/src/Controller/ImageController.php +++ b/src/Controller/ImageController.php @@ -5,6 +5,7 @@ namespace Jesperbeisner\Fwstats\Controller; use Jesperbeisner\Fwstats\Enum\WorldEnum; +use Jesperbeisner\Fwstats\Stdlib\Config; use Jesperbeisner\Fwstats\Stdlib\Exception\NotFoundException; use Jesperbeisner\Fwstats\Stdlib\Interface\ResponseInterface; use Jesperbeisner\Fwstats\Stdlib\Request; @@ -16,7 +17,7 @@ final class ImageController extends AbstractController private const RANKING_IMAGE = '/data/images/[WORLD]-ranking.png'; public function __construct( - private readonly string $rootDir, + private readonly Config $config, private readonly Request $request, ) { } @@ -30,10 +31,11 @@ public function image(): ResponseInterface { /** @var string $worldString */ $worldString = $this->request->getRouteParameter('world'); + if (null === $world = WorldEnum::tryFrom($worldString)) { throw new NotFoundException(); } - return new ImageResponse(str_replace('[WORLD]', $world->value, $this->rootDir . self::RANKING_IMAGE)); + return new ImageResponse(str_replace('[WORLD]', $world->value, $this->config->getRootDir() . self::RANKING_IMAGE)); } } diff --git a/src/ImageService/AbstractImageService.php b/src/ImageService/AbstractImageService.php index f1853ca..44286bb 100644 --- a/src/ImageService/AbstractImageService.php +++ b/src/ImageService/AbstractImageService.php @@ -6,6 +6,7 @@ use GdImage; use Jesperbeisner\Fwstats\ImageService\Exception\ImageException; +use Jesperbeisner\Fwstats\Stdlib\Config; abstract class AbstractImageService implements ImageServiceInterface { @@ -18,7 +19,7 @@ abstract class AbstractImageService implements ImageServiceInterface protected array $colors = []; public function __construct( - private readonly string $rootDir, + private readonly Config $config, ) { } @@ -51,7 +52,7 @@ protected function write(string $text, int $x, int $y, int $size = null, int $co $size = $size ?? 14; $color = $color ?? $this->colorBlack(); - if (false === imagettftext($this->image, $size, $angle, $x, $y, $color, $this->rootDir . self::ROBOTO_FONT, $text)) { + if (false === imagettftext($this->image, $size, $angle, $x, $y, $color, $this->config->getRootDir() . self::ROBOTO_FONT, $text)) { throw new ImageException('Could not write to image.'); } } @@ -116,6 +117,6 @@ protected function colorWhite(): int protected function getImageFolder(): string { - return $this->rootDir . self::IMAGE_FOLDER; + return $this->config->getRootDir() . self::IMAGE_FOLDER; } } diff --git a/src/ImageService/Factory/RankingImageServiceFactory.php b/src/ImageService/Factory/RankingImageServiceFactory.php index 85f1362..9f115e4 100644 --- a/src/ImageService/Factory/RankingImageServiceFactory.php +++ b/src/ImageService/Factory/RankingImageServiceFactory.php @@ -7,24 +7,25 @@ use Jesperbeisner\Fwstats\ImageService\RankingImageService; use Jesperbeisner\Fwstats\Repository\ClanRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; +use Jesperbeisner\Fwstats\Stdlib\Config; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class RankingImageServiceFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): RankingImageService + public function build(ContainerInterface $container, string $serviceId): RankingImageService { - /** @var string $rootDir */ - $rootDir = $serviceContainer->get('rootDir'); + /** @var Config $config */ + $config = $container->get(Config::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var ClanRepository $clanRepository */ - $clanRepository = $serviceContainer->get(ClanRepository::class); + $clanRepository = $container->get(ClanRepository::class); return new RankingImageService( - $rootDir, + $config, $playerRepository, $clanRepository, ); diff --git a/src/ImageService/RankingImageService.php b/src/ImageService/RankingImageService.php index 4eb4e8e..4a7c8e0 100644 --- a/src/ImageService/RankingImageService.php +++ b/src/ImageService/RankingImageService.php @@ -10,15 +10,16 @@ use Jesperbeisner\Fwstats\ImageService\Exception\ImageException; use Jesperbeisner\Fwstats\Repository\ClanRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; +use Jesperbeisner\Fwstats\Stdlib\Config; final class RankingImageService extends AbstractImageService { public function __construct( - string $rootDir, + Config $config, private readonly PlayerRepository $playerRepository, private readonly ClanRepository $clanRepository, ) { - parent::__construct($rootDir); + parent::__construct($config); } public function create(WorldEnum $world): void diff --git a/src/Importer/Factory/AchievementImporterFactory.php b/src/Importer/Factory/AchievementImporterFactory.php index 71c5081..9760bd4 100644 --- a/src/Importer/Factory/AchievementImporterFactory.php +++ b/src/Importer/Factory/AchievementImporterFactory.php @@ -8,21 +8,21 @@ use Jesperbeisner\Fwstats\Repository\AchievementRepository; use Jesperbeisner\Fwstats\Repository\PlayerRepository; use Jesperbeisner\Fwstats\Service\Interface\FreewarDumpServiceInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class AchievementImporterFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): AchievementImporter + public function build(ContainerInterface $container, string $serviceId): AchievementImporter { /** @var FreewarDumpServiceInterface $freewarDumpService */ - $freewarDumpService = $serviceContainer->get(FreewarDumpServiceInterface::class); + $freewarDumpService = $container->get(FreewarDumpServiceInterface::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var AchievementRepository $achievementRepository */ - $achievementRepository = $serviceContainer->get(AchievementRepository::class); + $achievementRepository = $container->get(AchievementRepository::class); return new AchievementImporter( $freewarDumpService, diff --git a/src/Importer/Factory/ClanImporterFactory.php b/src/Importer/Factory/ClanImporterFactory.php index 800a48a..d1b9bf8 100644 --- a/src/Importer/Factory/ClanImporterFactory.php +++ b/src/Importer/Factory/ClanImporterFactory.php @@ -10,27 +10,27 @@ use Jesperbeisner\Fwstats\Repository\ClanNameHistoryRepository; use Jesperbeisner\Fwstats\Repository\ClanRepository; use Jesperbeisner\Fwstats\Service\Interface\FreewarDumpServiceInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class ClanImporterFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): ClanImporter + public function build(ContainerInterface $container, string $serviceId): ClanImporter { /** @var FreewarDumpServiceInterface $freewarDumpService */ - $freewarDumpService = $serviceContainer->get(FreewarDumpServiceInterface::class); + $freewarDumpService = $container->get(FreewarDumpServiceInterface::class); /** @var ClanRepository $clanRepository */ - $clanRepository = $serviceContainer->get(ClanRepository::class); + $clanRepository = $container->get(ClanRepository::class); /** @var ClanNameHistoryRepository $clanNamingHistoryRepository */ - $clanNamingHistoryRepository = $serviceContainer->get(ClanNameHistoryRepository::class); + $clanNamingHistoryRepository = $container->get(ClanNameHistoryRepository::class); /** @var ClanDeletedHistoryRepository $clanDeletedHistoryRepository */ - $clanDeletedHistoryRepository = $serviceContainer->get(ClanDeletedHistoryRepository::class); + $clanDeletedHistoryRepository = $container->get(ClanDeletedHistoryRepository::class); /** @var ClanCreatedHistoryRepository $clanCreatedHistoryRepository */ - $clanCreatedHistoryRepository = $serviceContainer->get(ClanCreatedHistoryRepository::class); + $clanCreatedHistoryRepository = $container->get(ClanCreatedHistoryRepository::class); return new ClanImporter( $freewarDumpService, diff --git a/src/Importer/Factory/PlayerImporterFactory.php b/src/Importer/Factory/PlayerImporterFactory.php index d8b7430..23204b8 100644 --- a/src/Importer/Factory/PlayerImporterFactory.php +++ b/src/Importer/Factory/PlayerImporterFactory.php @@ -14,39 +14,39 @@ use Jesperbeisner\Fwstats\Repository\PlayerStatusHistoryRepository; use Jesperbeisner\Fwstats\Service\Interface\FreewarDumpServiceInterface; use Jesperbeisner\Fwstats\Service\PlayerStatusService; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class PlayerImporterFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PlayerImporter + public function build(ContainerInterface $container, string $serviceId): PlayerImporter { /** @var FreewarDumpServiceInterface $freewarDumpService */ - $freewarDumpService = $serviceContainer->get(FreewarDumpServiceInterface::class); + $freewarDumpService = $container->get(FreewarDumpServiceInterface::class); /** @var ClanRepository $clanRepository */ - $clanRepository = $serviceContainer->get(ClanRepository::class); + $clanRepository = $container->get(ClanRepository::class); /** @var PlayerRepository $playerRepository */ - $playerRepository = $serviceContainer->get(PlayerRepository::class); + $playerRepository = $container->get(PlayerRepository::class); /** @var PlayerNameHistoryRepository $playerNameHistoryRepository */ - $playerNameHistoryRepository = $serviceContainer->get(PlayerNameHistoryRepository::class); + $playerNameHistoryRepository = $container->get(PlayerNameHistoryRepository::class); /** @var PlayerRaceHistoryRepository $playerRaceHistoryRepository */ - $playerRaceHistoryRepository = $serviceContainer->get(PlayerRaceHistoryRepository::class); + $playerRaceHistoryRepository = $container->get(PlayerRaceHistoryRepository::class); /** @var PlayerClanHistoryRepository $playerClanHistoryRepository */ - $playerClanHistoryRepository = $serviceContainer->get(PlayerClanHistoryRepository::class); + $playerClanHistoryRepository = $container->get(PlayerClanHistoryRepository::class); /** @var PlayerProfessionHistoryRepository $playerProfessionHistoryRepository */ - $playerProfessionHistoryRepository = $serviceContainer->get(PlayerProfessionHistoryRepository::class); + $playerProfessionHistoryRepository = $container->get(PlayerProfessionHistoryRepository::class); /** @var PlayerStatusHistoryRepository $playerStatusHistoryRepository */ - $playerStatusHistoryRepository = $serviceContainer->get(PlayerStatusHistoryRepository::class); + $playerStatusHistoryRepository = $container->get(PlayerStatusHistoryRepository::class); /** @var PlayerStatusService $playerStatusService */ - $playerStatusService = $serviceContainer->get(PlayerStatusService::class); + $playerStatusService = $container->get(PlayerStatusService::class); return new PlayerImporter( $freewarDumpService, diff --git a/src/Importer/Factory/PlaytimeImporterFactory.php b/src/Importer/Factory/PlaytimeImporterFactory.php index ad1fabb..498c019 100644 --- a/src/Importer/Factory/PlaytimeImporterFactory.php +++ b/src/Importer/Factory/PlaytimeImporterFactory.php @@ -7,18 +7,18 @@ use Jesperbeisner\Fwstats\Importer\PlaytimeImporter; use Jesperbeisner\Fwstats\Repository\PlayerActiveSecondRepository; use Jesperbeisner\Fwstats\Service\Interface\FreewarDumpServiceInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; final class PlaytimeImporterFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PlaytimeImporter + public function build(ContainerInterface $container, string $serviceId): PlaytimeImporter { /** @var FreewarDumpServiceInterface $freewarDumpService */ - $freewarDumpService = $serviceContainer->get(FreewarDumpServiceInterface::class); + $freewarDumpService = $container->get(FreewarDumpServiceInterface::class); /** @var PlayerActiveSecondRepository $playerActiveSecondRepository */ - $playerActiveSecondRepository = $serviceContainer->get(PlayerActiveSecondRepository::class); + $playerActiveSecondRepository = $container->get(PlayerActiveSecondRepository::class); return new PlaytimeImporter( $freewarDumpService, diff --git a/src/Repository/AbstractRepository.php b/src/Repository/AbstractRepository.php index 6ccf5bd..1eae5f2 100644 --- a/src/Repository/AbstractRepository.php +++ b/src/Repository/AbstractRepository.php @@ -4,12 +4,12 @@ namespace Jesperbeisner\Fwstats\Repository; -use PDO; +use Jesperbeisner\Fwstats\Stdlib\Interface\DatabaseInterface; abstract class AbstractRepository { public function __construct( - protected readonly PDO $pdo, + protected readonly DatabaseInterface $database, ) { } } diff --git a/src/Repository/AchievementRepository.php b/src/Repository/AchievementRepository.php index a8b4d00..f0c7592 100644 --- a/src/Repository/AchievementRepository.php +++ b/src/Repository/AchievementRepository.php @@ -8,28 +8,34 @@ use Jesperbeisner\Fwstats\Model\Achievement; use Jesperbeisner\Fwstats\Enum\WorldEnum; use Jesperbeisner\Fwstats\Model\Player; +use Jesperbeisner\Fwstats\Stdlib\Exception\DatabaseException; final class AchievementRepository extends AbstractRepository { - private string $table = 'achievements'; - public function findByPlayer(Player $player): ?Achievement { - $stmt = $this->pdo->prepare("SELECT * FROM $this->table WHERE world = :world AND player_id = :playerId"); - $stmt->execute(['world' => $player->world->value, 'playerId' => $player->playerId]); + $sql = "SELECT * FROM achievements WHERE world = :world AND player_id = :playerId"; + + $result = $this->database->select($sql, [ + 'world' => $player->world->value, + 'playerId' => $player->playerId, + ]); - if (false === $achievementRow = $stmt->fetch()) { + if (count($result) === 0) { return null; } - /** @var array $achievementRow */ - return $this->hydrateAchievement($achievementRow); + if (count($result) > 1) { + throw new DatabaseException('How can there be more than 1 achievement row for a single player?'); + } + + return $this->hydrateAchievement($result[0]); } public function insert(Achievement $achievement): void { $sql = <<table ( + INSERT INTO achievements ( world, player_id, fields_walked, fields_elixir, fields_run, fields_run_fast, npc_kills_gold, normal_npc_killed, phase_npc_killed, aggressive_npc_killed, invasion_npc_killed, unique_npc_killed, group_npc_killed, @@ -42,7 +48,7 @@ public function insert(Achievement $achievement): void ) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $achievement->world->value, 'playerId' => $achievement->playerId, 'fieldsWalked' => $achievement->fieldsWalked, @@ -65,20 +71,22 @@ public function insert(Achievement $achievement): void */ public function insertAchievements(WorldEnum $world, array $achievements): void { - $sql = "DELETE FROM $this->table WHERE world = :world"; + $sql = "DELETE FROM achievements WHERE world = :world"; try { - $this->pdo->beginTransaction(); + $this->database->beginTransaction(); - $this->pdo->prepare($sql)->execute(['world' => $world->value]); + $this->database->delete($sql, [ + 'world' => $world->value, + ]); foreach ($achievements as $achievement) { $this->insert($achievement); } - $this->pdo->commit(); + $this->database->commitTransaction(); } catch (Exception $e) { - $this->pdo->rollBack(); + $this->database->rollbackTransaction(); throw $e; } diff --git a/src/Repository/ClanCreatedHistoryRepository.php b/src/Repository/ClanCreatedHistoryRepository.php index 33a95fe..58e360e 100644 --- a/src/Repository/ClanCreatedHistoryRepository.php +++ b/src/Repository/ClanCreatedHistoryRepository.php @@ -8,16 +8,14 @@ final class ClanCreatedHistoryRepository extends AbstractRepository { - private string $table = 'clans_created_history'; - public function insert(ClanCreatedHistory $clanCreatedHistory): void { $sql = <<table (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points) + INSERT INTO clans_created_history (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points) VALUES (:world, :clanId, :shortcut, :name, :leaderId, :coLeaderId, :diplomatId, :warPoints) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $clanCreatedHistory->world->value, 'clanId' => $clanCreatedHistory->clanId, 'shortcut' => $clanCreatedHistory->shortcut, diff --git a/src/Repository/ClanDeletedHistoryRepository.php b/src/Repository/ClanDeletedHistoryRepository.php index 5ba0a8e..9f94ae4 100644 --- a/src/Repository/ClanDeletedHistoryRepository.php +++ b/src/Repository/ClanDeletedHistoryRepository.php @@ -8,16 +8,14 @@ final class ClanDeletedHistoryRepository extends AbstractRepository { - private string $table = 'clans_deleted_history'; - public function insert(ClanDeletedHistory $clanDeletedHistory): void { $sql = <<table (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points) + INSERT INTO clans_deleted_history (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points) VALUES (:world, :clanId, :shortcut, :name, :leaderId, :coLeaderId, :diplomatId, :warPoints) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $clanDeletedHistory->world->value, 'clanId' => $clanDeletedHistory->clanId, 'shortcut' => $clanDeletedHistory->shortcut, diff --git a/src/Repository/ClanNameHistoryRepository.php b/src/Repository/ClanNameHistoryRepository.php index 0a9d46e..455dfd7 100644 --- a/src/Repository/ClanNameHistoryRepository.php +++ b/src/Repository/ClanNameHistoryRepository.php @@ -8,16 +8,14 @@ final class ClanNameHistoryRepository extends AbstractRepository { - private string $table = 'clans_name_history'; - public function insert(ClanNameHistory $clanNameHistory): void { $sql = <<table} (world, clan_id, old_shortcut, new_shortcut, old_name, new_name) + INSERT INTO clans_name_history (world, clan_id, old_shortcut, new_shortcut, old_name, new_name) VALUES (:world, :clanId, :oldShortcut, :newShortcut, :oldName, :newName) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $clanNameHistory->world->value, 'clanId' => $clanNameHistory->clanId, 'oldShortcut' => $clanNameHistory->oldShortcut, diff --git a/src/Repository/ClanRepository.php b/src/Repository/ClanRepository.php index 773adc2..dc4eb14 100644 --- a/src/Repository/ClanRepository.php +++ b/src/Repository/ClanRepository.php @@ -11,18 +11,19 @@ final class ClanRepository extends AbstractRepository { - private string $table = 'clans'; - /** * @return Clan[] */ public function findAllByWorld(WorldEnum $world): array { - $stmt = $this->pdo->prepare("SELECT * FROM $this->table WHERE world = :world"); - $stmt->execute(['world' => $world->value]); + $sql = "SELECT * FROM clans WHERE world = :world"; + + $result = $this->database->select($sql, [ + 'world' => $world->value, + ]); $clans = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array $row */ $clans[$row['clan_id']] = $this->hydrateClan($row); } @@ -33,11 +34,11 @@ public function findAllByWorld(WorldEnum $world): array public function insert(Clan $clan): void { $sql = <<table (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points, created) + INSERT INTO clans (world, clan_id, shortcut, name, leader_id, co_leader_id, diplomat_id, war_points, created) VALUES (:world, :clanId, :shortcut, :name, :leaderId, :coLeaderId, :diplomatId, :warPoints, :created) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $clan->world->value, 'clanId' => $clan->clanId, 'shortcut' => $clan->shortcut, @@ -55,20 +56,22 @@ public function insert(Clan $clan): void */ public function insertClans(WorldEnum $world, array $clans): void { - $sql = "DELETE FROM $this->table WHERE world = :world"; + $sql = "DELETE FROM clans WHERE world = :world"; try { - $this->pdo->beginTransaction(); + $this->database->beginTransaction(); - $this->pdo->prepare($sql)->execute(['world' => $world->value]); + $this->database->delete($sql, [ + 'world' => $world->value, + ]); foreach ($clans as $clan) { $this->insert($clan); } - $this->pdo->commit(); + $this->database->commitTransaction(); } catch (Exception $e) { - $this->pdo->rollBack(); + $this->database->rollbackTransaction(); throw $e; } @@ -76,10 +79,9 @@ public function insertClans(WorldEnum $world, array $clans): void public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM clans"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } /** diff --git a/src/Repository/Factory/RepositoryFactory.php b/src/Repository/Factory/RepositoryFactory.php index b281093..267ee2d 100644 --- a/src/Repository/Factory/RepositoryFactory.php +++ b/src/Repository/Factory/RepositoryFactory.php @@ -6,26 +6,27 @@ use Jesperbeisner\Fwstats\Repository\AbstractRepository; use Jesperbeisner\Fwstats\Stdlib\Exception\RuntimeException; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\DatabaseInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use PDO; -use Psr\Container\ContainerInterface; use Throwable; class RepositoryFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): AbstractRepository + public function build(ContainerInterface $container, string $serviceId): AbstractRepository { - /** @var PDO $pdo */ - $pdo = $serviceContainer->get(PDO::class); + /** @var DatabaseInterface $database */ + $database = $container->get(DatabaseInterface::class); try { - $repository = new $serviceName($pdo); + $repository = new $serviceId($database); } catch (Throwable $e) { - throw new RuntimeException("Looks like '$serviceName' is not a valid repository class."); + throw new RuntimeException(sprintf('Looks like "%s" is not a valid repository class.', $serviceId)); } if (!($repository instanceof AbstractRepository)) { - throw new RuntimeException("Looks like '$serviceName' is not a valid repository class."); + throw new RuntimeException(sprintf('Looks like "%s" is not a valid repository class.', $serviceId)); } return $repository; diff --git a/src/Repository/Factory/UserRepositoryFactory.php b/src/Repository/Factory/UserRepositoryFactory.php deleted file mode 100644 index be1ba32..0000000 --- a/src/Repository/Factory/UserRepositoryFactory.php +++ /dev/null @@ -1,23 +0,0 @@ -get(DatabaseInterface::class); - - return new UserRepository( - $database, - ); - } -} diff --git a/src/Repository/LogRepository.php b/src/Repository/LogRepository.php index 05fdf69..09bbb5f 100644 --- a/src/Repository/LogRepository.php +++ b/src/Repository/LogRepository.php @@ -9,13 +9,11 @@ final class LogRepository extends AbstractRepository { - private string $table = 'logs'; - public function insert(Log $log): void { - $sql = "INSERT INTO $this->table (url, created) VALUES (:url, :created)"; + $sql = "INSERT INTO logs (url, created) VALUES (:url, :created)"; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'url' => $log->url, 'created' => $log->created->format('Y-m-d H:i:s'), ]); @@ -26,13 +24,12 @@ public function insert(Log $log): void */ public function findLast250Logs(): array { - $sql = "SELECT * FROM $this->table ORDER BY id DESC LIMIT 250"; + $sql = "SELECT * FROM logs ORDER BY id DESC LIMIT 250"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $result = $this->database->select($sql); $logs = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array{id: int, url: string, created: string} $row */ $logs[] = $this->hydrateLog($row); } diff --git a/src/Repository/MigrationRepository.php b/src/Repository/MigrationRepository.php index 0df15e3..2e0b236 100644 --- a/src/Repository/MigrationRepository.php +++ b/src/Repository/MigrationRepository.php @@ -4,21 +4,21 @@ namespace Jesperbeisner\Fwstats\Repository; +use Jesperbeisner\Fwstats\Stdlib\Exception\DatabaseException; + final class MigrationRepository extends AbstractRepository { - private string $table = 'migrations'; - public function createMigrationsTable(): void { $sql = <<table} ( + CREATE TABLE IF NOT EXISTS migrations ( id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE, created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) SQL; - $this->pdo->exec($sql); + $this->database->execute($sql); } /** @@ -26,26 +26,32 @@ public function createMigrationsTable(): void */ public function findByFileName(string $fileName): ?array { - $sql = "SELECT * FROM {$this->table} WHERE name = :migration"; + $sql = "SELECT * FROM migrations WHERE name = :migration"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['migration' => $fileName]); + /** @var array $result */ + $result = $this->database->select($sql, [ + 'migration' => $fileName, + ]); - $result = $stmt->fetchAll(); if (count($result) === 0) { return null; } - /** @var array{id: int, name: string, created: string} $result */ + if (count($result) > 1) { + throw new DatabaseException('How can there be more than 1 migration for a single file name?'); + } - return $result; + return $result[0]; } - public function executeMigration(string $fileName, string $sql): void + public function executeMigration(string $migrationName, string $migrationSql): void { - $this->pdo->exec($sql); + $sql = "INSERT INTO migrations (name) VALUES (:migrationName)"; + + $this->database->execute($migrationSql); - $stmt = $this->pdo->prepare("INSERT INTO {$this->table} (name) VALUES (:migrationName)"); - $stmt->execute(['migrationName' => $fileName]); + $this->database->insert($sql, [ + 'migrationName' => $migrationName, + ]); } } diff --git a/src/Repository/PlayerActiveSecondRepository.php b/src/Repository/PlayerActiveSecondRepository.php index 6dd6a81..d79c341 100644 --- a/src/Repository/PlayerActiveSecondRepository.php +++ b/src/Repository/PlayerActiveSecondRepository.php @@ -15,17 +15,15 @@ final class PlayerActiveSecondRepository extends AbstractRepository { - private string $table = 'players_active_seconds'; - public function insert(PlayerActiveSecond $playerActiveSecond): void { $sql = <<table + UPDATE players_active_seconds SET seconds = :seconds WHERE world = :world AND player_id = :playerId AND created = :created SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->update($sql, [ 'world' => $playerActiveSecond->world->value, 'playerId' => $playerActiveSecond->playerId, 'seconds' => $playerActiveSecond->seconds, @@ -33,11 +31,11 @@ public function insert(PlayerActiveSecond $playerActiveSecond): void ]); $sql = <<table (world, player_id, seconds, created) + INSERT OR IGNORE INTO players_active_seconds (world, player_id, seconds, created) VALUES (:world, :playerId, :seconds, :created) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerActiveSecond->world->value, 'playerId' => $playerActiveSecond->playerId, 'seconds' => $playerActiveSecond->seconds, @@ -51,15 +49,15 @@ public function insert(PlayerActiveSecond $playerActiveSecond): void public function insertPlayerActiveSeconds(array $playerActiveSeconds): void { try { - $this->pdo->beginTransaction(); + $this->database->beginTransaction(); foreach ($playerActiveSeconds as $playerActiveSecond) { $this->insert($playerActiveSecond); } - $this->pdo->commit(); + $this->database->commitTransaction(); } catch (Exception $e) { - $this->pdo->rollBack(); + $this->database->rollbackTransaction(); throw $e; } @@ -70,13 +68,15 @@ public function insertPlayerActiveSeconds(array $playerActiveSeconds): void */ public function findAllByWorldAndDate(WorldEnum $world, string $created): array { - $sql = "SELECT * FROM $this->table WHERE world = :world AND created = :created"; + $sql = "SELECT * FROM players_active_seconds WHERE world = :world AND created = :created"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $world->value, 'created' => $created]); + $result = $this->database->select($sql, [ + 'world' => $world->value, + 'created' => $created, + ]); $playerActiveSeconds = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array{world: string, player_id: int, seconds: int, created: string} $row */ $playerActiveSeconds[$row['player_id']] = new PlayerActiveSecond( world: WorldEnum::from($row['world']), @@ -117,15 +117,14 @@ public function getPlaytimeByWorld(WorldEnum $world): array pas2.seconds - pas1.seconds DESC SQL; - $stmt = $this->pdo->prepare($sql); - $stmt->execute([ + $result = $this->database->select($sql, [ 'world' => $world->value, 'yesterday' => (new DateTimeImmutable('-1 day'))->format('Y-m-d'), 'today' => (new DateTimeImmutable())->format('Y-m-d'), ]); $playtime = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array{world: string, name: string, player_id: int, playtime: int} $row */ $playtime[] = new Playtime( world: WorldEnum::from($row['world']), @@ -144,8 +143,9 @@ public function getPlaytimeByWorld(WorldEnum $world): array public function getPlaytimesForPlayer(Player $player, int $days): array { $sql = "SELECT "; + for ($i = 1; $i < $days + 2; $i++) { - $sql .= "(SELECT seconds FROM $this->table WHERE player_id = :playerId and world = :world AND created = :day$i) AS 'day_$i',"; + $sql .= "(SELECT seconds FROM players_active_seconds WHERE player_id = :playerId and world = :world AND created = :day$i) AS 'day_$i',"; } $sql = rtrim($sql, ','); @@ -160,23 +160,16 @@ public function getPlaytimesForPlayer(Player $player, int $days): array $params["day$i"] = $date->modify('-1 day')->format('Y-m-d'); } - $stmt = $this->pdo->prepare($sql); - $stmt->execute($params); - - $result = $stmt->fetch(); - - if (is_array($result)) { - return $result; - } + /** @var array{array} $result */ + $result = $this->database->select($sql, $params); - throw new DatabaseException('This should never happen!'); + return $result[0]; } public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM players_active_seconds"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } } diff --git a/src/Repository/PlayerClanHistoryRepository.php b/src/Repository/PlayerClanHistoryRepository.php index da17eee..278532a 100644 --- a/src/Repository/PlayerClanHistoryRepository.php +++ b/src/Repository/PlayerClanHistoryRepository.php @@ -8,16 +8,14 @@ final class PlayerClanHistoryRepository extends AbstractRepository { - private string $table = 'players_clan_history'; - public function insert(PlayerClanHistory $playerClanHistory): void { $sql = <<table} (world, player_id, old_clan_id, new_clan_id, old_shortcut, new_shortcut, old_name, new_name) + INSERT INTO players_clan_history (world, player_id, old_clan_id, new_clan_id, old_shortcut, new_shortcut, old_name, new_name) VALUES (:world, :playerId, :oldClanId, :newClanId, :oldShortcut, :newShortcut, :oldName, :newName) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerClanHistory->world->value, 'playerId' => $playerClanHistory->playerId, 'oldClanId' => $playerClanHistory->oldClanId, diff --git a/src/Repository/PlayerNameHistoryRepository.php b/src/Repository/PlayerNameHistoryRepository.php index 56abf09..5e6471c 100644 --- a/src/Repository/PlayerNameHistoryRepository.php +++ b/src/Repository/PlayerNameHistoryRepository.php @@ -11,16 +11,14 @@ final class PlayerNameHistoryRepository extends AbstractRepository { - private string $table = 'players_name_history'; - public function insert(PlayerNameHistory $playerNameHistory): void { $sql = <<table} (world, player_id, old_name, new_name, created) + INSERT INTO players_name_history (world, player_id, old_name, new_name, created) VALUES (:world, :playerId, :oldName, :newName, :created) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerNameHistory->world->value, 'playerId' => $playerNameHistory->playerId, 'oldName' => $playerNameHistory->oldName, @@ -34,22 +32,15 @@ public function insert(PlayerNameHistory $playerNameHistory): void */ public function getNameChangesByWorld(WorldEnum $world): array { - $sql = "SELECT * FROM $this->table WHERE world = :world ORDER BY created DESC"; + $sql = "SELECT * FROM players_name_history WHERE world = :world ORDER BY created DESC"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $world->value]); + $result = $this->database->select($sql, [ + 'world' => $world->value, + ]); $playerNameHistories = []; - while (false !== $row = $stmt->fetch()) { - /** - * @var array{ - * world: string, - * player_id: int, - * old_name: string, - * new_name: string, - * created: string - * } $row - */ + foreach ($result as $row) { + /** @var array{world: string, player_id: int, old_name: string, new_name: string, created: string} $row */ $playerNameHistories[] = $this->hydratePlayerNameHistory($row); } @@ -61,22 +52,16 @@ public function getNameChangesByWorld(WorldEnum $world): array */ public function getNameChangesForPlayer(PlayerInterface $player): array { - $sql = "SELECT * FROM $this->table WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; + $sql = "SELECT * FROM players_name_history WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $player->getWorld()->value, 'playerId' => $player->getPlayerId()]); + $result = $this->database->select($sql, [ + 'world' => $player->getWorld()->value, + 'playerId' => $player->getPlayerId(), + ]); $playerNameHistories = []; - while (false !== $row = $stmt->fetch()) { - /** - * @var array{ - * world: string, - * player_id: int, - * old_name: string, - * new_name: string, - * created: string - * } $row - */ + foreach ($result as $row) { + /** @var array{world: string, player_id: int, old_name: string, new_name: string, created: string} $row */ $playerNameHistories[] = $this->hydratePlayerNameHistory($row); } @@ -85,10 +70,9 @@ public function getNameChangesForPlayer(PlayerInterface $player): array public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM players_name_history"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } /** diff --git a/src/Repository/PlayerProfessionHistoryRepository.php b/src/Repository/PlayerProfessionHistoryRepository.php index fee9547..b863a41 100644 --- a/src/Repository/PlayerProfessionHistoryRepository.php +++ b/src/Repository/PlayerProfessionHistoryRepository.php @@ -11,16 +11,14 @@ final class PlayerProfessionHistoryRepository extends AbstractRepository { - private string $table = 'players_profession_history'; - public function insert(PlayerProfessionHistory $playerProfessionHistory): void { $sql = <<table} (world, player_id, old_profession, new_profession, created) + INSERT INTO players_profession_history (world, player_id, old_profession, new_profession, created) VALUES (:world, :playerId, :oldProfession, :newProfession, :created) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerProfessionHistory->world->value, 'playerId' => $playerProfessionHistory->playerId, 'oldProfession' => $playerProfessionHistory->oldProfession, @@ -34,22 +32,16 @@ public function insert(PlayerProfessionHistory $playerProfessionHistory): void */ public function getProfessionChangesForPlayer(PlayerInterface $player): array { - $sql = "SELECT * FROM $this->table WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; + $sql = "SELECT * FROM players_profession_history WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $player->getWorld()->value, 'playerId' => $player->getPlayerId()]); + $result = $this->database->select($sql, [ + 'world' => $player->getWorld()->value, + 'playerId' => $player->getPlayerId(), + ]); $playerProfessionHistories = []; - while (false !== $row = $stmt->fetch()) { - /** - * @var array{ - * world: string, - * player_id: int, - * old_profession: string|null, - * new_profession: string|null, - * created: string - * } $row - */ + foreach ($result as $row) { + /** @var array{world: string, player_id: int, old_profession: string|null, new_profession: string|null, created: string} $row */ $playerProfessionHistories[] = $this->hydratePlayerProfessionHistory($row); } @@ -58,10 +50,9 @@ public function getProfessionChangesForPlayer(PlayerInterface $player): array public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM players_profession_history"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } /** diff --git a/src/Repository/PlayerRaceHistoryRepository.php b/src/Repository/PlayerRaceHistoryRepository.php index f7b5614..e2e1746 100644 --- a/src/Repository/PlayerRaceHistoryRepository.php +++ b/src/Repository/PlayerRaceHistoryRepository.php @@ -11,16 +11,14 @@ final class PlayerRaceHistoryRepository extends AbstractRepository { - private string $table = 'players_race_history'; - public function insert(PlayerRaceHistory $playerRaceHistory): void { $sql = <<table} (world, player_id, old_race, new_race, created) + INSERT INTO players_race_history (world, player_id, old_race, new_race, created) VALUES (:world, :playerId, :oldRace, :newRace, :created) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerRaceHistory->world->value, 'playerId' => $playerRaceHistory->playerId, 'oldRace' => $playerRaceHistory->oldRace, @@ -34,22 +32,16 @@ public function insert(PlayerRaceHistory $playerRaceHistory): void */ public function getRaceChangesForPlayer(PlayerInterface $player): array { - $sql = "SELECT * FROM $this->table WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; + $sql = "SELECT * FROM players_race_history WHERE world = :world AND player_id = :playerId ORDER BY created DESC"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $player->getWorld()->value, 'playerId' => $player->getPlayerId()]); + $result = $this->database->select($sql, [ + 'world' => $player->getWorld()->value, + 'playerId' => $player->getPlayerId(), + ]); $playerRaceHistories = []; - while (false !== $row = $stmt->fetch()) { - /** - * @var array{ - * world: string, - * player_id: int, - * old_race: string, - * new_race: string, - * created: string - * } $row - */ + foreach ($result as $row) { + /** @var array{world: string, player_id: int, old_race: string, new_race: string, created: string} $row */ $playerRaceHistories[] = $this->hydratePlayerRaceHistory($row); } @@ -58,10 +50,9 @@ public function getRaceChangesForPlayer(PlayerInterface $player): array public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM players_race_history"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } /** diff --git a/src/Repository/PlayerRepository.php b/src/Repository/PlayerRepository.php index 13df018..540144a 100644 --- a/src/Repository/PlayerRepository.php +++ b/src/Repository/PlayerRepository.php @@ -8,26 +8,28 @@ use Exception; use Jesperbeisner\Fwstats\Model\Player; use Jesperbeisner\Fwstats\Enum\WorldEnum; +use Jesperbeisner\Fwstats\Stdlib\Exception\DatabaseException; final class PlayerRepository extends AbstractRepository { - private string $table = 'players'; - public function find(WorldEnum $world, int $playerId): ?Player { - $sql = "SELECT * FROM $this->table WHERE world = :world AND player_id = :playerId"; - - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $world->value, 'playerId' => $playerId]); + $sql = "SELECT * FROM players WHERE world = :world AND player_id = :playerId"; - /** @var false|array $playerData */ - $playerData = $stmt->fetch(); + $result = $this->database->select($sql, [ + 'world' => $world->value, + 'playerId' => $playerId, + ]); - if ($playerData === false) { + if (count($result) === 0) { return null; } - return $this->hydratePlayer($playerData); + if (count($result) > 1) { + throw new DatabaseException(sprintf('More than 1 player for the id "%s". How is this possible?', $playerId)); + } + + return $this->hydratePlayer($result[0]); } /** @@ -35,14 +37,14 @@ public function find(WorldEnum $world, int $playerId): ?Player */ public function findAllByWorldAndOrderedByTotalXp(WorldEnum $world): array { - $sql = "SELECT * FROM $this->table WHERE world = :world ORDER BY total_xp DESC LIMIT 100"; + $sql = "SELECT * FROM players WHERE world = :world ORDER BY total_xp DESC LIMIT 100"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $world->value]); + $result = $this->database->select($sql, [ + 'world' => $world->value, + ]); $players = []; - while (false !== $row = $stmt->fetch()) { - /** @var array $row */ + foreach ($result as $row) { $players[] = $this->hydratePlayer($row); } @@ -54,11 +56,14 @@ public function findAllByWorldAndOrderedByTotalXp(WorldEnum $world): array */ public function findAllByWorld(WorldEnum $world): array { - $stmt = $this->pdo->prepare("SELECT * FROM $this->table WHERE world = :world"); - $stmt->execute(['world' => $world->value]); + $sql = "SELECT * FROM players WHERE world = :world"; + + $result = $this->database->select($sql, [ + 'world' => $world->value, + ]); $players = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array $row */ $players[$row['player_id']] = $this->hydratePlayer($row); } @@ -69,11 +74,11 @@ public function findAllByWorld(WorldEnum $world): array public function insert(Player $player): void { $sql = <<table (world, player_id, name, race, clan_id, profession, xp, soul_xp, total_xp) + INSERT INTO players (world, player_id, name, race, clan_id, profession, xp, soul_xp, total_xp) VALUES (:world, :playerId, :name, :race, :clanId, :profession, :xp, :soulXp, :totalXp) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $player->world->value, 'playerId' => $player->playerId, 'name' => $player->name, @@ -91,20 +96,22 @@ public function insert(Player $player): void */ public function insertPlayers(WorldEnum $world, array $players): void { - $sql = "DELETE FROM $this->table WHERE world = :world"; + $sql = "DELETE FROM players WHERE world = :world"; try { - $this->pdo->beginTransaction(); + $this->database->beginTransaction(); - $this->pdo->prepare($sql)->execute(['world' => $world->value]); + $this->database->delete($sql, [ + 'world' => $world->value, + ]); foreach ($players as $player) { $this->insert($player); } - $this->pdo->commit(); + $this->database->commitTransaction(); } catch (Exception $e) { - $this->pdo->rollBack(); + $this->database->rollbackTransaction(); throw $e; } @@ -115,13 +122,14 @@ public function insertPlayers(WorldEnum $world, array $players): void */ public function getTop50PlayersByWorld(WorldEnum $world): array { - $sql = "SELECT * FROM $this->table WHERE world = :world ORDER BY total_xp DESC LIMIT 50"; + $sql = "SELECT * FROM players WHERE world = :world ORDER BY total_xp DESC LIMIT 50"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(['world' => $world->value]); + $result = $this->database->select($sql, [ + 'world' => $world->value, + ]); $players = []; - while (false !== $row = $stmt->fetch()) { + foreach ($result as $row) { /** @var array $row */ $players[] = $this->hydratePlayer($row); } @@ -131,10 +139,9 @@ public function getTop50PlayersByWorld(WorldEnum $world): array public function deleteAll(): void { - $sql = "DELETE FROM $this->table"; + $sql = "DELETE FROM players"; - $stmt = $this->pdo->prepare($sql); - $stmt->execute(); + $this->database->delete($sql); } /** diff --git a/src/Repository/PlayerStatusHistoryRepository.php b/src/Repository/PlayerStatusHistoryRepository.php index 30df459..44e60e8 100644 --- a/src/Repository/PlayerStatusHistoryRepository.php +++ b/src/Repository/PlayerStatusHistoryRepository.php @@ -8,16 +8,14 @@ final class PlayerStatusHistoryRepository extends AbstractRepository { - private string $table = 'players_status_history'; - public function insert(PlayerStatusHistory $playerStatusHistory): void { $sql = <<table (world, player_id, name, status) + INSERT INTO players_status_history (world, player_id, name, status) VALUES (:world, :playerId, :name, :status) SQL; - $this->pdo->prepare($sql)->execute([ + $this->database->insert($sql, [ 'world' => $playerStatusHistory->world->value, 'playerId' => $playerStatusHistory->playerId, 'name' => $playerStatusHistory->name, diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index cf18674..71ae5dd 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -6,20 +6,14 @@ use DateTimeImmutable; use Jesperbeisner\Fwstats\Model\User; +use Jesperbeisner\Fwstats\Stdlib\Exception\DatabaseException; use Jesperbeisner\Fwstats\Stdlib\Interface\DatabaseInterface; -final class UserRepository +final class UserRepository extends AbstractRepository { - private string $table = 'users'; - - public function __construct( - private readonly DatabaseInterface $database, - ) { - } - public function insert(User $user): void { - $sql = "INSERT INTO $this->table (uuid, email, password, created) VALUES (:uuid, :email, :password, :created)"; + $sql = "INSERT INTO users (uuid, email, password, created) VALUES (:uuid, :email, :password, :created)"; $this->database->insert($sql, [ 'uuid' => $user->uuid, @@ -31,21 +25,28 @@ public function insert(User $user): void public function findOneByEmail(string $email): ?User { - $sql = "SELECT uuid, email, password, created FROM $this->table WHERE email = :email"; + $sql = "SELECT uuid, email, password, created FROM users WHERE email = :email"; - /** @var array{uuid: string, email: string, password: string, created: string}|null $userData */ - $userData = $this->database->fetchOne($sql, ['email' => $email]); + $result = $this->database->select($sql, [ + 'email' => $email, + ]); - if ($userData === null) { + if (count($result) === 0) { return null; } - return $this->hydrateUser($userData); + if (count($result) > 1) { + throw new DatabaseException(sprintf('How can there be more than 1 user for email "%s"', $email)); + } + + return $this->hydrateUser($result[0]); } public function deleteAll(): void { - $this->database->deleteAll($this->table); + $sql = "DELETE FROM users"; + + $this->database->delete($sql); } /** diff --git a/src/Service/Factory/FreewarDumpServiceFactory.php b/src/Service/Factory/FreewarDumpServiceFactory.php index f6e9468..b30bc8c 100644 --- a/src/Service/Factory/FreewarDumpServiceFactory.php +++ b/src/Service/Factory/FreewarDumpServiceFactory.php @@ -6,12 +6,12 @@ use Jesperbeisner\Fwstats\Service\FreewarDumpService; use Jesperbeisner\Fwstats\Service\Interface\FreewarDumpServiceInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class FreewarDumpServiceFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): FreewarDumpServiceInterface + public function build(ContainerInterface $container, string $serviceId): FreewarDumpServiceInterface { return new FreewarDumpService(); } diff --git a/src/Service/Factory/PlayerStatusServiceFactory.php b/src/Service/Factory/PlayerStatusServiceFactory.php index 2f4707a..cbaad86 100644 --- a/src/Service/Factory/PlayerStatusServiceFactory.php +++ b/src/Service/Factory/PlayerStatusServiceFactory.php @@ -5,12 +5,12 @@ namespace Jesperbeisner\Fwstats\Service\Factory; use Jesperbeisner\Fwstats\Service\PlayerStatusService; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class PlayerStatusServiceFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PlayerStatusService + public function build(ContainerInterface $container, string $serviceId): PlayerStatusService { return new PlayerStatusService(); } diff --git a/src/Service/Factory/PlaytimeServiceFactory.php b/src/Service/Factory/PlaytimeServiceFactory.php index a96f273..589b03d 100644 --- a/src/Service/Factory/PlaytimeServiceFactory.php +++ b/src/Service/Factory/PlaytimeServiceFactory.php @@ -6,15 +6,15 @@ use Jesperbeisner\Fwstats\Repository\PlayerActiveSecondRepository; use Jesperbeisner\Fwstats\Service\PlaytimeService; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; -use Psr\Container\ContainerInterface; class PlaytimeServiceFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): PlaytimeService + public function build(ContainerInterface $container, string $serviceId): PlaytimeService { /** @var PlayerActiveSecondRepository $playerActiveSecondRepository */ - $playerActiveSecondRepository = $serviceContainer->get(PlayerActiveSecondRepository::class); + $playerActiveSecondRepository = $container->get(PlayerActiveSecondRepository::class); return new PlaytimeService($playerActiveSecondRepository); } diff --git a/src/Service/FreewarDumpService.php b/src/Service/FreewarDumpService.php index e4bf390..ae559d5 100644 --- a/src/Service/FreewarDumpService.php +++ b/src/Service/FreewarDumpService.php @@ -13,7 +13,7 @@ final class FreewarDumpService implements FreewarDumpServiceInterface { - private const ADMINS = ['Sotrax', 'bwoebi', 'Nyrea', 'Andocai']; + private const ADMINS = ['Sotrax', 'bwoebi', 'Nyrea', 'Andocai', 'alexa']; private const PLAYERS_DUMP_URL = 'https://[WORLD].freewar.de/freewar/dump_players.php'; private const CLANS_DUMP_URL = 'https://[WORLD].freewar.de/freewar/dump_clans.php'; diff --git a/src/Stdlib/Config.php b/src/Stdlib/Config.php new file mode 100644 index 0000000..e1a7c0a --- /dev/null +++ b/src/Stdlib/Config.php @@ -0,0 +1,72 @@ +config = $configArray; + } + + public function set(string $key, mixed $value): void + { + $this->config[$key] = $value; + } + + public function get(string $key): mixed + { + if (array_key_exists($key, $this->config)) { + return $this->config[$key]; + } + + throw new RuntimeException(sprintf('There is no config value for the key "%s".', $key)); + } + + public function getAppEnv(): string + { + if (!array_key_exists('app_env', $this->config)) { + throw new RuntimeException('There is no config value for the "app_env" key.'); + } + + $appEnv = $this->config['app_env']; + + if (!is_string($appEnv)) { + throw new RuntimeException('The config value for the "app_env" key is not of type string.'); + } + + return $appEnv; + } + + public function getRootDir(): string + { + if (!array_key_exists('root_dir', $this->config)) { + throw new RuntimeException('There is no config value for the "root_dir" key.'); + } + + $rootDir = $this->config['root_dir']; + + if (!is_string($rootDir)) { + throw new RuntimeException('The config value for the "root_dir" key is not of type string.'); + } + + return $rootDir; + } +} diff --git a/src/Stdlib/Container.php b/src/Stdlib/Container.php new file mode 100644 index 0000000..6d7a204 --- /dev/null +++ b/src/Stdlib/Container.php @@ -0,0 +1,79 @@ +> */ + private array $serviceFactories; + + /** @var array */ + private array $services = []; + + public function __construct(string $servicesFile) + { + if (!file_exists($servicesFile)) { + throw new ContainerException(sprintf('The provided services file "%s" does not exist.', $servicesFile)); + } + + $serviceFactories = require $servicesFile; + + if (!is_array($serviceFactories)) { + throw new ContainerException(sprintf('The provided services file "%s" did not return an array.', $servicesFile)); + } + + $this->serviceFactories = $serviceFactories; + } + + public function set(string $serviceId, mixed $service): void + { + $this->services[$serviceId] = $service; + } + + public function get(string $serviceId): mixed + { + if (array_key_exists($serviceId, $this->services)) { + return $this->services[$serviceId]; + } + + if (array_key_exists($serviceId, $this->serviceFactories)) { + /** @var class-string $factoryClassName */ + $factoryClassName = $this->serviceFactories[$serviceId]; + + try { + $service = (new $factoryClassName())->build($this, $serviceId); + } catch (Exception $e) { + throw new ContainerException($e->getMessage()); + } + + $this->services[$serviceId] = $service; + + return $service; + } + + throw new ContainerException(sprintf('Service with id "%s" does not exist in the Container. Did you forget to register it?', $serviceId)); + } + + public function has(string $serviceId): bool + { + if (array_key_exists($serviceId, $this->services)) { + return true; + } + + if (array_key_exists($serviceId, $this->serviceFactories)) { + return true; + } + + return false; + } +} diff --git a/src/Stdlib/Database.php b/src/Stdlib/Database.php index 1bec061..f38fecc 100644 --- a/src/Stdlib/Database.php +++ b/src/Stdlib/Database.php @@ -4,38 +4,78 @@ namespace Jesperbeisner\Fwstats\Stdlib; +use Jesperbeisner\Fwstats\Stdlib\Exception\DatabaseException; use Jesperbeisner\Fwstats\Stdlib\Interface\DatabaseInterface; use PDO; final class Database implements DatabaseInterface { + private bool $transactionStarted = false; + public function __construct( private readonly PDO $pdo ) { } + public function execute(string $sql, array $params = []): void + { + $this->pdo->prepare($sql)->execute($params); + } + + public function select(string $sql, array $params = []): array + { + $statement = $this->pdo->prepare($sql); + + $statement->execute($params); + + return $statement->fetchAll(); + } + public function insert(string $sql, array $params = []): void { $this->pdo->prepare($sql)->execute($params); } - public function fetchOne(string $sql, array $params = []): ?array + public function update(string $sql, array $params = []): void + { + $this->pdo->prepare($sql)->execute($params); + } + + public function delete(string $sql, array $params = []): void { - $stmt = $this->pdo->prepare($sql); - $stmt->execute($params); + $this->pdo->prepare($sql)->execute($params); + } - /** @var mixed[]|false $data */ - $data = $stmt->fetch(); + public function beginTransaction(): void + { + if ($this->transactionStarted === true) { + throw new DatabaseException('The transaction was already started. You can call "beginTransaction" only once per transaction.'); + } + + $this->pdo->beginTransaction(); - if ($data === false) { - return null; + $this->transactionStarted = true; + } + + public function commitTransaction(): void + { + if ($this->transactionStarted === false) { + throw new DatabaseException('No transaction was started that you can commit.'); } - return $data; + $this->pdo->commit(); + + $this->transactionStarted = false; } - public function deleteAll(string $tableName): void + public function rollbackTransaction(): void { - $this->pdo->prepare("DELETE FROM $tableName")->execute(); + if ($this->transactionStarted === false) { + throw new DatabaseException('No transaction was started that you can rollback.'); + } + + $this->pdo->rollBack(); + + $this->transactionStarted = false; } } diff --git a/src/Stdlib/DotEnvPhpLoader.php b/src/Stdlib/DotEnvPhpLoader.php new file mode 100644 index 0000000..d32e177 --- /dev/null +++ b/src/Stdlib/DotEnvPhpLoader.php @@ -0,0 +1,48 @@ + $envVars */ + $envVars = []; + + foreach ($dotEnvPhpFiles as $dotEnvPhpFile) { + if (file_exists($dotEnvPhpFile)) { + $dotEnvPhpFileArray = require $dotEnvPhpFile; + + if (!is_array($dotEnvPhpFileArray)) { + throw new RuntimeException(sprintf('The file "%s" did not return an array.', $dotEnvPhpFile)); + } + + foreach ($dotEnvPhpFileArray as $envKey => $envValue) { + if (!is_string($envKey)) { + throw new RuntimeException('Only string values are allowed as array keys.'); + } + + if (!is_scalar($envValue)) { + throw new RuntimeException('Only scalar values are allowed as array values.'); + } + + $envVars[$envKey] = $envValue; + } + } + } + + foreach ($envVars as $envKey => $envValue) { + $_ENV[$envKey] = $envValue; + } + } +} diff --git a/src/Stdlib/Exception/ContainerException.php b/src/Stdlib/Exception/ContainerException.php index 9e78d5b..3fe80e3 100644 --- a/src/Stdlib/Exception/ContainerException.php +++ b/src/Stdlib/Exception/ContainerException.php @@ -5,8 +5,7 @@ namespace Jesperbeisner\Fwstats\Stdlib\Exception; use Exception; -use Psr\Container\ContainerExceptionInterface; -final class ContainerException extends Exception implements ContainerExceptionInterface +final class ContainerException extends Exception { } diff --git a/src/Stdlib/Exception/LoggerException.php b/src/Stdlib/Exception/LoggerException.php new file mode 100644 index 0000000..717934b --- /dev/null +++ b/src/Stdlib/Exception/LoggerException.php @@ -0,0 +1,11 @@ +get('rootDir'); + /** @var Config $config */ + $config = $container->get(Config::class); $options = [ PDO::ATTR_EMULATE_PREPARES => false, @@ -23,8 +24,8 @@ public function __invoke(ContainerInterface $serviceContainer, string $serviceNa PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]; - return new Database( - new PDO(dsn: 'sqlite:' . $rootDir . '/data/database/sqlite.db', options: $options), - ); + $pdo = new PDO(dsn: 'sqlite:' . $config->getRootDir() . '/data/database/sqlite.db', options: $options); + + return new Database($pdo); } } diff --git a/src/Stdlib/Factory/LoggerFactory.php b/src/Stdlib/Factory/LoggerFactory.php index 4726879..a900ff1 100644 --- a/src/Stdlib/Factory/LoggerFactory.php +++ b/src/Stdlib/Factory/LoggerFactory.php @@ -4,20 +4,19 @@ namespace Jesperbeisner\Fwstats\Stdlib\Factory; +use Jesperbeisner\Fwstats\Stdlib\Config; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; +use Jesperbeisner\Fwstats\Stdlib\Interface\LoggerInterface; use Jesperbeisner\Fwstats\Stdlib\Logger; -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; final class LoggerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): LoggerInterface + public function build(ContainerInterface $container, string $serviceId): LoggerInterface { - /** @var string $rootDir */ - $rootDir = $serviceContainer->get('rootDir'); + /** @var Config $config */ + $config = $container->get(Config::class); - return new Logger( - $rootDir, - ); + return new Logger($config); } } diff --git a/src/Stdlib/Factory/PdoFactory.php b/src/Stdlib/Factory/PdoFactory.php deleted file mode 100644 index 2bf663b..0000000 --- a/src/Stdlib/Factory/PdoFactory.php +++ /dev/null @@ -1,26 +0,0 @@ -get('rootDir'); - - $options = [ - PDO::ATTR_EMULATE_PREPARES => false, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ]; - - return new PDO(dsn: 'sqlite:' . $rootDir . '/data/database/sqlite.db', options: $options); - } -} diff --git a/src/Stdlib/Factory/RequestFactory.php b/src/Stdlib/Factory/RequestFactory.php index f82e065..a30afd4 100644 --- a/src/Stdlib/Factory/RequestFactory.php +++ b/src/Stdlib/Factory/RequestFactory.php @@ -4,13 +4,13 @@ namespace Jesperbeisner\Fwstats\Stdlib\Factory; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Request; -use Psr\Container\ContainerInterface; final class RequestFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): Request + public function build(ContainerInterface $container, string $serviceId): Request { $uri = $_SERVER['REQUEST_URI']; diff --git a/src/Stdlib/Factory/RouterFactory.php b/src/Stdlib/Factory/RouterFactory.php deleted file mode 100644 index 6d32e3f..0000000 --- a/src/Stdlib/Factory/RouterFactory.php +++ /dev/null @@ -1,27 +0,0 @@ -get('config'); - - /** @var array $routesConfig */ - $routesConfig = $globalConfig['routes']; - - /** @var Request $request */ - $request = $serviceContainer->get(Request::class); - - return new Router($routesConfig, $request); - } -} diff --git a/src/Stdlib/Factory/SessionFactory.php b/src/Stdlib/Factory/SessionFactory.php index be7482b..a591f76 100644 --- a/src/Stdlib/Factory/SessionFactory.php +++ b/src/Stdlib/Factory/SessionFactory.php @@ -5,16 +5,16 @@ namespace Jesperbeisner\Fwstats\Stdlib\Factory; use Jesperbeisner\Fwstats\Repository\UserRepository; +use Jesperbeisner\Fwstats\Stdlib\Interface\ContainerInterface; use Jesperbeisner\Fwstats\Stdlib\Interface\FactoryInterface; use Jesperbeisner\Fwstats\Stdlib\Session; -use Psr\Container\ContainerInterface; final class SessionFactory implements FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): Session + public function build(ContainerInterface $container, string $serviceId): Session { /** @var UserRepository $userRepository */ - $userRepository = $serviceContainer->get(UserRepository::class); + $userRepository = $container->get(UserRepository::class); return new Session($userRepository); } diff --git a/src/Stdlib/Interface/ContainerInterface.php b/src/Stdlib/Interface/ContainerInterface.php new file mode 100644 index 0000000..90d7bdf --- /dev/null +++ b/src/Stdlib/Interface/ContainerInterface.php @@ -0,0 +1,14 @@ + $params + */ + public function execute(string $sql, array $params = []): void; + + /** + * @param array $params + */ + public function select(string $sql, array $params = []): array; + /** * @param array $params */ @@ -13,9 +23,17 @@ public function insert(string $sql, array $params = []): void; /** * @param array $params - * @return mixed[]|null */ - public function fetchOne(string $sql, array $params = []): ?array; + public function update(string $sql, array $params = []): void; + + /** + * @param array $params + */ + public function delete(string $sql, array $params = []): void; + + public function beginTransaction(): void; + + public function commitTransaction(): void; - public function deleteAll(string $tableName): void; + public function rollbackTransaction(): void; } diff --git a/src/Stdlib/Interface/FactoryInterface.php b/src/Stdlib/Interface/FactoryInterface.php index 0c930ab..a17c3f7 100644 --- a/src/Stdlib/Interface/FactoryInterface.php +++ b/src/Stdlib/Interface/FactoryInterface.php @@ -4,9 +4,7 @@ namespace Jesperbeisner\Fwstats\Stdlib\Interface; -use Psr\Container\ContainerInterface; - interface FactoryInterface { - public function __invoke(ContainerInterface $serviceContainer, string $serviceName): mixed; + public function build(ContainerInterface $container, string $serviceId): mixed; } diff --git a/src/Stdlib/Interface/LoggerInterface.php b/src/Stdlib/Interface/LoggerInterface.php new file mode 100644 index 0000000..c08846a --- /dev/null +++ b/src/Stdlib/Interface/LoggerInterface.php @@ -0,0 +1,23 @@ +rootDir . '/data/logs/fwstats.log', 'a')) { - throw new RuntimeException('Could not open stdout resource'); + $logFile = $this->config->getRootDir() . '/data/logs/fwstats.log'; + + if (false === $logResource = fopen($logFile, 'a')) { + throw new LoggerException(sprintf('Could not open "%s".', $logFile)); } - fwrite($outputStream, $message); - fclose($outputStream); + fwrite($logResource, $message); + fclose($logResource); + } + + public function info(string $message, array $context = []): void + { + $this->log('INFO', $message, $context); + } + + public function error(string $message, array $context = []): void + { + $this->log('ERROR', $message, $context); } } diff --git a/src/Stdlib/Router.php b/src/Stdlib/Router.php index 8b70c89..7653096 100644 --- a/src/Stdlib/Router.php +++ b/src/Stdlib/Router.php @@ -5,29 +5,38 @@ namespace Jesperbeisner\Fwstats\Stdlib; use FastRoute; +use Jesperbeisner\Fwstats\Stdlib\Exception\RouterException; final class Router { - /** - * @param array $routesConfig - */ - public function __construct( - private readonly array $routesConfig, - private readonly Request $request, - ) { + private readonly array $routes; + + public function __construct(string $routesFile) + { + if (!file_exists($routesFile)) { + throw new RouterException(sprintf('The provided routes file "%s" does not exist.', $routesFile)); + } + + $routesArray = require $routesFile; + + if (!is_array($routesArray)) { + throw new RouterException(sprintf('The provided routes config file "%s" did not return an array.', $routesFile)); + } + + $this->routes = $routesArray; } /** * @return mixed[] */ - public function match(): array + public function match(Request $request): array { $dispatcher = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $routeCollector) { - foreach ($this->routesConfig as $routeConfig) { - $routeCollector->addRoute($routeConfig['methods'], $routeConfig['route'], $routeConfig['controller']); + foreach ($this->routes as $route) { + $routeCollector->addRoute($route['methods'], $route['route'], [$route['controller'], $route['action']]); } }); - return $dispatcher->dispatch($this->request->httpMethod, $this->request->uri); + return $dispatcher->dispatch($request->httpMethod, $request->uri); } } diff --git a/src/Stdlib/ServiceContainer.php b/src/Stdlib/ServiceContainer.php deleted file mode 100644 index 73d1af9..0000000 --- a/src/Stdlib/ServiceContainer.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ - private array $buildServices = []; - - /** - * @param array $services - */ - public function __construct( - private readonly array $services - ) { - } - - public function get(string $id): mixed - { - if (array_key_exists($id, $this->buildServices)) { - return $this->buildServices[$id]; - } - - if (array_key_exists($id, $this->services)) { - /** @var class-string $factoryClassName */ - $factoryClassName = $this->services[$id]; - - try { - $service = (new $factoryClassName())($this, $id); - } catch (Exception $e) { - throw new ContainerException($e->getMessage()); - } - - $this->buildServices[$id] = $service; - - return $service; - } - - throw new ServiceNotFoundException(sprintf("Service '%s' does not exist in the ServiceManager. Did you forget to register it?", $id)); - } - - public function set(string $identifier, mixed $service): void - { - $this->buildServices[$identifier] = $service; - } - - public function has(string $id): bool - { - return array_key_exists($id, $this->services); - } -} diff --git a/tests/Fixtures/DotEnv/.env.invalid-array-keys.php b/tests/Fixtures/DotEnv/.env.invalid-array-keys.php new file mode 100644 index 0000000..9504cd7 --- /dev/null +++ b/tests/Fixtures/DotEnv/.env.invalid-array-keys.php @@ -0,0 +1,5 @@ + new stdClass(), +]; diff --git a/tests/Fixtures/DotEnv/.env.no-array-return.php b/tests/Fixtures/DotEnv/.env.no-array-return.php new file mode 100644 index 0000000..80070bb --- /dev/null +++ b/tests/Fixtures/DotEnv/.env.no-array-return.php @@ -0,0 +1,5 @@ + 'dev', + 'STRING' => 'Hello world', + 'INTEGER' => 123, + 'FLOAT' => 123.456, + 'BOOL' => true, +]; diff --git a/tests/Fixtures/DotEnv/.env.valid-values_second_file.php b/tests/Fixtures/DotEnv/.env.valid-values_second_file.php new file mode 100644 index 0000000..791f078 --- /dev/null +++ b/tests/Fixtures/DotEnv/.env.valid-values_second_file.php @@ -0,0 +1,11 @@ + 'prod', + 'STRING' => 'Hello world', + 'INTEGER' => 123, + 'FLOAT' => 123.456, + 'BOOL' => true, +]; diff --git a/tests/Unit/Stdlib/ContainerTest.php b/tests/Unit/Stdlib/ContainerTest.php new file mode 100644 index 0000000..fdcc339 --- /dev/null +++ b/tests/Unit/Stdlib/ContainerTest.php @@ -0,0 +1,18 @@ + -
- -
- -
-
+
+
+
+
+ +
+ +
+
-
- -
- -
-
+
+ +
+ +
+
-
- +
+ +
+
- +