diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cc4abc --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/app/vendor/ +/.vagrant/ +/.idea/ +*.log +/app/var/routesCache +/app/var/listenerCache diff --git a/app/composer.json b/app/composer.json new file mode 100644 index 0000000..6f93458 --- /dev/null +++ b/app/composer.json @@ -0,0 +1,51 @@ +{ + "name": "lubian/attribute-magic", + "autoload": { + "psr-4": { + "Lubian\\AttributeMagic\\": "src/" + }, + "files": [ + "src/Infrastructure/functions.php" + ] + }, + "authors": [ + { + "name": "lubiana", + "email": "lubiana123@gmail.com" + } + ], + "require": { + "php": ">=8.1", + "php-di/php-di": "^6.4", + "nikic/fast-route": "^1.3", + "symfony/http-foundation": "^6.1.7" + }, + "require-dev": { + "phpstan/phpstan": "^1.9.1", + "lubiana/code-quality": "^1.1", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan-strict-rules": "^1.4", + "thecodingmachine/phpstan-strict-rules": "^1.0" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } + }, + "scripts": { + "serve": [ + "Composer\\Config::disableProcessTimeout", + "php -S 0.0.0.0:1235 -t public" + ], + "phpstan": "./vendor/bin/phpstan analyze", + "baseline": "./vendor/bin/phpstan analyze --generate-baseline", + "style": "./vendor/bin/ecs", + "fix": [ + "rector process" ,"ecs --fix", "ecs --fix" + ], + "rector": "./vendor/bin/rector process" + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/app/composer.lock b/app/composer.lock new file mode 100644 index 0000000..9c2dee0 --- /dev/null +++ b/app/composer.lock @@ -0,0 +1,1162 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "a5621f758f1624602b7368fd562c7ff2", + "packages": [ + { + "name": "laravel/serializable-closure", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae", + "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2022-09-08T13:45:54+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "php-di/invoker", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/Invoker.git", + "reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786", + "reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "psr/container": "^1.0|^2.0" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Invoker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generic and extensible callable invoker", + "homepage": "https://github.com/PHP-DI/Invoker", + "keywords": [ + "callable", + "dependency", + "dependency-injection", + "injection", + "invoke", + "invoker" + ], + "support": { + "issues": "https://github.com/PHP-DI/Invoker/issues", + "source": "https://github.com/PHP-DI/Invoker/tree/2.3.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + } + ], + "time": "2021-12-13T09:22:56+00:00" + }, + { + "name": "php-di/php-di", + "version": "6.4.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PHP-DI.git", + "reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/ae0f1b3b03d8b29dff81747063cbfd6276246cc4", + "reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4", + "shasum": "" + }, + "require": { + "laravel/serializable-closure": "^1.0", + "php": ">=7.4.0", + "php-di/invoker": "^2.0", + "php-di/phpdoc-reader": "^2.0.1", + "psr/container": "^1.0" + }, + "provide": { + "psr/container-implementation": "^1.0" + }, + "require-dev": { + "doctrine/annotations": "~1.10", + "friendsofphp/php-cs-fixer": "^2.4", + "mnapoli/phpunit-easymock": "^1.2", + "ocramius/proxy-manager": "^2.11.2", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^9.5" + }, + "suggest": { + "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)", + "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~2.0)" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "DI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The dependency injection container for humans", + "homepage": "https://php-di.org/", + "keywords": [ + "PSR-11", + "container", + "container-interop", + "dependency injection", + "di", + "ioc", + "psr11" + ], + "support": { + "issues": "https://github.com/PHP-DI/PHP-DI/issues", + "source": "https://github.com/PHP-DI/PHP-DI/tree/6.4.0" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", + "type": "tidelift" + } + ], + "time": "2022-04-09T16:46:38+00:00" + }, + { + "name": "php-di/phpdoc-reader", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PhpDocReader.git", + "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/66daff34cbd2627740ffec9469ffbac9f8c8185c", + "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "require-dev": { + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpDocReader\\": "src/PhpDocReader" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)", + "keywords": [ + "phpdoc", + "reflection" + ], + "support": { + "issues": "https://github.com/PHP-DI/PhpDocReader/issues", + "source": "https://github.com/PHP-DI/PhpDocReader/tree/2.2.1" + }, + "time": "2020-10-12T12:39:22+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "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/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-02-25T11:15:52+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "792a1856d2b95273f0e1c3435785f1d01a60ecc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/792a1856d2b95273f0e1c3435785f1d01a60ecc6", + "reference": "792a1856d2b95273f0e1c3435785f1d01a60ecc6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/cache": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^5.4|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v6.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-12T09:44:59+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-24T11:49:31+00:00" + } + ], + "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.7.2", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, + "time": "2022-02-04T12:51:07+00:00" + }, + { + "name": "lubiana/code-quality", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://git.php.fail/lubiana/code-quality.git", + "reference": "a99023d48440482d9da3c604442600b142ebe259" + }, + "require": { + "rector/rector": "^0.14.7", + "slevomat/coding-standard": "^8.6.2", + "symplify/easy-coding-standard": "^11.1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lubiana\\CodeQuality\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "time": "2022-11-04T10:18:22+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40", + "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.8.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.2.0" + }, + "time": "2022-10-17T12:59:16+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.13.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "33aefcdab42900e36366d0feab6206e2dd68f947" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/33aefcdab42900e36366d0feab6206e2dd68f947", + "reference": "33aefcdab42900e36366d0feab6206e2dd68f947", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.13.0" + }, + "time": "2022-10-21T09:57:39+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f", + "reference": "a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "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.9.1" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-11-04T13:35:59+00:00" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "1.4.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.8.6" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" + }, + "time": "2022-09-21T11:38:17+00:00" + }, + { + "name": "rector/rector", + "version": "0.14.7", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "3553aaba0e820083fc6d7f0dc78d8d789226a398" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/3553aaba0e820083fc6d7f0dc78d8d789226a398", + "reference": "3553aaba0e820083fc6d7f0dc78d8d789226a398", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.9.0" + }, + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-php-parser": "*", + "rector/rector-phpoffice": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.14-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/0.14.7" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-11-04T08:48:40+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "8.6.2", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "080f592b16f021a3a8e43d95ca8f57b87ddcf4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/080f592b16f021a3a8e43d95ca8f57b87ddcf4e6", + "reference": "080f592b16f021a3a8e43d95ca8f57b87ddcf4e6", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": ">=1.11.0 <1.14.0", + "squizlabs/php_codesniffer": "^3.7.1" + }, + "require-dev": { + "phing/phing": "2.17.4", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.4.10|1.8.10", + "phpstan/phpstan-deprecation-rules": "1.0.0", + "phpstan/phpstan-phpunit": "1.0.0|1.1.1", + "phpstan/phpstan-strict-rules": "1.4.4", + "phpunit/phpunit": "7.5.20|8.5.21|9.5.25" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.6.2" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2022-10-22T15:42:49+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.1", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2022-06-18T07:21:10+00:00" + }, + { + "name": "symplify/easy-coding-standard", + "version": "11.1.16", + "source": { + "type": "git", + "url": "https://github.com/symplify/easy-coding-standard.git", + "reference": "32ebd57f0f47713540df8ea39134adaa9d912fae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/32ebd57f0f47713540df8ea39134adaa9d912fae", + "reference": "32ebd57f0f47713540df8ea39134adaa9d912fae", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "conflict": { + "friendsofphp/php-cs-fixer": "<3.0", + "squizlabs/php_codesniffer": "<3.6" + }, + "bin": [ + "bin/ecs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.3-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Prefixed scoped version of ECS package", + "support": { + "source": "https://github.com/symplify/easy-coding-standard/tree/11.1.16" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-10-27T10:48:13+00:00" + }, + { + "name": "thecodingmachine/phpstan-strict-rules", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/phpstan-strict-rules.git", + "reference": "2ba8fa8b328c45f3b149c05def5bf96793c594b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/phpstan-strict-rules/zipball/2ba8fa8b328c45f3b149c05def5bf96793c594b6", + "reference": "2ba8fa8b328c45f3b149c05def5bf96793c594b6", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0", + "phpstan/phpstan": "^1.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^7.1" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "phpstan": { + "includes": [ + "phpstan-strict-rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "TheCodingMachine\\PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David NĂ©grier", + "email": "d.negrier@thecodingmachine.com" + } + ], + "description": "A set of additional rules for PHPStan based on best practices followed at TheCodingMachine", + "support": { + "issues": "https://github.com/thecodingmachine/phpstan-strict-rules/issues", + "source": "https://github.com/thecodingmachine/phpstan-strict-rules/tree/v1.0.0" + }, + "time": "2021-11-08T09:10:49+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=8.1" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/app/config/.gitkeep b/app/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/ecs.php b/app/ecs.php new file mode 100644 index 0000000..12d6e36 --- /dev/null +++ b/app/ecs.php @@ -0,0 +1,18 @@ +parallel(); + $c->paths([ + __DIR__ . '/src', + __DIR__ . '/config', + __DIR__ . '/ecs.php', + __DIR__ . '/rector.php', + ]); + + $c->sets([ + LubiSetList::ECS, + ]); +}; diff --git a/app/phpstan-baseline.neon b/app/phpstan-baseline.neon new file mode 100644 index 0000000..e69de29 diff --git a/app/phpstan.neon b/app/phpstan.neon new file mode 100644 index 0000000..20a700a --- /dev/null +++ b/app/phpstan.neon @@ -0,0 +1,8 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: max + paths: + - src + - config \ No newline at end of file diff --git a/app/public/favicon.ico b/app/public/favicon.ico new file mode 100644 index 0000000..09499b8 Binary files /dev/null and b/app/public/favicon.ico differ diff --git a/app/public/index.php b/app/public/index.php new file mode 100644 index 0000000..cfd3989 --- /dev/null +++ b/app/public/index.php @@ -0,0 +1,3 @@ +paths([__DIR__ . '/src', __DIR__ . '/config', __DIR__ . '/ecs.php', __DIR__ . '/rector.php']); + + $c->importNames(); + + $c->sets([ + LubiSetList::RECTOR, + ]); +}; diff --git a/app/src/Bootstrap.php b/app/src/Bootstrap.php new file mode 100644 index 0000000..e8d10d3 --- /dev/null +++ b/app/src/Bootstrap.php @@ -0,0 +1,30 @@ +addDefinitions([ + Finder::class => static fn (): Finder => new Finder(__DIR__, [], $cached), + Dispatcher::class => static fn (DispatcherFactory $f): Dispatcher => $f->getDispatcher($cached), + HandlerResolver::class => static fn (Dispatcher $d): HandlerResolver => new HandlerResolver($d, $cached), +])->build(); +$dispatcher = $container->get(Dispatcher::class); +assert($dispatcher instanceof Dispatcher); +$request = new RequestEvent(Request::createFromGlobals()); + +$dispatcher->dispatch($request); + +$request->response?->send(); +exit; diff --git a/app/src/Handler/Auchnoch.php b/app/src/Handler/Auchnoch.php new file mode 100644 index 0000000..0376c65 --- /dev/null +++ b/app/src/Handler/Auchnoch.php @@ -0,0 +1,15 @@ +dispatcher->dispatch($event); + echo $event->message; + } +} diff --git a/app/src/Handler/Viel/.gitkeep b/app/src/Handler/Viel/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/Infrastructure/Event/AsListener.php b/app/src/Infrastructure/Event/AsListener.php new file mode 100644 index 0000000..4143478 --- /dev/null +++ b/app/src/Infrastructure/Event/AsListener.php @@ -0,0 +1,19 @@ + $priority + */ + public function __construct( + public readonly string $eventClass, + public readonly int $priority = 0, + ) { + } +} diff --git a/app/src/Infrastructure/Event/Dispatcher.php b/app/src/Infrastructure/Event/Dispatcher.php new file mode 100644 index 0000000..1a186e6 --- /dev/null +++ b/app/src/Infrastructure/Event/Dispatcher.php @@ -0,0 +1,60 @@ +listeners[] = $listener; + } + + /** + * @return Listener[] + */ + public function getListenerForEvent(GenericEvent $event): array + { + return arrayFilter( + $this->listeners, + static fn (Listener $l): bool => $l->eventClass === $event::class, + ); + } + + /** + * @return Listener[] + */ + public function getSortedListenerForEvent(GenericEvent $event): array + { + $filtered = $this->getListenerForEvent($event); + usort($filtered, static fn (Listener $a, Listener $b): int => $a->priority <=> $b->priority); + return $filtered; + } + + public function dispatch(GenericEvent $event): void + { + foreach ($this->getSortedListenerForEvent($event) as $listener) { + if ($event->stopped === true) { + return; + } + + $this->invoker->call( + [$listener->listenerClass, $listener->listenerMethod], + [$event], + ); + } + } +} diff --git a/app/src/Infrastructure/Event/DispatcherFactory.php b/app/src/Infrastructure/Event/DispatcherFactory.php new file mode 100644 index 0000000..08ba7e9 --- /dev/null +++ b/app/src/Infrastructure/Event/DispatcherFactory.php @@ -0,0 +1,49 @@ +invoker, $this->getListeners($cached)); + } + + /** + * @return Listener[] + */ + private function getListeners(bool $cached = false): array + { + if ($cached === true && file_exists(self::CACHE_FILE)) { + /** @var Listener[] $listeners */ + $listeners = unserialize( + file_get_contents(self::CACHE_FILE) + ); //@phpstan-ignore-line + return $listeners; + } + + $listeners = $this->finder->getListeners(); + if ($cached === true) { + file_put_contents(self::CACHE_FILE, serialize($listeners)); + } + + return $listeners; + } +} diff --git a/app/src/Infrastructure/Event/GenericEvent.php b/app/src/Infrastructure/Event/GenericEvent.php new file mode 100644 index 0000000..60ff8af --- /dev/null +++ b/app/src/Infrastructure/Event/GenericEvent.php @@ -0,0 +1,8 @@ + $priority + * @param class-string $listenerClass + * @param non-empty-string $listenerMethod + */ + public function __construct( + public readonly string $eventClass, + public readonly int $priority, + public readonly string $listenerClass, + public readonly string $listenerMethod, + ) { + } +} diff --git a/app/src/Infrastructure/Finder.php b/app/src/Infrastructure/Finder.php new file mode 100644 index 0000000..623fc28 --- /dev/null +++ b/app/src/Infrastructure/Finder.php @@ -0,0 +1,114 @@ +populateClassnames(); + return array_map( + static fn (array $h): Listener => new Listener($h[0]->eventClass, $h[0]->priority, $h[1], $h[2]), + iterator_to_array($this->getAttributes(AsListener::class)), + ); + } + + /** + * @return Handler[] + */ + public function getHandlers(): array + { + $this->populateClassnames(); + return array_map( + static fn (array $h): Handler => new Handler($h[0]->method, $h[0]->path, $h[1], $h[2]), + iterator_to_array($this->getAttributes(AsHandler::class)), + ); + } + + private function populateClassnames(): void + { + if ($this->classNames !== []) { + return; + } + + if ($this->cached === true && file_exists(self::CACHE_FILE)) { + $this->classNames = unserialize(file_get_contents(self::CACHE_FILE)); + return; + } + + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path)); + /** @var SplFileInfo $file */ + foreach ($it as $file) { + if (! str_ends_with((string) $file, '.php')) { + continue; + } + + $classesBeforeLoad = get_declared_classes(); + require_once (string) $file; + $classesAfterLoad = get_declared_classes(); + $this->classNames = [...$this->classNames, ...array_diff($classesAfterLoad, $classesBeforeLoad)]; + } + + if ($this->cached === true) { + file_put_contents(self::CACHE_FILE, serialize($this->classNames)); + } + } + + /** + * @template T + * @param class-string $attributeClass + * @return Iterator + */ + private function getAttributes( + string $attributeClass + ): Iterator { + foreach ($this->classNames as $class) { + $reflectionClass = new ReflectionClass($class); + foreach ($reflectionClass->getMethods() as $method) { + foreach ($method->getAttributes($attributeClass) as $attribute) { + yield [ + $attribute->newInstance(), + $class, + $method->getName(), + ]; + } + } + } + } +} diff --git a/app/src/Infrastructure/Route/AsHandler.php b/app/src/Infrastructure/Route/AsHandler.php new file mode 100644 index 0000000..7a417ca --- /dev/null +++ b/app/src/Infrastructure/Route/AsHandler.php @@ -0,0 +1,18 @@ +routes = $this->finder->getHandlers(); + } +} diff --git a/app/src/Infrastructure/WebApp/Route/CachedResponse.php b/app/src/Infrastructure/WebApp/Route/CachedResponse.php new file mode 100644 index 0000000..d2d19e6 --- /dev/null +++ b/app/src/Infrastructure/WebApp/Route/CachedResponse.php @@ -0,0 +1,36 @@ +response = $response; + // $event->stopped = true; + } + + #[AsListener(RequestEvent::class, 99)] + public function doCache(RequestEvent $event): void + { + if ($event->response === null) { + return; + } + + $path = md5($event->request->getPathInfo()); + apcu_add($path, serialize($event->response)); + } +} diff --git a/app/src/Infrastructure/WebApp/Route/CachedRouteCollector.php b/app/src/Infrastructure/WebApp/Route/CachedRouteCollector.php new file mode 100644 index 0000000..e749258 --- /dev/null +++ b/app/src/Infrastructure/WebApp/Route/CachedRouteCollector.php @@ -0,0 +1,44 @@ +cached === false) { + return; + } + + if (! file_exists(self::ROUTES_DIR)) { + return; + } + + $event->routes = unserialize(file_get_contents(self::ROUTES_DIR)); //@phpstan-ignore-line + $event->stopped = true; + } + + #[AsListener(CollectRoutes::class, 10)] + public function setCached(CollectRoutes $event): void + { + if ($event->cached === false) { + return; + } + + file_put_contents( + self::ROUTES_DIR, + serialize($event->routes), + ); + } +} diff --git a/app/src/Infrastructure/WebApp/Route/CollectRoutes.php b/app/src/Infrastructure/WebApp/Route/CollectRoutes.php new file mode 100644 index 0000000..9ed4f7b --- /dev/null +++ b/app/src/Infrastructure/WebApp/Route/CollectRoutes.php @@ -0,0 +1,19 @@ +handler === null) { + $event->stopped = true; + $event->response = new Response('not resolved', 500); + return; + } + + ob_start(); + $response = $this->invoker->call( + [$event->handler->handlerClass, $event->handler->handlerMethod], + $event->request->attributes->all() + ); + $output = (string) ob_get_clean(); + + if ($response instanceof Response) { + $event->response = $response; + return; + } + + $event->response = new Response($output, 200); + } +} diff --git a/app/src/Infrastructure/WebApp/Route/HandlerResolver.php b/app/src/Infrastructure/WebApp/Route/HandlerResolver.php new file mode 100644 index 0000000..d42c64a --- /dev/null +++ b/app/src/Infrastructure/WebApp/Route/HandlerResolver.php @@ -0,0 +1,68 @@ +cached); + $this->dispatcher->dispatch($routesEvent); + $dispatcher = $this->dispatcher; + + $routeDispatcher = cachedDispatcher(static function (RouteCollector $r) use ( + $dispatcher, + $routesEvent + ): void { + $dispatcher->dispatch($routesEvent); + foreach ($routesEvent->routes as $h) { + $r->addRoute($h->method->value, $h->path, [$h->handlerClass, $h->handlerMethod]); + } + }, [ + 'cacheFile' => __DIR__ . '/../../../../var/route.cache', + 'cacheDisabled' => ! $this->cached, + ]); + + $routeInfo = $routeDispatcher->dispatch( + $event->request->getMethod(), + $event->request->getPathInfo(), + ); + + if ($routeInfo[0] === \FastRoute\Dispatcher::NOT_FOUND) { + $event->response = new Response('Not Found', 404); + $event->stopped = true; + return; + } + + if ($routeInfo[0] === \FastRoute\Dispatcher::METHOD_NOT_ALLOWED) { + $event->response = new Response('Not Allowed', 403); + $event->stopped = true; + return; + } + + $event->handler = new Handler( + HttpMethod::from($event->request->getMethod()), + $event->request->getPathInfo(), + ...$routeInfo[1], + ); + + $event->request->attributes->add($routeInfo[2]); + } +} diff --git a/app/src/Infrastructure/functions.php b/app/src/Infrastructure/functions.php new file mode 100644 index 0000000..46b4dd7 --- /dev/null +++ b/app/src/Infrastructure/functions.php @@ -0,0 +1,23 @@ + $input + * @return array + */ +function arrayFilter( + array $input, + callable $callable +): array { + return array_values( + array_filter( + $input, + $callable, + ) + ); +} diff --git a/app/src/Listener/LauschEvent.php b/app/src/Listener/LauschEvent.php new file mode 100644 index 0000000..22e463a --- /dev/null +++ b/app/src/Listener/LauschEvent.php @@ -0,0 +1,13 @@ +message = $event->message . ' lolduuuuu'; + return $event; + } +} diff --git a/app/test.php b/app/test.php new file mode 100644 index 0000000..7a52fc2 --- /dev/null +++ b/app/test.php @@ -0,0 +1,57 @@ +