diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.github/img/2fa_setup.png b/.github/img/2fa_setup.png new file mode 100644 index 0000000..8aac7c3 Binary files /dev/null and b/.github/img/2fa_setup.png differ diff --git a/.github/img/email.png b/.github/img/email.png new file mode 100644 index 0000000..735bed8 Binary files /dev/null and b/.github/img/email.png differ diff --git a/.github/img/light_dark.png b/.github/img/light_dark.png new file mode 100644 index 0000000..5716ddc Binary files /dev/null and b/.github/img/light_dark.png differ diff --git a/.github/img/login_forms.png b/.github/img/login_forms.png new file mode 100644 index 0000000..97ec519 Binary files /dev/null and b/.github/img/login_forms.png differ diff --git a/.github/img/logs.png b/.github/img/logs.png new file mode 100644 index 0000000..5d59da6 Binary files /dev/null and b/.github/img/logs.png differ diff --git a/.github/img/org/03_dashboard.png b/.github/img/org/03_dashboard.png new file mode 100644 index 0000000..5ab857f Binary files /dev/null and b/.github/img/org/03_dashboard.png differ diff --git a/.github/img/org/04_user.png b/.github/img/org/04_user.png new file mode 100644 index 0000000..9cea3e7 Binary files /dev/null and b/.github/img/org/04_user.png differ diff --git a/.github/img/org/05_2fa_setup.png b/.github/img/org/05_2fa_setup.png new file mode 100644 index 0000000..8aac7c3 Binary files /dev/null and b/.github/img/org/05_2fa_setup.png differ diff --git a/.github/img/org/05_2fa_user.png b/.github/img/org/05_2fa_user.png new file mode 100644 index 0000000..0ec7916 Binary files /dev/null and b/.github/img/org/05_2fa_user.png differ diff --git a/.github/img/org/06_logs.png b/.github/img/org/06_logs.png new file mode 100644 index 0000000..5d59da6 Binary files /dev/null and b/.github/img/org/06_logs.png differ diff --git a/.github/img/org/light_dark/dark.png b/.github/img/org/light_dark/dark.png new file mode 100644 index 0000000..dc8c84b Binary files /dev/null and b/.github/img/org/light_dark/dark.png differ diff --git a/.github/img/org/light_dark/light.png b/.github/img/org/light_dark/light.png new file mode 100644 index 0000000..7996056 Binary files /dev/null and b/.github/img/org/light_dark/light.png differ diff --git a/.github/img/org/light_dark/light_dark.xcf b/.github/img/org/light_dark/light_dark.xcf new file mode 100644 index 0000000..92f4c40 Binary files /dev/null and b/.github/img/org/light_dark/light_dark.xcf differ diff --git a/.github/img/org/login_forms/01_login.png b/.github/img/org/login_forms/01_login.png new file mode 100644 index 0000000..1ce771f Binary files /dev/null and b/.github/img/org/login_forms/01_login.png differ diff --git a/.github/img/org/login_forms/01_register.png b/.github/img/org/login_forms/01_register.png new file mode 100644 index 0000000..940d0fd Binary files /dev/null and b/.github/img/org/login_forms/01_register.png differ diff --git a/.github/img/org/login_forms/01_resetpassworrd.png b/.github/img/org/login_forms/01_resetpassworrd.png new file mode 100644 index 0000000..4eb6611 Binary files /dev/null and b/.github/img/org/login_forms/01_resetpassworrd.png differ diff --git a/.github/img/org/login_forms/02_2falogin.png b/.github/img/org/login_forms/02_2falogin.png new file mode 100644 index 0000000..745cf97 Binary files /dev/null and b/.github/img/org/login_forms/02_2falogin.png differ diff --git a/.github/img/org/login_forms/login_forms.xcf b/.github/img/org/login_forms/login_forms.xcf new file mode 100644 index 0000000..80cccbd Binary files /dev/null and b/.github/img/org/login_forms/login_forms.xcf differ diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 0000000..e69de29 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..49221db --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +Closes #XXXX <- add related issue number here + +Effect of the changes: + +What was done: + +Todos until this is ready for merging: + +What was not done on purpose: + +How to test the changes: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce97822 --- /dev/null +++ b/.gitignore @@ -0,0 +1,91 @@ + +.DS_Store +app/vendor/* +app/.env + + +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> phpunit/phpunit ### +/phpunit.xml +.phpunit.result.cache +###< phpunit/phpunit ### + +###> symfony/phpunit-bridge ### +.phpunit.result.cache +/phpunit.xml +###< symfony/phpunit-bridge ### + + +# Created by https://www.toptal.com/developers/gitignore/api/symfony +# Edit at https://www.toptal.com/developers/gitignore?templates=symfony + +### Symfony ### +# Cache and logs (Symfony2) +/app/cache/* +/app/logs/* +!app/cache/.gitkeep +!app/logs/.gitkeep + +# Email spool folder +/app/spool/* + +# Cache, session files and logs (Symfony3) +/var/cache/* +/var/logs/* +/var/sessions/* +!var/cache/.gitkeep +!var/logs/.gitkeep +!var/sessions/.gitkeep + +# Logs (Symfony4) +/var/log/* +!var/log/.gitkeep + +# Parameters +/app/config/parameters.yml +/app/config/parameters.ini + +# Managed by Composer +/app/bootstrap.php.cache +/var/bootstrap.php.cache +/bin/* +!bin/console +!bin/symfony_requirements +/vendor/ + +# Assets and user uploads +/web/bundles/ +/web/uploads/ + +# PHPUnit +/app/phpunit.xml +/phpunit.xml + +# Build data +/build/ + +# Composer PHAR +/composer.phar + +# Backup entities generated with doctrine:generate:entities command +**/Entity/*~ + +# Embedded web-server pid file +/.web-server-pid + +### Symfony Patch ### +/web/css/ +/web/js/ + +# End of https://www.toptal.com/developers/gitignore/api/symfony +tools/php-cs-fixer/vendor/ +.php-cs-fixer.cache diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6bb35a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,168 @@ +#!/usr/bin/make -f + +ENV = dev +ifdef env +ENV = $(env) +endif + + +LOCALTEST = false +ifdef localtest +LOCALTEST = $(localtest) +endif + +DOCKER_COMPOSE_FILE ?= docker-compose.yml +DOCKER_CONTAINER_PHP = symfony6app-php + + +DOCKER_CMD = docker exec -t ${DOCKER_CONTAINER_PHP} sh -c + +PHP_CMD = ${DOCKER_CMD} 'php +COMPOSER_CMD = ${DOCKER_CMD} 'php -d memory_limit=-1 /usr/bin/composer +SYMFONY_CMD = ${PHP_CMD} bin/console --env=${ENV} +END = ' + +ifeq ($(ENV),prod) + SYMFONY_CMD += --no-debug +endif + + +# Docker +inside: + make docker-into-php +docker-into-php: + docker exec -it ${DOCKER_CONTAINER_PHP} bash + +docker-rebuild: + docker-compose -f ${DOCKER_COMPOSE_FILE} up -d --force-recreate --build + + +# Composer +# Example: make composer command="update nothing" +COMPOSER_COMMAND = +ifdef command +COMPOSER_COMMAND = $(command) +endif + +composer: + ${COMPOSER_CMD} ${COMPOSER_COMMAND} ${END} + +composer-install: + ${COMPOSER_CMD} install ${END} + make cs-install + +dependencies-update: + ${COMPOSER_CMD} update --with-all-dependencies ${END} + +# Symfony +# Example: make symfony command=about +SYMFONY_COMMAND = +ifdef command +SYMFONY_COMMAND = $(command) +endif + +symfony: + ${SYMFONY_CMD} ${SYMFONY_COMMAND} ${END} + +setup-app: + cp app/.env.dev app/.env + make composer-install + make db-reset || true + make db-migrations + make db-fixtures + make clear-cache + make file-permissions + +setup-app-test: + cp app/.env.test app/.env + make db-drop + make db-create + make db-migrations + ${SYMFONY_CMD} doctrine:fixtures:load --group=test -n --env=${ENV} ${END} + make db-migrations + make clear-cache + make file-permissions + + +clear: + rm -rf app/cache/${env}/* + rm -rf app/logs/${env}/* + ${SYMFONY_CMD} cache:warmup ${END} + +clear-all: + rm -rf app/cache/* + rm -rf app/logs/* + mkdir app/cache/ + mkdir app/logs/ + +clear-cache: + ${SYMFONY_CMD} cache:clear ${END} + ${SYMFONY_CMD} cache:warmup ${END} + +file-permissions: + ${DOCKER_CMD} 'chown -R www-data app/cache/ app/logs/ var/' || true + + +# Database +db-create: + ${SYMFONY_CMD} doctrine:schema:create -e ${ENV} ${END} + +db-drop: +ifeq ($(ENV),prod) + @echo "Dropping DB on production is disabled" +else + ${SYMFONY_CMD} doctrine:schema:drop --force --full-database --env=${ENV} ${END} +endif + +db-reset: +ifeq ($(ENV),prod) + @echo "Dropping DB on production is disabled" +else + make db-drop + make db-create + make db-migrations + ${SYMFONY_CMD} doctrine:fixtures:load --group=setup -n --env=${ENV} ${END} +endif + +db-make-migration: + ${SYMFONY_CMD} make:migration ${END} + +db-migrations: + ${SYMFONY_CMD} doctrine:migrations:migrate --em default --no-interaction ${END} + +db-fixtures: + ${SYMFONY_CMD} doctrine:fixtures:load -n -e ${ENV} ${END} + + + +# Codestyle +cs-install: + cd tools/php-cs-fixer; composer install + +cs-check: + tools/php-cs-fixer/vendor/bin/php-cs-fixer --no-interaction --dry-run --diff -v fix app/src + +cs-fix: + tools/php-cs-fixer/vendor/bin/php-cs-fixer --diff -v fix app/src + + +# translations + +trans-extract: + ${SYMFONY_CMD} translation:extract --force --format=yaml --as-tree=10 --domain=admin en ${END} + ${SYMFONY_CMD} translation:extract --force --format=yaml --as-tree=10 --domain=core en ${END} + ${SYMFONY_CMD} translation:extract --force --format=yaml --as-tree=10 --domain=messages en ${END} + +#phpunit + +tests: + make setup-app-test ENV=test + make tests-phpunit ENV=test + +tests-phpunit: clear-cache tests-phpunit-tests + +tests-phpunit-tests: + ${PHP_CMD} vendor/bin/phpunit --testdox ${PHPUNIT_FILTER} ${END} + +testdev: + ${PHP_CMD} vendor/bin/phpunit --testdox --group dev ${PHPUNIT_FILTER} ${END} diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f1c540 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Symfony6 Stack + +This stack contains some essentials to quick start your symfony project: + +- **Docker**: dockerized development environment +- **Authentication**: [Registration](https://symfonycasts.com/screencast/symfony-security/registration-auth), [Email verfication](https://symfonycasts.com/screencast/symfony-security/verify-email), [Password Reset](https://symfonycasts.com/screencast/symfony-security/verify-email), [two-factor authentication (2FA)](https://symfony.com/bundles/SchebTwoFactorBundle/6.x/index.html) with BackupCodes, TrustedDevice +- **EasyAdmin 4.0**: [EasyAdmin](https://github.com/EasyCorp/EasyAdminBundle) is a fast, beautiful and modern admin generator for Symfony applications. +- **Email Templates**: most used elements (header, footer, button) in separated files for an easy include +- **Multiple Languages**: the core features are in translation fiels, easy implementation of other languages +- **API Plattform**: The [API Platform](https://api-platform.com/) with token authentication is ready to use. +- **Traits**: [Reusable Entityfields](https://github.com/ganti/symfony6-stack/tree/main/app/src/Entity/Traits): createdAt, updatedAt, deletedAt (softdelete), isActive, UUID +- **Database Logging**: Most critical and technical issues shall be logged into files, but some user actions may be logged into the database. A simple [Logging engine](https://github.com/ganti/symfony6-stack/blob/main/app/.env.dev) is used to log events into the database +- **PHP Coding Standards Fixer**: normalize your PHP code with [CS-fixer](https://cs.symfony.com/) + + + + + + + + + + + +
+ Ready to use Forms (Registration, mail verification, Login, 2FA, password reset
+ simple user event logging +
+ two setup autentication setup + Easyadmin with light and dark mode + + Structured emailtemplate +
+ + +## Installation + +```bash + sudo docker-compose up -d + make setup-app +``` + +Browse to [localhost:8001/login](http://localhost:8001/login) and use admin:admin as credentials. Do not forget to change the password! + +### Main configuration points +- **app/.env.dev**/**app/.env.prod**: DATABASE_URL, MAILER_DSN +- **app/config/packages/parameters.yaml**: App configuration (Locale, Timezone, Mailer settings) +- **app/config/packages/scheb_2fa.yaml**: two factor configuration (backupcodes, trusted devices) +- **app/config/*.yaml**: many other settings + + +### Makefile +Here are a few make commands + + - `make setup-app`: Setup + - `make inside` jump inside php-container + - `make db-reset`: Reset DB in development (mostly used after changing an entity, but no new migration is created + - `make cs-check` displays what cs fixes are executed when using `make cs-fix` + - `make symfony command="make:entity"` execute symfony console commands with make + - `make composer command="require foobar"` executed composer commands with make + diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..4b1140a --- /dev/null +++ b/SETUP.md @@ -0,0 +1,108 @@ +# Setup Protocol + + +## docker +```sh + + + +``` +## symfony base + +### Skeleton / Easyadmin + +``` +make inside + +composer create-project symfony/website-skeleton . +composer require easycorp/easyadmin-bundle +php bin/console make:admin:dashboard +``` + +## Security + +https://symfony.com/doc/5.2/security.html#1-installation +``` +composer require symfony/security-bundle +php bin/console ma:user +php bin/console make:auth +php bin/console make:registration-form +``` + +composer require symfonycasts/verify-email-bundle + 1) Install some missing packages: + composer require symfonycasts/verify-email-bundle + 2) In RegistrationController::verifyUserEmail(): + * Customize the last redirectToRoute() after a successful email verification. + * Make sure you're rendering success flash messages or change the $this->addFlash() line. + 3) Review and customize the form, controller, and templates as needed. + 4) Run "php bin/console make:migration" to generate a migration for the newly added User::isVerified property. + +``` + + +composer require symfonycasts/reset-password-bundle +php bin/console make:reset-password + + Next: + 1) Run "php bin/console make:migration" to generate a migration for the new "App\Entity\ResetPasswordRequest" entity. + 2) Review forms in "src/Form" to customize validation and labels. + 3) Review and customize the templates in `templates/reset_password`. + 4) Make sure your MAILER_DSN env var has the correct settings. + 5) Create a "forgot your password link" to the app_forgot_password_request route on your login form. + + Then open your browser, go to "/reset-password" and enjoy! +``` + +## Password Hash +composer require symfony/password-hasher + + +## Fix Mailer +symfony/mailer wont send +in config/packages/messenger.yaml comment out + + messenger: + #failure_transport: failed + [...] + #Symfony\Component\Mailer\Messenger\SendEmailMessage: async + +## Make migration +``` +php bin/console make:migration +php bin/console doctrine:migrations:migrate +``` + +# timezone +into .env / services.yml +Kernel boot() + +# ORM +composer require symfony/orm-pack + + +## Traits +composer require stof/doctrine-extensions-bundle +/config/bundles.php => Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], + +### Softdelete +composer require gedmo/doctrine-extensions + +use ActiveTrait; +use TimestampableCreatedTrait; +use TimestampableUpdatedTrait; +use TimestampableDeletedTrait; + +### UUID Trait + +## fixtures +composer require orm-fixtures --dev +php bin/console doctrine:fixtures:load --group=setup + +## symfony/mailer wont send +in config/packages/messenger.yaml comment out + + messenger: + #failure_transport: failed + [...] + #Symfony\Component\Mailer\Messenger\SendEmailMessage: async \ No newline at end of file diff --git a/app/.env.dev b/app/.env.dev new file mode 100644 index 0000000..4bb7b3f --- /dev/null +++ b/app/.env.dev @@ -0,0 +1,26 @@ + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=202b0ed719a12ea092d50d92583774ba +#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 +#TRUSTED_HOSTS='^(localhost|example\.com)$' +CORS_ALLOW_ORIGIN='*' +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +DATABASE_URL=mysql://root:P@ssw0rd@mysql:3306/default_app?serverVersion=8 +###< doctrine/doctrine-bundle ### + +###> symfony/mailer ### +MAILER_DSN=smtp://df69edb17e1644:8c349d8d7dbe61@smtp.mailtrap.io:2525?encryption=tls&auth_mode=login +MAILER_FROM_MAIL=team@root.dev +MAILER_FROM_NAME=AcmeBotName +###< symfony/mailer ### + +###> symfony/messenger ### +# Choose one of the transports below +#MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages +MESSENGER_TRANSPORT_DSN=doctrine://default +#MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +###< symfony/messenger ### + diff --git a/app/.env.test b/app/.env.test new file mode 100644 index 0000000..cda5117 --- /dev/null +++ b/app/.env.test @@ -0,0 +1,26 @@ +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=202b0ed719a12ea092d50d92583774ba +#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 +#TRUSTED_HOSTS='^(localhost|example\.com)$' +CORS_ALLOW_ORIGIN='*' +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +DATABASE_URL=mysql://root:P@ssw0rd@mysql:3306/default_test?serverVersion=8 +###< doctrine/doctrine-bundle ### + +###> symfony/mailer ### +MAILER_DSN=smtp://df69edb17e1644:8c349d8d7dbe61@smtp.mailtrap.io:2525?encryption=tls&auth_mode=login +MAILER_FROM_MAIL=team@root.dev +MAILER_FROM_NAME=AcmeBotName +###< symfony/mailer ### + +MESSENGER_TRANSPORT_DSN=doctrine://default + +# define your env variables for the test env here +KERNEL_CLASS='App\Kernel' +APP_SECRET='$ecretf0rt3st' +SYMFONY_DEPRECATIONS_HELPER=999999 +PANTHER_APP_ENV=panther +PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..4a344c4 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,82 @@ +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### +###> symfony/phpunit-bridge ### +.phpunit.result.cache +/phpunit.xml +###< symfony/phpunit-bridge ### + + +# Created by https://www.toptal.com/developers/gitignore/api/symfony +# Edit at https://www.toptal.com/developers/gitignore?templates=symfony + +### Symfony ### +# Cache and logs (Symfony2) +/app/cache/* +/app/logs/* +!app/cache/.gitkeep +!app/logs/.gitkeep + +# Email spool folder +/app/spool/* + +# Cache, session files and logs (Symfony3) +/var/cache/* +/var/logs/* +/var/sessions/* +!var/cache/.gitkeep +!var/logs/.gitkeep +!var/sessions/.gitkeep + +# Logs (Symfony4) +/var/log/* +!var/log/.gitkeep + +# Parameters +/app/config/parameters.yml +/app/config/parameters.ini + +# Managed by Composer +/app/bootstrap.php.cache +/var/bootstrap.php.cache +/bin/* +!bin/console +!bin/symfony_requirements +/vendor/ + +# Assets and user uploads +/web/bundles/ +/web/uploads/ + +# PHPUnit +/app/phpunit.xml +/phpunit.xml + +# Build data +/build/ + +# Composer PHAR +/composer.phar + +# Backup entities generated with doctrine:generate:entities command +**/Entity/*~ + +# Embedded web-server pid file +/.web-server-pid + +### Symfony Patch ### +/web/css/ +/web/js/ + +# End of https://www.toptal.com/developers/gitignore/api/symfony + +###> phpunit/phpunit ### +/phpunit.xml +.phpunit.result.cache +###< phpunit/phpunit ### diff --git a/app/bin/console b/app/bin/console new file mode 100755 index 0000000..c933dc5 --- /dev/null +++ b/app/bin/console @@ -0,0 +1,17 @@ +#!/usr/bin/env php +=8.1.11", + "ext-ctype": "*", + "ext-iconv": "*", + "api-platform/core": "^2.6", + "doctrine/annotations": "^1.0", + "doctrine/doctrine-bundle": "^2.7", + "doctrine/doctrine-migrations-bundle": "^3.2", + "doctrine/orm": "^2.12", + "easycorp/easyadmin-bundle": "^4.3", + "endroid/qr-code": "^4.6", + "html2text/html2text": "^4.3", + "nelmio/cors-bundle": "^2.2", + "phpdocumentor/reflection-docblock": "^5.3", + "phpstan/phpdoc-parser": "^1.6", + "scheb/2fa-backup-code": "^6.3", + "scheb/2fa-bundle": "^6.3", + "scheb/2fa-google-authenticator": "^6.3", + "scheb/2fa-trusted-device": "^6.3", + "sensio/framework-extra-bundle": "^6.1", + "stof/doctrine-extensions-bundle": "^1.7", + "symfony/asset": "6.1.*", + "symfony/console": "6.1.*", + "symfony/dependency-injection": "6.1.*", + "symfony/doctrine-messenger": "6.1.*", + "symfony/dotenv": "6.1.*", + "symfony/expression-language": "6.1.*", + "symfony/flex": "^2", + "symfony/form": "6.1.*", + "symfony/framework-bundle": "6.1.*", + "symfony/http-client": "6.1.*", + "symfony/intl": "6.1.*", + "symfony/mailer": "6.1.*", + "symfony/mime": "6.1.*", + "symfony/monolog-bundle": "^3.0", + "symfony/notifier": "6.1.*", + "symfony/password-hasher": "6.1.*", + "symfony/process": "6.1.*", + "symfony/property-access": "6.1.*", + "symfony/property-info": "6.1.*", + "symfony/proxy-manager-bridge": "6.1.*", + "symfony/rate-limiter": "6.1.*", + "symfony/runtime": "6.1.*", + "symfony/security-bundle": "6.1.*", + "symfony/serializer": "6.1.*", + "symfony/string": "6.1.*", + "symfony/translation": "6.1.*", + "symfony/twig-bundle": "6.1.*", + "symfony/uid": "6.1.*", + "symfony/validator": "6.1.*", + "symfony/web-link": "6.1.*", + "symfony/yaml": "6.1.*", + "symfonycasts/reset-password-bundle": "^1.14", + "symfonycasts/verify-email-bundle": "^1.11", + "twig/extra-bundle": "^3.4", + "twig/twig": "^2.12|^3.0" + }, + "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^3.4", + "phpunit/phpunit": "^9", + "symfony/browser-kit": "6.1.*", + "symfony/css-selector": "6.1.*", + "symfony/debug-bundle": "6.1.*", + "symfony/maker-bundle": "^1.0", + "symfony/phpunit-bridge": "*", + "symfony/stopwatch": "6.1.*", + "symfony/web-profiler-bundle": "6.1.*" + }, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "optimize-autoloader": true, + "preferred-install": { + "*": "dist" + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } + }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php73": "*", + "symfony/polyfill-php74": "*", + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*" + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ] + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "6.1.*" + } + } +} diff --git a/app/composer.lock b/app/composer.lock new file mode 100644 index 0000000..7bbaabc --- /dev/null +++ b/app/composer.lock @@ -0,0 +1,11663 @@ +{ + "_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": "934073d75b70361ded0af471c8d13d54", + "packages": [ + { + "name": "api-platform/core", + "version": "v2.7.2", + "source": { + "type": "git", + "url": "https://github.com/api-platform/core.git", + "reference": "80c3f3c38b9ac234bde0cbc2b77d6628326bdefc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/api-platform/core/zipball/80c3f3c38b9ac234bde0cbc2b77d6628326bdefc", + "reference": "80c3f3c38b9ac234bde0cbc2b77d6628326bdefc", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^1.0 || ^2.0", + "php": ">=7.1", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/http-foundation": "^4.4 || ^5.1 || ^6.0", + "symfony/http-kernel": "^4.4 || ^5.1 || ^6.0", + "symfony/property-access": "^3.4.19 || ^4.4 || ^5.1 || ^6.0", + "symfony/property-info": "^3.4 || ^4.4 || ^5.2.1 || ^6.0", + "symfony/serializer": "^4.4 || ^5.1 || ^6.0", + "symfony/web-link": "^4.4 || ^5.1 || ^6.0", + "willdurand/negotiation": "^2.0.3 || ^3.0" + }, + "conflict": { + "doctrine/common": "<2.7", + "doctrine/dbal": "<2.10", + "doctrine/mongodb-odm": "<2.2", + "doctrine/persistence": "<1.3", + "elasticsearch/elasticsearch": ">=8.0" + }, + "require-dev": { + "behat/behat": "^3.1", + "behat/mink": "^1.9@dev", + "doctrine/annotations": "^1.7", + "doctrine/cache": "^1.11 || ^2.1", + "doctrine/common": "^2.11 || ^3.0", + "doctrine/data-fixtures": "^1.2.2", + "doctrine/dbal": "^2.6 || ^3.0", + "doctrine/doctrine-bundle": "^1.12 || ^2.0", + "doctrine/mongodb-odm": "^2.2", + "doctrine/mongodb-odm-bundle": "^4.0", + "doctrine/orm": "^2.6.4", + "elasticsearch/elasticsearch": "^7.11.0", + "friends-of-behat/mink-browserkit-driver": "^1.3.1", + "friends-of-behat/mink-extension": "^2.2", + "friends-of-behat/symfony-extension": "^2.1", + "guzzlehttp/guzzle": "^6.0 || ^7.0", + "jangregor/phpstan-prophecy": "^1.0", + "justinrainbow/json-schema": "^5.2.1", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.1", + "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.4", + "phpspec/prophecy": "^1.10", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-doctrine": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-symfony": "^1.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "ramsey/uuid": "^3.7 || ^4.0", + "ramsey/uuid-doctrine": "^1.4", + "soyuka/contexts": "dev-main", + "soyuka/stubs-mongodb": "^1.0", + "symfony/asset": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/browser-kit": "^4.4 || ^5.1 || ^6.0", + "symfony/cache": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/config": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/console": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/css-selector": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/debug": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/dependency-injection": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/doctrine-bridge": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/dom-crawler": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/event-dispatcher": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/expression-language": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/finder": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/form": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/framework-bundle": "^4.4 || ^5.1 || ^6.0", + "symfony/http-client": "^4.4 || ^5.1 || ^6.0", + "symfony/intl": "^4.4 || ^5.3 || ^6.0", + "symfony/maker-bundle": "^1.24", + "symfony/mercure-bundle": "*", + "symfony/messenger": "^4.4 || ^5.1 || ^6.0", + "symfony/phpunit-bridge": "^5.4 || ^6.0", + "symfony/routing": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/security-bundle": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/security-core": "^4.4 || ^5.1 || ^6.0", + "symfony/twig-bundle": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/validator": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "symfony/web-profiler-bundle": "^4.4 || ^5.1 || ^6.0", + "symfony/yaml": "^3.4 || ^4.4 || ^5.1 || ^6.0", + "twig/twig": "^1.42.3 || ^2.12 || ^3.0", + "webonyx/graphql-php": "^14.0" + }, + "suggest": { + "doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.", + "elasticsearch/elasticsearch": "To support Elasticsearch.", + "ocramius/package-versions": "To display the API Platform's version in the debug bar.", + "phpdocumentor/reflection-docblock": "To support extracting metadata from PHPDoc.", + "psr/cache-implementation": "To use metadata caching.", + "ramsey/uuid": "To support Ramsey's UUID identifiers.", + "symfony/cache": "To have metadata caching when using Symfony integration.", + "symfony/config": "To load XML configuration files.", + "symfony/expression-language": "To use authorization features.", + "symfony/http-client": "To use the HTTP cache invalidation system.", + "symfony/messenger": "To support messenger integration.", + "symfony/security": "To use authorization features.", + "symfony/twig-bundle": "To use the Swagger UI integration.", + "symfony/uid": "To support Symfony UUID/ULID identifiers.", + "symfony/web-profiler-bundle": "To use the data collector.", + "webonyx/graphql-php": "To support GraphQL." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.7.x-dev" + }, + "symfony": { + "require": "^3.4 || ^4.4 || ^5.1 || ^6.0" + } + }, + "autoload": { + "files": [ + "src/deprecation.php" + ], + "psr-4": { + "ApiPlatform\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + } + ], + "description": "Build a fully-featured hypermedia or GraphQL API in minutes!", + "homepage": "https://api-platform.com", + "keywords": [ + "Hydra", + "JSON-LD", + "api", + "graphql", + "hal", + "jsonapi", + "openapi", + "rest", + "swagger" + ], + "support": { + "issues": "https://github.com/api-platform/core/issues", + "source": "https://github.com/api-platform/core/tree/v2.7.2" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/api-platform/core", + "type": "tidelift" + } + ], + "time": "2022-10-07T09:12:23+00:00" + }, + { + "name": "bacon/bacon-qr-code", + "version": "2.0.7", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/d70c840f68657ce49094b8d91f9ee0cc07fbf66c", + "reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c", + "shasum": "" + }, + "require": { + "dasprid/enum": "^1.0.3", + "ext-iconv": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phly/keep-a-changelog": "^2.1", + "phpunit/phpunit": "^7 | ^8 | ^9", + "spatie/phpunit-snapshot-assertions": "^4.2.9", + "squizlabs/php_codesniffer": "^3.4" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "type": "library", + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "support": { + "issues": "https://github.com/Bacon/BaconQrCode/issues", + "source": "https://github.com/Bacon/BaconQrCode/tree/2.0.7" + }, + "time": "2022-03-14T02:02:36+00:00" + }, + { + "name": "behat/transliterator", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Transliterator.git", + "reference": "baac5873bac3749887d28ab68e2f74db3a4408af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/baac5873bac3749887d28ab68e2f74db3a4408af", + "reference": "baac5873bac3749887d28ab68e2f74db3a4408af", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "chuyskywalker/rolling-curl": "^3.1", + "php-yaoi/php-yaoi": "^1.0", + "phpunit/phpunit": "^8.5.25 || ^9.5.19" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Transliterator\\": "src/Behat/Transliterator" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Artistic-1.0" + ], + "description": "String transliterator", + "keywords": [ + "i18n", + "slug", + "transliterator" + ], + "support": { + "issues": "https://github.com/Behat/Transliterator/issues", + "source": "https://github.com/Behat/Transliterator/tree/v1.5.0" + }, + "time": "2022-03-30T09:27:43+00:00" + }, + { + "name": "dasprid/enum", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "5abf82f213618696dda8e3bf6f64dd042d8542b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/5abf82f213618696dda8e3bf6f64dd042d8542b2", + "reference": "5abf82f213618696dda8e3bf6f64dd042d8542b2", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^7 | ^8 | ^9", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "support": { + "issues": "https://github.com/DASPRiD/Enum/issues", + "source": "https://github.com/DASPRiD/Enum/tree/1.0.3" + }, + "time": "2020-10-02T16:03:48+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.13.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", + "symfony/cache": "^4.4 || ^5.2", + "vimeo/psalm": "^4.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.13.3" + }, + "time": "2022-07-02T10:48:51+00:00" + }, + { + "name": "doctrine/cache", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2022-05-20T20:07:39+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e", + "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^0.5.3 || ^1", + "php": "^7.1.3 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0 || ^10.0", + "phpstan/phpstan": "^1.4.8", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5", + "vimeo/psalm": "^4.22" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/1.8.0" + }, + "time": "2022-09-01T20:12:10+00:00" + }, + { + "name": "doctrine/common", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/8b5e5650391f851ed58910b3e3d48a71062eeced", + "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced", + "shasum": "" + }, + "require": { + "doctrine/persistence": "^2.0 || ^3.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0 || ^10.0", + "doctrine/collections": "^1", + "phpstan/phpstan": "^1.4.1", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^6.1", + "vimeo/psalm": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/common/issues", + "source": "https://github.com/doctrine/common/tree/3.4.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", + "type": "tidelift" + } + ], + "time": "2022-10-09T11:47:59+00:00" + }, + { + "name": "doctrine/dbal", + "version": "3.4.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "a5a58773109c0abb13e658c8ccd92aeec8d07f9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/a5a58773109c0abb13e658c8ccd92aeec8d07f9e", + "reference": "a5a58773109c0abb13e658c8ccd92aeec8d07f9e", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1.0", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "10.0.0", + "jetbrains/phpstorm-stubs": "2022.2", + "phpstan/phpstan": "1.8.3", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "9.5.24", + "psalm/plugin-phpunit": "0.17.0", + "squizlabs/php_codesniffer": "3.7.1", + "symfony/cache": "^5.4|^6.0", + "symfony/console": "^4.4|^5.4|^6.0", + "vimeo/psalm": "4.27.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.4.5" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2022-09-23T17:48:57+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" + }, + { + "name": "doctrine/doctrine-bundle", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "d2088fc50494e4e7441fecca54732245a613eeb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/d2088fc50494e4e7441fecca54732245a613eeb6", + "reference": "d2088fc50494e4e7441fecca54732245a613eeb6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1", + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/dbal": "^2.13.1|^3.3.2", + "doctrine/persistence": "^2.2|^3", + "doctrine/sql-formatter": "^1.0.1", + "php": "^7.1 || ^8.0", + "symfony/cache": "^4.3.3|^5.0|^6.0", + "symfony/config": "^4.4.3|^5.0|^6.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/dependency-injection": "^4.4.18|^5.0|^6.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/doctrine-bridge": "^4.4.22|^5.2.7|^6.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/service-contracts": "^1.1.1|^2.0|^3" + }, + "conflict": { + "doctrine/orm": "<2.10|>=3.0", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "doctrine/orm": "^2.11 || ^3.0", + "friendsofphp/proxy-manager-lts": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3 || ^10.0", + "psalm/plugin-phpunit": "^0.16.1", + "psalm/plugin-symfony": "^3", + "psr/log": "^1.1.4|^2.0|^3.0", + "symfony/phpunit-bridge": "^5.2|^6.0", + "symfony/property-info": "^4.3.3|^5.0|^6.0", + "symfony/proxy-manager-bridge": "^3.4|^4.3.3|^5.0|^6.0", + "symfony/security-bundle": "^4.4|^5.0|^6.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0|^6.0", + "twig/twig": "^1.34|^2.12|^3.0", + "vimeo/psalm": "^4.7" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "ext-pdo": "*", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\DoctrineBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org/" + } + ], + "description": "Symfony DoctrineBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "orm", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineBundle/issues", + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.7.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", + "type": "tidelift" + } + ], + "time": "2022-06-10T10:55:26+00:00" + }, + { + "name": "doctrine/doctrine-migrations-bundle", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", + "reference": "3393f411ba25ade21969c33f2053220044854d01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/3393f411ba25ade21969c33f2053220044854d01", + "reference": "3393f411ba25ade21969c33f2053220044854d01", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "~1.0|~2.0", + "doctrine/migrations": "^3.2", + "php": "^7.2|^8.0", + "symfony/framework-bundle": "~3.4|~4.0|~5.0|~6.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "doctrine/orm": "^2.6", + "doctrine/persistence": "^1.3||^2.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^8.0|^9.0", + "vimeo/psalm": "^4.11" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\MigrationsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineMigrationsBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "dbal", + "migrations", + "schema" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.2.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2022-02-01T18:08:07+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", + "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^0.5.3 || ^1", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.8", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.24" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2022-10-12T20:51:15+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ade2b3bbfb776f27f0558e26eed43b5d9fe1b392", + "reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.5" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2022-09-07T09:01:28+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-03-03T08:28:38+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-02-28T11:07:21+00:00" + }, + { + "name": "doctrine/migrations", + "version": "3.5.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "61c6ef3a10b7df43c3b6388a184754f26e58700a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/61c6ef3a10b7df43c3b6388a184754f26e58700a", + "reference": "61c6ef3a10b7df43c3b6388a184754f26e58700a", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.3", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.0", + "friendsofphp/proxy-manager-lts": "^1.0", + "php": "^7.4 || ^8.0", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^4.4.16 || ^5.4 || ^6.0", + "symfony/stopwatch": "^4.4 || ^5.4 || ^6.0" + }, + "conflict": { + "doctrine/orm": "<2.12" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "doctrine/orm": "^2.12", + "doctrine/persistence": "^2 || ^3", + "doctrine/sql-formatter": "^1.0", + "ergebnis/composer-normalize": "^2.9", + "ext-pdo_sqlite": "*", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpstan/phpstan-symfony": "^1.1", + "phpunit/phpunit": "^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0", + "symfony/process": "^4.4 || ^5.4 || ^6.0", + "symfony/yaml": "^4.4 || ^5.4 || ^6.0" + }, + "suggest": { + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "extra": { + "composer-normalize": { + "indent-size": 4, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "dbal", + "migrations" + ], + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.5.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2022-08-04T14:29:49+00:00" + }, + { + "name": "doctrine/orm", + "version": "2.13.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "e750360bd52b080c4cbaaee1b48b80f7dc873b36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/e750360bd52b080c4cbaaee1b48b80f7dc873b36", + "reference": "e750360bd52b080c4cbaaee1b48b80f7dc873b36", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.12.1 || ^2.1.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^3.0.3", + "doctrine/dbal": "^2.13.1 || ^3.2", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.1", + "doctrine/inflector": "^1.4 || ^2.0", + "doctrine/instantiator": "^1.3", + "doctrine/lexer": "^1.2.3", + "doctrine/persistence": "^2.4 || ^3", + "ext-ctype": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3", + "symfony/console": "^3.0 || ^4.0 || ^5.0 || ^6.0", + "symfony/polyfill-php72": "^1.23", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "doctrine/annotations": "<1.13 || >= 2.0" + }, + "require-dev": { + "doctrine/annotations": "^1.13", + "doctrine/coding-standard": "^9.0.2 || ^10.0", + "phpbench/phpbench": "^0.16.10 || ^1.0", + "phpstan/phpstan": "~1.4.10 || 1.8.5", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/log": "^1 || ^2 || ^3", + "squizlabs/php_codesniffer": "3.7.1", + "symfony/cache": "^4.4 || ^5.4 || ^6.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0", + "vimeo/psalm": "4.27.0" + }, + "suggest": { + "ext-dom": "Provides support for XSD validation for XML mapping files", + "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0", + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ], + "support": { + "issues": "https://github.com/doctrine/orm/issues", + "source": "https://github.com/doctrine/orm/tree/2.13.3" + }, + "time": "2022-10-07T06:37:17+00:00" + }, + { + "name": "doctrine/persistence", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "05612da375f8a3931161f435f91d6704926e6ec5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/05612da375f8a3931161f435f91d6704926e6ec5", + "reference": "05612da375f8a3931161f435f91d6704926e6ec5", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "^1 || ^2", + "php": "^7.2 || ^8.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0" + }, + "conflict": { + "doctrine/annotations": "<1.7 || >=2.0", + "doctrine/common": "<2.10" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^1.7", + "doctrine/coding-standard": "^10", + "doctrine/common": "^3.0", + "phpstan/phpstan": "1.8.8", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0", + "vimeo/psalm": "4.29.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Persistence\\": "src/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://www.doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/persistence/issues", + "source": "https://github.com/doctrine/persistence/tree/3.0.4" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", + "type": "tidelift" + } + ], + "time": "2022-10-13T07:34:14+00:00" + }, + { + "name": "doctrine/sql-formatter", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", + "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4" + }, + "bin": [ + "bin/sql-formatter" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\SqlFormatter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "https://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/doctrine/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "support": { + "issues": "https://github.com/doctrine/sql-formatter/issues", + "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" + }, + "time": "2022-05-23T21:33:49+00:00" + }, + { + "name": "easycorp/easyadmin-bundle", + "version": "v4.4.0", + "source": { + "type": "git", + "url": "https://github.com/EasyCorp/EasyAdminBundle.git", + "reference": "dd1ed80a0a7c26e7ae0a0788a3cbc296d835560e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/dd1ed80a0a7c26e7ae0a0788a3cbc296d835560e", + "reference": "dd1ed80a0a7c26e7ae0a0788a3cbc296d835560e", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "^2.5", + "doctrine/orm": "^2.10", + "ext-json": "*", + "php": ">=8.0.2", + "symfony/asset": "^5.4|^6.0", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/deprecation-contracts": "^3.0", + "symfony/doctrine-bridge": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/framework-bundle": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/security-bundle": "^5.4|^6.0", + "symfony/string": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/twig-bundle": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0" + }, + "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^3.4", + "psr/log": "^1.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/phpunit-bridge": "^5.4|^6.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "EasyCorp\\Bundle\\EasyAdminBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Project Contributors", + "homepage": "https://github.com/EasyCorp/EasyAdminBundle/graphs/contributors" + } + ], + "description": "Admin generator for Symfony applications", + "homepage": "https://github.com/EasyCorp/EasyAdminBundle", + "keywords": [ + "admin", + "backend", + "generator" + ], + "support": { + "issues": "https://github.com/EasyCorp/EasyAdminBundle/issues", + "source": "https://github.com/EasyCorp/EasyAdminBundle/tree/v4.4.0" + }, + "funding": [ + { + "url": "https://github.com/javiereguiluz", + "type": "github" + } + ], + "time": "2022-10-05T18:13:05+00:00" + }, + { + "name": "egulias/email-validator", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "f88dcf4b14af14a98ad96b14b2b317969eab6715" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/f88dcf4b14af14a98ad96b14b2b317969eab6715", + "reference": "f88dcf4b14af14a98ad96b14b2b317969eab6715", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.2", + "php": ">=7.2", + "symfony/polyfill-intl-idn": "^1.15" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^8.5.8|^9.3.3", + "vimeo/psalm": "^4" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2022-06-18T20:57:19+00:00" + }, + { + "name": "endroid/qr-code", + "version": "4.6.0", + "source": { + "type": "git", + "url": "https://github.com/endroid/qr-code.git", + "reference": "b60873b14e2ca7bf3c3746f5e032023095a7e05c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/b60873b14e2ca7bf3c3746f5e032023095a7e05c", + "reference": "b60873b14e2ca7bf3c3746f5e032023095a7e05c", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "^2.0.5", + "php": "^7.4||^8.0" + }, + "require-dev": { + "endroid/quality": "dev-master", + "ext-gd": "*", + "khanamiryan/qrcode-detector-decoder": "^1.0.4", + "setasign/fpdf": "^1.8.2" + }, + "suggest": { + "ext-gd": "Enables you to write PNG images", + "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator", + "roave/security-advisories": "Makes sure package versions with known security issues are not installed", + "setasign/fpdf": "Enables you to use the PDF writer" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Endroid\\QrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeroen van den Enden", + "email": "info@endroid.nl" + } + ], + "description": "Endroid QR Code", + "homepage": "https://github.com/endroid/qr-code", + "keywords": [ + "code", + "endroid", + "php", + "qr", + "qrcode" + ], + "support": { + "issues": "https://github.com/endroid/qr-code/issues", + "source": "https://github.com/endroid/qr-code/tree/4.6.0" + }, + "funding": [ + { + "url": "https://github.com/endroid", + "type": "github" + } + ], + "time": "2022-10-04T17:13:41+00:00" + }, + { + "name": "friendsofphp/proxy-manager-lts", + "version": "v1.0.12", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/proxy-manager-lts.git", + "reference": "8419f0158715b30d4b99a5bd37c6a39671994ad7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/8419f0158715b30d4b99a5bd37c6a39671994ad7", + "reference": "8419f0158715b30d4b99a5bd37c6a39671994ad7", + "shasum": "" + }, + "require": { + "laminas/laminas-code": "~3.4.1|^4.0", + "php": ">=7.1", + "symfony/filesystem": "^4.4.17|^5.0|^6.0" + }, + "conflict": { + "laminas/laminas-stdlib": "<3.2.1", + "zendframework/zend-stdlib": "<3.2.1" + }, + "replace": { + "ocramius/proxy-manager": "^2.1" + }, + "require-dev": { + "ext-phar": "*", + "symfony/phpunit-bridge": "^5.4|^6.0" + }, + "type": "library", + "extra": { + "thanks": { + "name": "ocramius/proxy-manager", + "url": "https://github.com/Ocramius/ProxyManager" + } + }, + "autoload": { + "psr-4": { + "ProxyManager\\": "src/ProxyManager" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Adding support for a wider range of PHP versions to ocramius/proxy-manager", + "homepage": "https://github.com/FriendsOfPHP/proxy-manager-lts", + "keywords": [ + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" + ], + "support": { + "issues": "https://github.com/FriendsOfPHP/proxy-manager-lts/issues", + "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.12" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", + "type": "tidelift" + } + ], + "time": "2022-05-05T09:31:05+00:00" + }, + { + "name": "gedmo/doctrine-extensions", + "version": "v3.9.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine-extensions/DoctrineExtensions.git", + "reference": "d869cf11f12995b27fa6486ec2a860cc76c46988" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/d869cf11f12995b27fa6486ec2a860cc76c46988", + "reference": "d869cf11f12995b27fa6486ec2a860cc76c46988", + "shasum": "" + }, + "require": { + "behat/transliterator": "~1.2", + "doctrine/annotations": "^1.13", + "doctrine/collections": "^1.0", + "doctrine/common": "^2.13 || ^3.0", + "doctrine/event-manager": "^1.0", + "doctrine/persistence": "^2.2 || ^3.0", + "php": "^7.2 || ^8.0", + "psr/cache": "^1 || ^2 || ^3", + "symfony/cache": "^4.4 || ^5.3 || ^6.0" + }, + "conflict": { + "doctrine/cache": "<1.11", + "doctrine/dbal": "<2.13.1 || ^3.0 <3.2", + "doctrine/mongodb-odm": "<2.3", + "doctrine/orm": "<2.10.2", + "sebastian/comparator": "<2.0" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/dbal": "^2.13.1 || ^3.2", + "doctrine/doctrine-bundle": "^2.3", + "doctrine/mongodb-odm": "^2.3", + "doctrine/orm": "^2.10.2", + "friendsofphp/php-cs-fixer": "^3.4.0,<3.10", + "nesbot/carbon": "^2.55", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-doctrine": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/console": "^4.4 || ^5.3 || ^6.0", + "symfony/phpunit-bridge": "^6.0", + "symfony/yaml": "^4.4 || ^5.3 || ^6.0" + }, + "suggest": { + "doctrine/mongodb-odm": "to use the extensions with the MongoDB ODM", + "doctrine/orm": "to use the extensions with the ORM", + "symfony/cache": "to cache parsed annotations" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.10-dev" + } + }, + "autoload": { + "psr-4": { + "Gedmo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gediminas Morkevicius", + "email": "gediminas.morkevicius@gmail.com" + }, + { + "name": "Gustavo Falco", + "email": "comfortablynumb84@gmail.com" + }, + { + "name": "David Buchmann", + "email": "david@liip.ch" + } + ], + "description": "Doctrine2 behavioral extensions", + "homepage": "http://gediminasm.org/", + "keywords": [ + "Blameable", + "behaviors", + "doctrine2", + "extensions", + "gedmo", + "loggable", + "nestedset", + "sluggable", + "sortable", + "timestampable", + "translatable", + "tree", + "uploadable" + ], + "support": { + "email": "gediminas.morkevicius@gmail.com", + "issues": "https://github.com/doctrine-extensions/DoctrineExtensions/issues", + "source": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.9.0", + "wiki": "https://github.com/Atlantic18/DoctrineExtensions/tree/main/doc" + }, + "time": "2022-09-22T02:37:53+00:00" + }, + { + "name": "html2text/html2text", + "version": "4.3.1", + "source": { + "type": "git", + "url": "https://github.com/mtibben/html2text.git", + "reference": "61ad68e934066a6f8df29a3d23a6460536d0855c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mtibben/html2text/zipball/61ad68e934066a6f8df29a3d23a6460536d0855c", + "reference": "61ad68e934066a6f8df29a3d23a6460536d0855c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-mbstring": "For best performance", + "symfony/polyfill-mbstring": "If you can't install ext-mbstring" + }, + "type": "library", + "autoload": { + "psr-4": { + "Html2Text\\": [ + "src/", + "test/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Converts HTML to formatted plain text", + "support": { + "issues": "https://github.com/mtibben/html2text/issues", + "source": "https://github.com/mtibben/html2text/tree/4.3.1" + }, + "time": "2020-04-16T23:44:31+00:00" + }, + { + "name": "laminas/laminas-code", + "version": "4.7.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-code.git", + "reference": "0337d9265bc2e6376babad8c511500821620cb30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/0337d9265bc2e6376babad8c511500821620cb30", + "reference": "0337d9265bc2e6376babad8c511500821620cb30", + "shasum": "" + }, + "require": { + "php": ">=7.4, <8.2" + }, + "require-dev": { + "doctrine/annotations": "^1.13.2", + "ext-phar": "*", + "laminas/laminas-coding-standard": "^2.3.0", + "laminas/laminas-stdlib": "^3.6.1", + "phpunit/phpunit": "^9.5.10", + "psalm/plugin-phpunit": "^0.17.0", + "vimeo/psalm": "^4.13.1" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "laminas/laminas-stdlib": "Laminas\\Stdlib component" + }, + "type": "library", + "autoload": { + "files": [ + "polyfill/ReflectionEnumPolyfill.php" + ], + "psr-4": { + "Laminas\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", + "homepage": "https://laminas.dev", + "keywords": [ + "code", + "laminas", + "laminasframework" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-code/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-code/issues", + "rss": "https://github.com/laminas/laminas-code/releases.atom", + "source": "https://github.com/laminas/laminas-code" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2022-09-13T10:33:30+00:00" + }, + { + "name": "lcobucci/clock", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/fb533e093fd61321bfcbac08b131ce805fe183d3", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3", + "shasum": "" + }, + "require": { + "php": "^8.0", + "stella-maris/clock": "^0.1.4" + }, + "require-dev": { + "infection/infection": "^0.26", + "lcobucci/coding-standard": "^8.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "support": { + "issues": "https://github.com/lcobucci/clock/issues", + "source": "https://github.com/lcobucci/clock/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2022-04-19T19:34:17+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "4.2.1", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/72ac6d807ee51a70ad376ee03a2387e8646e10f3", + "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3", + "shasum": "" + }, + "require": { + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-sodium": "*", + "lcobucci/clock": "^2.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "infection/infection": "^0.21", + "lcobucci/coding-standard": "^6.0", + "mikey179/vfsstream": "^1.6.7", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/php-invoker": "^3.1", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "support": { + "issues": "https://github.com/lcobucci/jwt/issues", + "source": "https://github.com/lcobucci/jwt/tree/4.2.1" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2022-08-19T23:14:07+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81", + "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^9.5.16", + "predis/predis": "^1.1", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2022-07-24T12:00:55+00:00" + }, + { + "name": "nelmio/cors-bundle", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/nelmio/NelmioCorsBundle.git", + "reference": "0ee5ee30b0ee08ea122d431ae6e0ddeb87f035c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/0ee5ee30b0ee08ea122d431ae6e0ddeb87f035c0", + "reference": "0ee5ee30b0ee08ea122d431ae6e0ddeb87f035c0", + "shasum": "" + }, + "require": { + "symfony/framework-bundle": "^4.3 || ^5.0 || ^6.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "symfony/phpunit-bridge": "^4.3 || ^5.0 || ^6.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Nelmio\\CorsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nelmio", + "homepage": "http://nelm.io" + }, + { + "name": "Symfony Community", + "homepage": "https://github.com/nelmio/NelmioCorsBundle/contributors" + } + ], + "description": "Adds CORS (Cross-Origin Resource Sharing) headers support in your Symfony application", + "keywords": [ + "api", + "cors", + "crossdomain" + ], + "support": { + "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.2.0" + }, + "time": "2021-12-01T09:34:27+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.6.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "58c3f47f650c94ec05a151692652a868995d2938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", + "reference": "58c3f47f650c94ec05a151692652a868995d2938", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2022-06-14T06:56:20+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.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "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.2" + }, + "time": "2022-10-14T12:47:21+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65", + "reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65", + "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.11.0" + }, + "time": "2022-10-14T13:32:28+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "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", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/link", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "84b159194ecfd7eaa472280213976e96415433f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7", + "reference": "84b159194ecfd7eaa472280213976e96415433f7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "suggest": { + "fig/link-util": "Provides some useful PSR-13 utilities" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "homepage": "https://github.com/php-fig/link", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "source": "https://github.com/php-fig/link/tree/2.0.1" + }, + "time": "2021-03-11T23:00:27+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": "scheb/2fa-backup-code", + "version": "v6.3.0", + "source": { + "type": "git", + "url": "https://github.com/scheb/2fa-backup-code.git", + "reference": "9d91d2f6c67acaa710d5d03aa71f5f490ac86d1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scheb/2fa-backup-code/zipball/9d91d2f6c67acaa710d5d03aa71f5f490ac86d1f", + "reference": "9d91d2f6c67acaa710d5d03aa71f5f490ac86d1f", + "shasum": "" + }, + "require": { + "php": "~8.0.0 || ~8.1.0", + "scheb/2fa-bundle": "self.version" + }, + "type": "library", + "autoload": { + "psr-4": { + "Scheb\\TwoFactorBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Scheb", + "email": "me@christianscheb.de" + } + ], + "description": "Extends scheb/2fa-bundle with backup codes support", + "homepage": "https://github.com/scheb/2fa", + "keywords": [ + "2fa", + "Authentication", + "backup-codes", + "symfony", + "two-factor", + "two-step" + ], + "support": { + "source": "https://github.com/scheb/2fa-backup-code/tree/v6.3.0" + }, + "time": "2022-01-03T10:16:52+00:00" + }, + { + "name": "scheb/2fa-bundle", + "version": "v6.3.0", + "source": { + "type": "git", + "url": "https://github.com/scheb/2fa-bundle.git", + "reference": "ffd3e73ba2984a326ea554663de85e58ef221f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scheb/2fa-bundle/zipball/ffd3e73ba2984a326ea554663de85e58ef221f11", + "reference": "ffd3e73ba2984a326ea554663de85e58ef221f11", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "~8.0.0 || ~8.1.0", + "symfony/config": "^5.4 || ^6.0", + "symfony/dependency-injection": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/framework-bundle": "^5.4 || ^6.0", + "symfony/http-foundation": "^5.4 || ^6.0", + "symfony/http-kernel": "^5.4 || ^6.0", + "symfony/property-access": "^5.4 || ^6.0", + "symfony/security-bundle": "^5.4 || ^6.0", + "symfony/twig-bundle": "^5.4 || ^6.0" + }, + "conflict": { + "scheb/two-factor-bundle": "*" + }, + "suggest": { + "scheb/2fa-backup-code": "Emergency codes when you have no access to other methods", + "scheb/2fa-email": "Send codes by email", + "scheb/2fa-google-authenticator": "Google Authenticator support", + "scheb/2fa-totp": "Temporary one-time password (TOTP) support (Google Authenticator compatible)", + "scheb/2fa-trusted-device": "Trusted devices support" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Scheb\\TwoFactorBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Scheb", + "email": "me@christianscheb.de" + } + ], + "description": "A generic interface to implement two-factor authentication in Symfony applications", + "homepage": "https://github.com/scheb/2fa", + "keywords": [ + "2fa", + "Authentication", + "symfony", + "two-factor", + "two-step" + ], + "support": { + "source": "https://github.com/scheb/2fa-bundle/tree/v6.3.0" + }, + "time": "2022-09-01T17:42:58+00:00" + }, + { + "name": "scheb/2fa-google-authenticator", + "version": "v6.3.0", + "source": { + "type": "git", + "url": "https://github.com/scheb/2fa-google-authenticator.git", + "reference": "fd0c2533f287d9687f9317fd48ff44d2e613e32a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scheb/2fa-google-authenticator/zipball/fd0c2533f287d9687f9317fd48ff44d2e613e32a", + "reference": "fd0c2533f287d9687f9317fd48ff44d2e613e32a", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2.4", + "php": "~8.0.0 || ~8.1.0", + "scheb/2fa-bundle": "self.version", + "spomky-labs/otphp": "^10.0 || ^11.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Scheb\\TwoFactorBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Scheb", + "email": "me@christianscheb.de" + } + ], + "description": "Extends scheb/2fa-bundle with two-factor authentication using Google Authenticator", + "homepage": "https://github.com/scheb/2fa", + "keywords": [ + "2fa", + "Authentication", + "google-authenticator", + "symfony", + "two-factor", + "two-step" + ], + "support": { + "source": "https://github.com/scheb/2fa-google-authenticator/tree/v6.3.0" + }, + "time": "2022-08-01T17:19:20+00:00" + }, + { + "name": "scheb/2fa-trusted-device", + "version": "v6.3.0", + "source": { + "type": "git", + "url": "https://github.com/scheb/2fa-trusted-device.git", + "reference": "adde81332dbae1e5f4b485ed9e13458e7809806b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scheb/2fa-trusted-device/zipball/adde81332dbae1e5f4b485ed9e13458e7809806b", + "reference": "adde81332dbae1e5f4b485ed9e13458e7809806b", + "shasum": "" + }, + "require": { + "lcobucci/clock": "^2.0", + "lcobucci/jwt": "^4.0", + "php": "~8.0.0 || ~8.1.0", + "scheb/2fa-bundle": "self.version" + }, + "type": "library", + "autoload": { + "psr-4": { + "Scheb\\TwoFactorBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Scheb", + "email": "me@christianscheb.de" + } + ], + "description": "Extends scheb/2fa-bundle with trusted devices support", + "homepage": "https://github.com/scheb/2fa", + "keywords": [ + "2fa", + "Authentication", + "symfony", + "trusted-device", + "two-factor", + "two-step" + ], + "support": { + "source": "https://github.com/scheb/2fa-trusted-device/tree/v6.3.0" + }, + "time": "2022-09-01T17:42:58+00:00" + }, + { + "name": "sensio/framework-extra-bundle", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", + "reference": "bb962f8aed09e60b0942545f6e4842ffeee4aafd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/bb962f8aed09e60b0942545f6e4842ffeee4aafd", + "reference": "bb962f8aed09e60b0942545f6e4842ffeee4aafd", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "php": ">=7.2.5", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/framework-bundle": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0" + }, + "conflict": { + "doctrine/doctrine-cache-bundle": "<1.3.1", + "doctrine/persistence": "<1.3" + }, + "require-dev": { + "doctrine/dbal": "^2.10|^3.0", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.5", + "symfony/browser-kit": "^4.4|^5.0|^6.0", + "symfony/doctrine-bridge": "^4.4|^5.0|^6.0", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/monolog-bridge": "^4.0|^5.0|^6.0", + "symfony/monolog-bundle": "^3.2", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", + "symfony/security-bundle": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0", + "twig/twig": "^1.34|^2.4|^3.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "6.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sensio\\Bundle\\FrameworkExtraBundle\\": "src/" + }, + "exclude-from-classmap": [ + "/tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "This bundle provides a way to configure your controllers with annotations", + "keywords": [ + "annotations", + "controllers" + ], + "support": { + "issues": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/issues", + "source": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/tree/v6.2.8" + }, + "time": "2022-09-05T16:44:56+00:00" + }, + { + "name": "spomky-labs/otphp", + "version": "v11.0.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "8cf16dcb41d35f04842ef38e7e61bfaa228f6c2b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/8cf16dcb41d35f04842ef38e7e61bfaa228f6c2b", + "reference": "8cf16dcb41d35f04842ef38e7e61bfaa228f6c2b", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "paragonie/constant_time_encoding": "^2.0", + "php": "^8.1" + }, + "require-dev": { + "ekino/phpstan-banned-code": "^1.0", + "infection/infection": "^0.26", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.14", + "symfony/phpunit-bridge": "^6.0", + "symplify/easy-coding-standard": "^11.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "OTPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/otphp/issues", + "source": "https://github.com/Spomky-Labs/otphp/tree/v11.0.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2022-10-11T05:29:12+00:00" + }, + { + "name": "stella-maris/clock", + "version": "0.1.6", + "source": { + "type": "git", + "url": "https://github.com/stella-maris-solutions/clock.git", + "reference": "a94228dac03c9a8411198ce8c8dacbbe99c930c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/a94228dac03c9a8411198ce8c8dacbbe99c930c3", + "reference": "a94228dac03c9a8411198ce8c8dacbbe99c930c3", + "shasum": "" + }, + "require": { + "php": "^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "StellaMaris\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Heigl", + "role": "Maintainer" + } + ], + "description": "A pre-release of the proposed PSR-20 Clock-Interface", + "homepage": "https://gitlab.com/stella-maris/clock", + "keywords": [ + "clock", + "datetime", + "point in time", + "psr20" + ], + "support": { + "issues": "https://github.com/stella-maris-solutions/clock/issues", + "source": "https://github.com/stella-maris-solutions/clock/tree/0.1.6" + }, + "time": "2022-09-27T15:03:11+00:00" + }, + { + "name": "stof/doctrine-extensions-bundle", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/stof/StofDoctrineExtensionsBundle.git", + "reference": "a2bffca41974d1c968557b343e269a60a8d5ffa4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/a2bffca41974d1c968557b343e269a60a8d5ffa4", + "reference": "a2bffca41974d1c968557b343e269a60a8d5ffa4", + "shasum": "" + }, + "require": { + "gedmo/doctrine-extensions": "^2.3.4 || ^3.0.0", + "php": "^7.1.3 || ^8.0", + "symfony/config": "^4.4 || ^5.2 || ^6.0", + "symfony/dependency-injection": "^4.4 || ^5.2 || ^6.0", + "symfony/event-dispatcher": "^4.4 || ^5.2 || ^6.0", + "symfony/http-kernel": "^4.4 || ^5.2 || ^6.0" + }, + "require-dev": { + "symfony/mime": "^4.4 || ^5.2 || ^6.0", + "symfony/phpunit-bridge": "^v5.2.4 || ^6.0", + "symfony/security-core": "^4.4 || ^5.2 || ^6.0" + }, + "suggest": { + "doctrine/doctrine-bundle": "to use the ORM extensions", + "doctrine/mongodb-odm-bundle": "to use the MongoDB ODM extensions", + "symfony/mime": "To use the Mime component integration for Uploadable" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Stof\\DoctrineExtensionsBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + "description": "Integration of the gedmo/doctrine-extensions with Symfony", + "homepage": "https://github.com/stof/StofDoctrineExtensionsBundle", + "keywords": [ + "behaviors", + "doctrine2", + "extensions", + "gedmo", + "loggable", + "nestedset", + "sluggable", + "sortable", + "timestampable", + "translatable", + "tree" + ], + "support": { + "issues": "https://github.com/stof/StofDoctrineExtensionsBundle/issues", + "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.7.0" + }, + "time": "2021-11-22T15:17:44+00:00" + }, + { + "name": "symfony/asset", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "6065b5edc36442cb1ba98dc40f7c7f6b9e154729" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/6065b5edc36442cb1ba98dc40f7c7f6b9e154729", + "reference": "6065b5edc36442cb1ba98dc40f7c7f6b9e154729", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "symfony/http-foundation": "<5.4" + }, + "require-dev": { + "symfony/http-client": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "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": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/asset/tree/v6.1.5" + }, + "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-08-31T08:17:45+00:00" + }, + { + "name": "symfony/cache", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "9ae74e40fde37aba127ad5db65c5193f41f86f95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/9ae74e40fde37aba127ad5db65c5193f41f86f95", + "reference": "9ae74e40fde37aba127ad5db65c5193f41f86f95", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2|^3", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/var-exporter": "^5.4|^6.0" + }, + "conflict": { + "doctrine/dbal": "<2.13.1", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/var-dumper": "<5.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v6.1.5" + }, + "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-09-08T09:34:40+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "2eab7fa459af6d75c6463e63e633b667a9b761d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/2eab7fa459af6d75c6463e63e633b667a9b761d3", + "reference": "2eab7fa459af6d75c6463e63e633b667a9b761d3", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "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": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-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/config", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "a0645dc585d378b73c01115dd7ab9348f7d40c85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/a0645dc585d378b73c01115dd7ab9348f7d40c85", + "reference": "a0645dc585d378b73c01115dd7ab9348f7d40c85", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<5.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "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": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v6.1.3" + }, + "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-07-20T15:00:40+00:00" + }, + { + "name": "symfony/console", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "7fa3b9cf17363468795e539231a5c91b02b608fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/7fa3b9cf17363468795e539231a5c91b02b608fc", + "reference": "7fa3b9cf17363468795e539231a5c91b02b608fc", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "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": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "b9c797c9d56afc290d4265854bafd01b4e379240" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b9c797c9d56afc290d4265854bafd01b4e379240", + "reference": "b9c797c9d56afc290d4265854bafd01b4e379240", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/service-contracts": "^1.1.6|^2.0|^3.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<6.1", + "symfony/finder": "<5.4", + "symfony/proxy-manager-bridge": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "symfony/config": "^6.1", + "symfony/expression-language": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "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": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v6.1.5" + }, + "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-09-28T16:00:52+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/doctrine-bridge", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "5db7ac51c40d03d576b2696a6b55975e53a3dfd5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/5db7ac51c40d03d576b2696a6b55975e53a3dfd5", + "reference": "5db7ac51c40d03d576b2696a6b55975e53a3dfd5", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^2|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "doctrine/dbal": "<2.13.1", + "doctrine/lexer": "<1.1", + "doctrine/orm": "<2.7.4", + "phpunit/phpunit": "<5.4.3", + "symfony/cache": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/form": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<5.4", + "symfony/property-info": "<5.4", + "symfony/security-bundle": "<5.4", + "symfony/security-core": "<6.0", + "symfony/validator": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "^1.1", + "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/orm": "^2.7.4", + "psr/log": "^1|^2|^3", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/doctrine-messenger": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/form": "^5.4.9|^6.0.9", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/proxy-manager-bridge": "^5.4|^6.0", + "symfony/security-core": "^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "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": "Provides integration for Doctrine with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.1.6" + }, + "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-10T09:34:31+00:00" + }, + { + "name": "symfony/doctrine-messenger", + "version": "v6.1.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-messenger.git", + "reference": "b7587ed78b788a65958592ec5dccd226a0f6fd8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/b7587ed78b788a65958592ec5dccd226a0f6fd8e", + "reference": "b7587ed78b788a65958592ec5dccd226a0f6fd8e", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.13|^3.0", + "php": ">=8.1", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "doctrine/persistence": "<1.3" + }, + "require-dev": { + "doctrine/persistence": "^1.3|^2|^3", + "symfony/property-access": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" + }, + "type": "symfony-messenger-bridge", + "autoload": { + "psr-4": { + "Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": "" + }, + "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": "Symfony Doctrine Messenger Bridge", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-messenger/tree/v6.1.4" + }, + "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-08-12T13:09:07+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "568c11bcedf419e7e61f663912c3547b54de51df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/568c11bcedf419e7e61f663912c3547b54de51df", + "reference": "568c11bcedf419e7e61f663912c3547b54de51df", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "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": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "source": "https://github.com/symfony/dotenv/tree/v6.1.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-04-01T07:15:35+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "49f718e41f1b6f0fd5730895ca5b1c37defd828d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/49f718e41f1b6f0fd5730895ca5b1c37defd828d", + "reference": "49f718e41f1b6f0fd5730895ca5b1c37defd828d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^5.4|^6.0" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "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": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.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-05T16:51:07+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-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/expression-language", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "d1538560c075007d3dfd1f8e3a05e43a5ff13fd6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/d1538560c075007d3dfd1f8e3a05e43a5ff13fd6", + "reference": "d1538560c075007d3dfd1f8e3a05e43a5ff13fd6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "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": "Provides an engine that can compile and evaluate expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/expression-language/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "4d216a2beef096edf040a070117c39ca2abce307" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d216a2beef096edf040a070117c39ca2abce307", + "reference": "4d216a2beef096edf040a070117c39ca2abce307", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.1.5" + }, + "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-09-21T20:29:40+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.1.3" + }, + "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-07-29T07:42:06+00:00" + }, + { + "name": "symfony/flex", + "version": "v2.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "0763da1bdcce1d48c06778d48249905c26d34a72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/0763da1bdcce1d48c06778d48249905c26d34a72", + "reference": "0763da1bdcce1d48c06778d48249905c26d34a72", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.1", + "php": ">=8.0" + }, + "require-dev": { + "composer/composer": "^2.1", + "symfony/dotenv": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/phpunit-bridge": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "support": { + "issues": "https://github.com/symfony/flex/issues", + "source": "https://github.com/symfony/flex/tree/v2.2.3" + }, + "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-08-07T09:39:47+00:00" + }, + { + "name": "symfony/form", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/form.git", + "reference": "176a358d54c70ec70708c7cbb4e8ac93cc138e6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/form/zipball/176a358d54c70ec70708c7cbb4e8ac93cc138e6c", + "reference": "176a358d54c70ec70708c7cbb4e8ac93cc138e6c", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/options-resolver": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/doctrine-bridge": "<5.4", + "symfony/error-handler": "<5.4", + "symfony/framework-bundle": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/translation": "<5.4", + "symfony/translation-contracts": "<1.1.7", + "symfony/twig-bridge": "<5.4" + }, + "require-dev": { + "doctrine/collections": "~1.0", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/security-csrf": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/validator": "For form validation." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "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": "Allows to easily create, process and reuse HTML forms", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/form/tree/v6.1.5" + }, + "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-09-09T09:34:27+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "b79e5866a8293de00c8436836c2038ec31916ee7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b79e5866a8293de00c8436836c2038ec31916ee7", + "reference": "b79e5866a8293de00c8436836c2038ec31916ee7", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^6.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.4|^6.0" + }, + "conflict": { + "doctrine/annotations": "<1.13.1", + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<5.4", + "symfony/console": "<5.4", + "symfony/dom-crawler": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/lock": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/mime": "<5.4", + "symfony/property-access": "<5.4", + "symfony/property-info": "<5.4", + "symfony/security-core": "<5.4", + "symfony/security-csrf": "<5.4", + "symfony/serializer": "<6.1", + "symfony/stopwatch": "<5.4", + "symfony/translation": "<5.4", + "symfony/twig-bridge": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/validator": "<5.4", + "symfony/web-profiler-bundle": "<5.4", + "symfony/workflow": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13.1", + "doctrine/persistence": "^1.3|^2|^3", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^5.4|^6.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/console": "^5.4.9|^6.0.9", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/dotenv": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", + "symfony/http-client": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/mailer": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/notifier": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/rate-limiter": "^5.4|^6.0", + "symfony/security-bundle": "^5.4|^6.0", + "symfony/semaphore": "^5.4|^6.0", + "symfony/serializer": "^6.1", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/string": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/twig-bundle": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0", + "symfony/web-link": "^5.4|^6.0", + "symfony/workflow": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "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": "Provides a tight integration between Symfony components and the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/framework-bundle/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/http-client", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "c8c887f4813370550147afd27d9eb8a8523e53b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c8c887f4813370550147afd27d9eb8a8523e53b2", + "reference": "c8c887f4813370550147afd27d9eb8a8523e53b2", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/http-client-contracts": "^3", + "symfony/service-contracts": "^1.0|^2|^3" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-client/tree/v6.1.6" + }, + "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-12T05:10:31+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/fd038f08c623ab5d22b26e9ba35afe8c79071800", + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-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-04-22T07:30:54+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "3ae8e9c57155fc48930493a629da293b32efbde0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3ae8e9c57155fc48930493a629da293b32efbde0", + "reference": "3ae8e9c57155fc48930493a629da293b32efbde0", + "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.6" + }, + "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-02T08:30:52+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "102f99bf81799e93f61b9a73b2f38b309c587a94" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/102f99bf81799e93f61b9a73b2f38b309c587a94", + "reference": "102f99bf81799e93f61b9a73b2f38b309c587a94", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/error-handler": "^6.1", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.4", + "symfony/config": "<6.1", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<6.1", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<5.4", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/config": "^6.1", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dependency-injection": "^6.1", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/process": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "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": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v6.1.6" + }, + "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-12T07:48:47+00:00" + }, + { + "name": "symfony/intl", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/intl.git", + "reference": "9ab546d9054b34feb2cb728349f6b8e8f18d4c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/intl/zipball/9ab546d9054b34feb2cb728349f6b8e8f18d4c43", + "reference": "9ab546d9054b34feb2cb728349f6b8e8f18d4c43", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Intl\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Eriksen Costa", + "email": "eriksen.costa@infranology.com.br" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a PHP replacement layer for the C intl extension that includes additional data from the ICU library", + "homepage": "https://symfony.com", + "keywords": [ + "i18n", + "icu", + "internationalization", + "intl", + "l10n", + "localization" + ], + "support": { + "source": "https://github.com/symfony/intl/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/lock", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "6e8c324132f8ebb47a1a8506031a55f0020783fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/6e8c324132f8ebb47a1a8506031a55f0020783fc", + "reference": "6e8c324132f8ebb47a1a8506031a55f0020783fc", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "doctrine/dbal": "<2.13" + }, + "require-dev": { + "doctrine/dbal": "^2.13|^3.0", + "predis/predis": "~1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Creates and manages locks, a mechanism to provide exclusive access to a shared resource", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "support": { + "source": "https://github.com/symfony/lock/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "e1b32deb9efc48def0c76b876860ad36f2123e89" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/e1b32deb9efc48def0c76b876860ad36f2123e89", + "reference": "e1b32deb9efc48def0c76b876860ad36f2123e89", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<5.4" + }, + "require-dev": { + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/messenger": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "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": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.1.5" + }, + "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-08-29T06:58:39+00:00" + }, + { + "name": "symfony/messenger", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/messenger.git", + "reference": "3d7fbc507ad31e71a96e8e65342243e2dbe22fa1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/messenger/zipball/3d7fbc507ad31e71a96e8e65342243e2dbe22fa1", + "reference": "3d7fbc507ad31e71a96e8e65342243e2dbe22fa1", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<5.4", + "symfony/event-dispatcher-contracts": "<2", + "symfony/framework-bundle": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/serializer": "<5.4" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0" + }, + "suggest": { + "enqueue/messenger-adapter": "For using the php-enqueue library as a transport." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Messenger\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Samuel Roze", + "email": "samuel.roze@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps applications send and receive messages to/from other applications or via message queues", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/messenger/tree/v6.1.6" + }, + "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-10T09:34:31+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "5ae192b9a39730435cfec025a499f79d05ac68a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/5ae192b9a39730435cfec025a499f79d05ac68a3", + "reference": "5ae192b9a39730435cfec025a499f79d05ac68a3", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "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": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/monolog-bridge", + "version": "v6.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bridge.git", + "reference": "1efd6a42b1dc80e03bd74d4a2fdc85e728dc2627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/1efd6a42b1dc80e03bd74d4a2fdc85e728dc2627", + "reference": "1efd6a42b1dc80e03bd74d4a2fdc85e728dc2627", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1|^2|^3", + "php": ">=8.1", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/console": "<5.4", + "symfony/http-foundation": "<5.4", + "symfony/security-core": "<6.0" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/mailer": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/security-core": "^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "symfony/console": "For the possibility to show log messages in console commands depending on verbosity settings.", + "symfony/http-kernel": "For using the debugging handlers together with the response life cycle of the HTTP kernel.", + "symfony/var-dumper": "For using the debugging handlers like the console handler or the log server handler." + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Monolog\\": "" + }, + "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": "Provides integration for Monolog with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/monolog-bridge/tree/v6.1.2" + }, + "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-06-21T08:28:57+00:00" + }, + { + "name": "symfony/monolog-bundle", + "version": "v3.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "a41bbcdc1105603b6d73a7d9a43a3788f8e0fb7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/a41bbcdc1105603b6d73a7d9a43a3788f8e0fb7d", + "reference": "a41bbcdc1105603b6d73a7d9a43a3788f8e0fb7d", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.22 || ^2.0 || ^3.0", + "php": ">=7.1.3", + "symfony/config": "~4.4 || ^5.0 || ^6.0", + "symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0", + "symfony/http-kernel": "~4.4 || ^5.0 || ^6.0", + "symfony/monolog-bridge": "~4.4 || ^5.0 || ^6.0" + }, + "require-dev": { + "symfony/console": "~4.4 || ^5.0 || ^6.0", + "symfony/phpunit-bridge": "^5.2 || ^6.0", + "symfony/yaml": "~4.4 || ^5.0 || ^6.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MonologBundle\\": "" + }, + "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": "Symfony MonologBundle", + "homepage": "https://symfony.com", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/symfony/monolog-bundle/issues", + "source": "https://github.com/symfony/monolog-bundle/tree/v3.8.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-10T14:24:36+00:00" + }, + { + "name": "symfony/notifier", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/notifier.git", + "reference": "34be8d35e4e71057cc10078dc28c7210673cb3de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/notifier/zipball/34be8d35e4e71057cc10078dc28c7210673cb3de", + "reference": "34be8d35e4e71057cc10078dc28c7210673cb3de", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<5.4", + "symfony/http-kernel": "<5.4" + }, + "require-dev": { + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/http-client-contracts": "^2|^3", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Notifier\\": "" + }, + "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": "Sends notifications via one or more channels (email, SMS, ...)", + "homepage": "https://symfony.com", + "keywords": [ + "notification", + "notifier" + ], + "support": { + "source": "https://github.com/symfony/notifier/tree/v6.1.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-11T12:12:29+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a3016f5442e28386ded73c43a32a5b68586dd1c4", + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v6.1.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-02-25T11:15:52+00:00" + }, + { + "name": "symfony/password-hasher", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/password-hasher.git", + "reference": "264894821636b77bb8282db6ec33b8b07b7a0678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/264894821636b77bb8282db6ec33b8b07b7a0678", + "reference": "264894821636b77bb8282db6ec33b8b07b7a0678", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "symfony/security-core": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/security-core": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PasswordHasher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides password hashing utilities", + "homepage": "https://symfony.com", + "keywords": [ + "hashing", + "password" + ], + "support": { + "source": "https://github.com/symfony/password-hasher/tree/v6.1.3" + }, + "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-07-20T14:45:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "433d05519ce6990bf3530fba6957499d327395c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", + "reference": "433d05519ce6990bf3530fba6957499d327395c2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "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\\Intl\\Grapheme\\": "" + } + }, + "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 intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/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" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "e407643d610e5f2c8a4b14189150f68934bf5e48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e407643d610e5f2c8a4b14189150f68934bf5e48", + "reference": "e407643d610e5f2c8a4b14189150f68934bf5e48", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "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\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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 intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-icu/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" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", + "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "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\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/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" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "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\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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 intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/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" + }, + { + "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" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/a41886c1c81dc075a09c71fe6db5b9d68c79de23", + "reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "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\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/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" + }, + { + "name": "symfony/process", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/property-access", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "25108ee9b62d6ef0815007d9c7cf6a7ba40bb7c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/25108ee9b62d6ef0815007d9c7cf6a7ba40bb7c5", + "reference": "25108ee9b62d6ef0815007d9c7cf6a7ba40bb7c5", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/property-info": "^5.4|^6.0" + }, + "require-dev": { + "symfony/cache": "^5.4|^6.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "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": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/property-info", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "f28d0db9d2687f81d68d0dc6b2e42817647f5d64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/f28d0db9d2687f81d68d0dc6b2e42817647f5d64", + "reference": "f28d0db9d2687f81d68d0dc6b2e42817647f5d64", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0", + "symfony/cache": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" + }, + "suggest": { + "phpdocumentor/reflection-docblock": "To use the PHPDoc", + "psr/cache-implementation": "To cache results", + "symfony/doctrine-bridge": "To use Doctrine metadata", + "symfony/serializer": "To use Serializer metadata" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/proxy-manager-bridge", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/proxy-manager-bridge.git", + "reference": "bcb3e7a28ee373bd64ecd2a2289a64c5860716af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/bcb3e7a28ee373bd64ecd2a2289a64c5860716af", + "reference": "bcb3e7a28ee373bd64ecd2a2289a64c5860716af", + "shasum": "" + }, + "require": { + "friendsofphp/proxy-manager-lts": "^1.0.2", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\ProxyManager\\": "" + }, + "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": "Provides integration for ProxyManager with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.1.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-03-02T13:21:45+00:00" + }, + { + "name": "symfony/rate-limiter", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/rate-limiter.git", + "reference": "9e75706446f7c3686773c408f422ffb5ec4ba32b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/9e75706446f7c3686773c408f422ffb5ec4ba32b", + "reference": "9e75706446f7c3686773c408f422ffb5ec4ba32b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/lock": "^5.4|^6.0", + "symfony/options-resolver": "^5.4|^6.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\RateLimiter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Wouter de Jong", + "email": "wouter@wouterj.nl" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a Token Bucket implementation to rate limit input and output in your application", + "homepage": "https://symfony.com", + "keywords": [ + "limiter", + "rate-limiter" + ], + "support": { + "source": "https://github.com/symfony/rate-limiter/tree/v6.1.3" + }, + "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-07-20T13:46:29+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "f8c1ebb43d0f39e5ecd12a732ba1952a3dd8455c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/f8c1ebb43d0f39e5ecd12a732ba1952a3dd8455c", + "reference": "f8c1ebb43d0f39e5ecd12a732ba1952a3dd8455c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "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": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v6.1.5" + }, + "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-09-09T09:26:14+00:00" + }, + { + "name": "symfony/runtime", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/runtime.git", + "reference": "e5d4d848656cbb1812d5f911b1bdec205c6e2fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/runtime/zipball/e5d4d848656cbb1812d5f911b1bdec205c6e2fac", + "reference": "e5d4d848656cbb1812d5f911b1bdec205c6e2fac", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.1" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4|^6.0", + "symfony/dotenv": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Enables decoupling PHP applications from global state", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/runtime/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/security-bundle", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-bundle.git", + "reference": "1410129e36e5d0cf4bde73f4ed5d9e18acff06b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/1410129e36e5d0cf4bde73f4ed5d9e18acff06b3", + "reference": "1410129e36e5d0cf4bde73f4ed5d9e18acff06b3", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.1", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/password-hasher": "^5.4|^6.0", + "symfony/security-core": "^5.4|^6.0", + "symfony/security-csrf": "^5.4|^6.0", + "symfony/security-http": "^5.4|^6.0" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/console": "<5.4", + "symfony/framework-bundle": "<5.4", + "symfony/ldap": "<5.4", + "symfony/twig-bundle": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "symfony/asset": "^5.4|^6.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/framework-bundle": "^5.4|^6.0", + "symfony/ldap": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/rate-limiter": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/twig-bridge": "^5.4|^6.0", + "symfony/twig-bundle": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\SecurityBundle\\": "" + }, + "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": "Provides a tight integration of the Security component into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-bundle/tree/v6.1.3" + }, + "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-07-20T13:46:29+00:00" + }, + { + "name": "symfony/security-core", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "e42fb611d1a36e6e1e34f8cd715cea108a39cad5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/e42fb611d1a36e6e1e34f8cd715cea108a39cad5", + "reference": "e42fb611d1a36e6e1e34f8cd715cea108a39cad5", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^1.1|^2|^3", + "symfony/password-hasher": "^5.4|^6.0", + "symfony/service-contracts": "^1.1.6|^2|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<5.4", + "symfony/http-foundation": "<5.4", + "symfony/ldap": "<5.4", + "symfony/security-guard": "<5.4", + "symfony/validator": "<5.4" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "psr/container": "^1.1|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/ldap": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0" + }, + "suggest": { + "psr/container-implementation": "To instantiate the Security class", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/ldap": "For using LDAP integration", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Core\\": "" + }, + "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": "Symfony Security Component - Core Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-core/tree/v6.1.6" + }, + "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-02T08:30:52+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "b44d74295a5651298de8c2760ba50bef3b97f34b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/b44d74295a5651298de8c2760ba50bef3b97f34b", + "reference": "b44d74295a5651298de8c2760ba50bef3b97f34b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/security-core": "^5.4|^6.0" + }, + "conflict": { + "symfony/http-foundation": "<5.4" + }, + "require-dev": { + "symfony/http-foundation": "^5.4|^6.0" + }, + "suggest": { + "symfony/http-foundation": "For using the class SessionTokenStorage." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Csrf\\": "" + }, + "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": "Symfony Security Component - CSRF Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-csrf/tree/v6.1.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-14T12:53:54+00:00" + }, + { + "name": "symfony/security-http", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-http.git", + "reference": "789492510f7127035da8bb5dbb4fb745970e2348" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-http/zipball/789492510f7127035da8bb5dbb4fb745970e2348", + "reference": "789492510f7127035da8bb5dbb4fb745970e2348", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^6.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/security-core": "^5.4.7|^6.0" + }, + "conflict": { + "symfony/event-dispatcher": "<5.4.9|>=6,<6.0.9", + "symfony/security-bundle": "<5.4", + "symfony/security-csrf": "<5.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/cache": "^5.4|^6.0", + "symfony/rate-limiter": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/security-csrf": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0" + }, + "suggest": { + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/security-csrf": "For using tokens to protect authentication/logout attempts" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Http\\": "" + }, + "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": "Symfony Security Component - HTTP Integration", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-http/tree/v6.1.6" + }, + "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-01T16:55:12+00:00" + }, + { + "name": "symfony/serializer", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "76af774da9daf606d6400f1445b69d23efa3b238" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/76af774da9daf606d6400f1445b69d23efa3b238", + "reference": "76af774da9daf606d6400f1445b69d23efa3b238", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/dependency-injection": "<5.4", + "symfony/property-access": "<5.4", + "symfony/property-info": "<5.4", + "symfony/uid": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12", + "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0", + "symfony/var-exporter": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "To deserialize relations.", + "symfony/var-exporter": "For using the metadata compiler.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "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": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v6.1.6" + }, + "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-12T05:10:31+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-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-05-30T19:18:58+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v6.1.5" + }, + "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-09-28T16:00:52+00:00" + }, + { + "name": "symfony/string", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "7e7e0ff180d4c5a6636eaad57b65092014b61864" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/7e7e0ff180d4c5a6636eaad57b65092014b61864", + "reference": "7e7e0ff180d4c5a6636eaad57b65092014b61864", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.1.6" + }, + "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-10T09:34:31+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "e6cd330e5a072518f88d65148f3f165541807494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/e6cd330e5a072518f88d65148f3f165541807494", + "reference": "e6cd330e5a072518f88d65148f3f165541807494", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.3|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "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": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "606be0f48e05116baef052f7f3abdb345c8e02cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/606be0f48e05116baef052f7f3abdb345c8e02cc", + "reference": "606be0f48e05116baef052f7f3abdb345c8e02cc", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "368e9bac2dbaed85d943745b521077f8101b599d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/368e9bac2dbaed85d943745b521077f8101b599d", + "reference": "368e9bac2dbaed85d943745b521077f8101b599d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/translation-contracts": "^1.1|^2|^3", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/console": "<5.4", + "symfony/form": "<6.1", + "symfony/http-foundation": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/translation": "<5.4", + "symfony/workflow": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12", + "egulias/email-validator": "^2.1.10|^3", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/form": "^6.1", + "symfony/html-sanitizer": "^6.1", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/security-acl": "^2.8|^3.0", + "symfony/security-core": "^5.4|^6.0", + "symfony/security-csrf": "^5.4|^6.0", + "symfony/security-http": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/web-link": "^5.4|^6.0", + "symfony/workflow": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0", + "twig/cssinliner-extra": "^2.12|^3", + "twig/inky-extra": "^2.12|^3", + "twig/markdown-extra": "^2.12|^3" + }, + "suggest": { + "symfony/asset": "For using the AssetExtension", + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/finder": "", + "symfony/form": "For using the FormExtension", + "symfony/html-sanitizer": "For using the HtmlSanitizerExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security-core": "For using the SecurityExtension", + "symfony/security-csrf": "For using the CsrfExtension", + "symfony/security-http": "For using the LogoutUrlExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/translation": "For using the TranslationExtension", + "symfony/var-dumper": "For using the DumpExtension", + "symfony/web-link": "For using the WebLinkExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "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": "Provides integration for Twig with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bridge/tree/v6.1.6" + }, + "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-12T05:10:31+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v6.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "a2abab10068525a7f5a879e40e411d369d688545" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/a2abab10068525a7f5a879e40e411d369d688545", + "reference": "a2abab10068525a7f5a879e40e411d369d688545", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "php": ">=8.1", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/twig-bridge": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "symfony/framework-bundle": "<5.4", + "symfony/translation": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "symfony/asset": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/framework-bundle": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/web-link": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "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": "Provides a tight integration of Twig into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bundle/tree/v6.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-05-27T16:55:36+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "e03519f7b1ce1d3c0b74f751892bb41d549a2d98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/e03519f7b1ce1d3c0b74f751892bb41d549a2d98", + "reference": "e03519f7b1ce1d3c0b74f751892bb41d549a2d98", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.1.5" + }, + "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-09-09T09:34:27+00:00" + }, + { + "name": "symfony/validator", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "e5589882403e1e19774d7c5ffb65d9c6466d216c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/e5589882403e1e19774d7c5ffb65d9c6466d216c", + "reference": "e5589882403e1e19774d7c5ffb65d9c6466d216c", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1|^2|^3" + }, + "conflict": { + "doctrine/annotations": "<1.13", + "doctrine/lexer": "<1.1", + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<5.4", + "symfony/expression-language": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/intl": "<5.4", + "symfony/property-info": "<5.4", + "symfony/translation": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13", + "egulias/email-validator": "^2.1.10|^3", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "egulias/email-validator": "Strict (RFC compliant) email validation", + "psr/cache-implementation": "For using the mapping cache.", + "symfony/config": "", + "symfony/expression-language": "For using the Expression validator and the ExpressionLanguageSyntax constraints", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For accessing properties within comparison constraints", + "symfony/property-info": "To automatically add NotNull and Type constraints", + "symfony/translation": "For translating validation errors.", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "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": "Provides tools to validate values", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/validator/tree/v6.1.6" + }, + "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-02T08:30:52+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "0f0adde127f24548e23cbde83bcaeadc491c551f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0f0adde127f24548e23cbde83bcaeadc491c551f", + "reference": "0f0adde127f24548e23cbde83bcaeadc491c551f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "b49350f45cebbba6e5286485264b912f2bcfc9ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/b49350f45cebbba6e5286485264b912f2bcfc9ef", + "reference": "b49350f45cebbba6e5286485264b912f2bcfc9ef", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v6.1.3" + }, + "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-07-04T16:01:56+00:00" + }, + { + "name": "symfony/web-link", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "d6ef738f97b60d859652d92f10bf8645bca28cd6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/d6ef738f97b60d859652d92f10bf8645bca28cd6", + "reference": "d6ef738f97b60d859652d92f10bf8645bca28cd6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/link": "^1.1|^2.0" + }, + "conflict": { + "symfony/http-kernel": "<5.4" + }, + "provide": { + "psr/link-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/http-kernel": "^5.4|^6.0" + }, + "suggest": { + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages links between resources", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "support": { + "source": "https://github.com/symfony/web-link/tree/v6.1.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-02-25T11:15:52+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "66c6b0cf52b00f74614a2cf7ae7db08ea1095931" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/66c6b0cf52b00f74614a2cf7ae7db08ea1095931", + "reference": "66c6b0cf52b00f74614a2cf7ae7db08ea1095931", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "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": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfonycasts/reset-password-bundle", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/SymfonyCasts/reset-password-bundle.git", + "reference": "05216bfd80d4019a155d326501f00bf92b9cd439" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SymfonyCasts/reset-password-bundle/zipball/05216bfd80d4019a155d326501f00bf92b9cd439", + "reference": "05216bfd80d4019a155d326501f00bf92b9cd439", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2.5", + "symfony/config": "^5.4 | ^6.0", + "symfony/dependency-injection": "^5.4 | ^6.0", + "symfony/deprecation-contracts": "^2.2 | ^3.0", + "symfony/http-kernel": "^5.4 | ^6.0" + }, + "conflict": { + "doctrine/orm": "<2.7", + "php": ">=8.1 <8.1.10" + }, + "require-dev": { + "doctrine/doctrine-bundle": "^2.0.3", + "doctrine/orm": "^2.7", + "symfony/framework-bundle": "^5.4 | ^6.0", + "symfony/phpunit-bridge": "^5.4 | ^6.0", + "vimeo/psalm": "^4.3" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "SymfonyCasts\\Bundle\\ResetPassword\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Symfony bundle that adds password reset functionality.", + "support": { + "issues": "https://github.com/SymfonyCasts/reset-password-bundle/issues", + "source": "https://github.com/SymfonyCasts/reset-password-bundle/tree/v1.16.0" + }, + "time": "2022-10-04T08:38:58+00:00" + }, + { + "name": "symfonycasts/verify-email-bundle", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/SymfonyCasts/verify-email-bundle.git", + "reference": "c60349bf5a6f5e9a40bd88ec7d19b9ffd7f6af12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SymfonyCasts/verify-email-bundle/zipball/c60349bf5a6f5e9a40bd88ec7d19b9ffd7f6af12", + "reference": "c60349bf5a6f5e9a40bd88ec7d19b9ffd7f6af12", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2.5", + "symfony/config": "^5.4 | ^6.0", + "symfony/dependency-injection": "^5.4 | ^6.0", + "symfony/deprecation-contracts": "^2.2 | ^3.0", + "symfony/http-kernel": "^5.4 | ^6.0", + "symfony/routing": "^5.4 | ^6.0" + }, + "require-dev": { + "doctrine/orm": "^2.7", + "doctrine/persistence": "^2.0", + "symfony/framework-bundle": "^5.4 | ^6.0", + "symfony/phpunit-bridge": "^5.4 | ^6.0", + "vimeo/psalm": "^4.3" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "SymfonyCasts\\Bundle\\VerifyEmail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Simple, stylish Email Verification for Symfony", + "support": { + "issues": "https://github.com/SymfonyCasts/verify-email-bundle/issues", + "source": "https://github.com/SymfonyCasts/verify-email-bundle/tree/v1.12.0" + }, + "time": "2022-10-04T08:35:54+00:00" + }, + { + "name": "twig/extra-bundle", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/twig-extra-bundle.git", + "reference": "2e58256b0e9fe52f30149347c0547e4633304765" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/2e58256b0e9fe52f30149347c0547e4633304765", + "reference": "2e58256b0e9fe52f30149347c0547e4633304765", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/framework-bundle": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "twig/twig": "^2.7|^3.0" + }, + "require-dev": { + "league/commonmark": "^1.0|^2.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", + "twig/cache-extra": "^3.0", + "twig/cssinliner-extra": "^2.12|^3.0", + "twig/html-extra": "^2.12|^3.0", + "twig/inky-extra": "^2.12|^3.0", + "twig/intl-extra": "^2.12|^3.0", + "twig/markdown-extra": "^2.12|^3.0", + "twig/string-extra": "^2.12|^3.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Twig\\Extra\\TwigExtraBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + } + ], + "description": "A Symfony bundle for extra Twig extensions", + "homepage": "https://twig.symfony.com", + "keywords": [ + "bundle", + "extra", + "twig" + ], + "support": { + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2022-01-04T13:58:53+00:00" + }, + { + "name": "twig/twig", + "version": "v3.4.3", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", + "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.4.3" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2022-09-28T08:42:51+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" + }, + { + "name": "willdurand/negotiation", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/willdurand/Negotiation.git", + "reference": "68e9ea0553ef6e2ee8db5c1d98829f111e623ec2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/Negotiation/zipball/68e9ea0553ef6e2ee8db5c1d98829f111e623ec2", + "reference": "68e9ea0553ef6e2ee8db5c1d98829f111e623ec2", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Negotiation\\": "src/Negotiation" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "will+git@drnd.me" + } + ], + "description": "Content Negotiation tools for PHP provided as a standalone library.", + "homepage": "http://williamdurand.fr/Negotiation/", + "keywords": [ + "accept", + "content", + "format", + "header", + "negotiation" + ], + "support": { + "issues": "https://github.com/willdurand/Negotiation/issues", + "source": "https://github.com/willdurand/Negotiation/tree/3.1.0" + }, + "time": "2022-01-30T20:08:53+00:00" + } + ], + "packages-dev": [ + { + "name": "doctrine/data-fixtures", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "ba37bfb776de763c5bf04a36d074cd5f5a083c42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/ba37bfb776de763c5bf04a36d074cd5f5a083c42", + "reference": "ba37bfb776de763c5bf04a36d074cd5f5a083c42", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.13|^3.0", + "doctrine/persistence": "^1.3.3|^2.0|^3.0", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<2.13", + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "doctrine/dbal": "^2.13 || ^3.0", + "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", + "doctrine/orm": "^2.7.0", + "ext-sqlite3": "*", + "jangregor/phpstan-prophecy": "^1", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/cache": "^5.0 || ^6.0", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "database" + ], + "support": { + "issues": "https://github.com/doctrine/data-fixtures/issues", + "source": "https://github.com/doctrine/data-fixtures/tree/1.5.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", + "type": "tidelift" + } + ], + "time": "2022-04-19T10:01:44+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.4.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "601988c5b46dbd20a0f886f967210aba378a6fd5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/601988c5b46dbd20a0f886f967210aba378a6fd5", + "reference": "601988c5b46dbd20a0f886f967210aba378a6fd5", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "doctrine/persistence": "^1.3.7|^2.0|^3.0", + "php": "^7.1 || ^8.0", + "symfony/config": "^3.4|^4.3|^5.0|^6.0", + "symfony/console": "^3.4|^4.3|^5.0|^6.0", + "symfony/dependency-injection": "^3.4.47|^4.3|^5.0|^6.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0|^6.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0|^6.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "^1.4.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "symfony/phpunit-bridge": "^6.0.8", + "vimeo/psalm": "^4.22" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", + "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.4.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-fixtures-bundle", + "type": "tidelift" + } + ], + "time": "2022-04-28T17:58:29+00:00" + }, + { + "name": "masterminds/html5", + "version": "2.7.6", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "897eb517a343a2281f11bc5556d6548db7d93947" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/897eb517a343a2281f11bc5556d6548db7d93947", + "reference": "897eb517a343a2281f11bc5556d6548db7d93947", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-libxml": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.7.6" + }, + "time": "2022-08-18T16:18:26+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2022-03-03T13:19:32+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" + }, + "time": "2022-09-04T07:30:47+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8" + }, + "dist": { + "type": "zip", + "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.14", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-08-30T12:24:04+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.5.25", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.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.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2022-09-25T03:44:45+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "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": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-04-03T09:37:03+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-12T14:47:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "2e3b6a4406c2af963c634d7bd0457402b67dcc56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2e3b6a4406c2af963c634d7bd0457402b67dcc56", + "reference": "2e3b6a4406c2af963c634d7bd0457402b67dcc56", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/dom-crawler": "^5.4|^6.0" + }, + "require-dev": { + "symfony/css-selector": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v6.1.3" + }, + "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-07-27T15:50:51+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/debug-bundle", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "4084f86639bf0270d6dd2225fc8d7c317780dd6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/4084f86639bf0270d6dd2225fc8d7c317780dd6b", + "reference": "4084f86639bf0270d6dd2225fc8d7c317780dd6b", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/twig-bridge": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0", + "symfony/web-profiler-bundle": "^5.4|^6.0" + }, + "suggest": { + "symfony/config": "For service container configuration", + "symfony/dependency-injection": "For using as a service from the container" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "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": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug-bundle/tree/v6.1.3" + }, + "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-07-20T13:46:29+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v6.1.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "8cb4c6e6c8d30c26f70529ed5e50d79a09576c0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/8cb4c6e6c8d30c26f70529ed5e50d79a09576c0c", + "reference": "8cb4c6e6c8d30c26f70529ed5e50d79a09576c0c", + "shasum": "" + }, + "require": { + "masterminds/html5": "^2.6", + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "^5.4|^6.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v6.1.4" + }, + "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-08-04T19:19:00+00:00" + }, + { + "name": "symfony/maker-bundle", + "version": "v1.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/maker-bundle.git", + "reference": "e607f129d29a6c1e9a9e1ef3d229d653311d58f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/e607f129d29a6c1e9a9e1ef3d229d653311d58f3", + "reference": "e607f129d29a6c1e9a9e1ef3d229d653311d58f3", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^2.0", + "nikic/php-parser": "^4.11", + "php": ">=8.0", + "symfony/config": "^5.4.7|^6.0", + "symfony/console": "^5.4.7|^6.0", + "symfony/dependency-injection": "^5.4.7|^6.0", + "symfony/deprecation-contracts": "^2.2|^3", + "symfony/filesystem": "^5.4.7|^6.0", + "symfony/finder": "^5.4.3|^6.0", + "symfony/framework-bundle": "^5.4.7|^6.0", + "symfony/http-kernel": "^5.4.7|^6.0" + }, + "conflict": { + "doctrine/doctrine-bundle": "<2.4", + "doctrine/orm": "<2.10", + "symfony/doctrine-bridge": "<5.4" + }, + "require-dev": { + "composer/semver": "^3.0", + "doctrine/doctrine-bundle": "^2.4", + "doctrine/orm": "^2.10.0", + "symfony/http-client": "^5.4.7|^6.0", + "symfony/phpunit-bridge": "^5.4.7|^6.0", + "symfony/polyfill-php80": "^1.16.0", + "symfony/process": "^5.4.7|^6.0", + "symfony/security-core": "^5.4.7|^6.0", + "symfony/yaml": "^5.4.3|^6.0", + "twig/twig": "^2.0|^3.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MakerBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", + "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", + "keywords": [ + "code generator", + "generator", + "scaffold", + "scaffolding" + ], + "support": { + "issues": "https://github.com/symfony/maker-bundle/issues", + "source": "https://github.com/symfony/maker-bundle/tree/v1.47.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-10-04T15:05:10+00:00" + }, + { + "name": "symfony/phpunit-bridge", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "07cf788ac9ae83b59d46599bb5098c3add88c68b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/07cf788ac9ae83b59d46599bb5098c3add88c68b", + "reference": "07cf788ac9ae83b59d46599bb5098c3add88c68b", + "shasum": "" + }, + "require": { + "php": ">=7.1.3" + }, + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/error-handler": "^5.4|^6.0" + }, + "suggest": { + "symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides utilities for PHPUnit, especially user deprecation notices management", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.1.6" + }, + "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-07T08:04:03+00:00" + }, + { + "name": "symfony/web-profiler-bundle", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "45d05cd8e967fd06bb1f66f748ed308c00674d32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/45d05cd8e967fd06bb1f66f748ed308c00674d32", + "reference": "45d05cd8e967fd06bb1f66f748ed308c00674d32", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/config": "^5.4|^6.0", + "symfony/framework-bundle": "^5.4|^6.0", + "symfony/http-kernel": "^6.1", + "symfony/routing": "^5.4|^6.0", + "symfony/twig-bundle": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "symfony/form": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4" + }, + "require-dev": { + "symfony/browser-kit": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\WebProfilerBundle\\": "" + }, + "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": "Provides a development tool that gives detailed information about the execution of any request", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.1.6" + }, + "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-02T08:30:52+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=8.1.11", + "ext-ctype": "*", + "ext-iconv": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/app/config/bundles.php b/app/config/bundles.php new file mode 100644 index 0000000..bcea0cc --- /dev/null +++ b/app/config/bundles.php @@ -0,0 +1,23 @@ + ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], + EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true], + SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle::class => ['all' => true], + Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], + Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], + SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true], + Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], + ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], + Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true], +]; diff --git a/app/config/packages/api_platform.yaml b/app/config/packages/api_platform.yaml new file mode 100644 index 0000000..ffbd43f --- /dev/null +++ b/app/config/packages/api_platform.yaml @@ -0,0 +1,16 @@ +# https://api-platform.com/docs/core/configuration/ +api_platform: + #title: 'API title' # The title of the API. + #description: 'API description' # The description of the API. + version: '0.0.1' # The version of the API. + + show_webby: false # show spider + + mapping: + paths: ['%kernel.project_dir%/src/Entity'] + + patch_formats: + json: ['application/merge-patch+json'] + + swagger: + versions: [3] diff --git a/app/config/packages/cache.yaml b/app/config/packages/cache.yaml new file mode 100644 index 0000000..6899b72 --- /dev/null +++ b/app/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null diff --git a/app/config/packages/debug.yaml b/app/config/packages/debug.yaml new file mode 100644 index 0000000..ad874af --- /dev/null +++ b/app/config/packages/debug.yaml @@ -0,0 +1,5 @@ +when@dev: + debug: + # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. + # See the "server:dump" command to start a new server. + dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" diff --git a/app/config/packages/doctrine.yaml b/app/config/packages/doctrine.yaml new file mode 100644 index 0000000..52e7e0d --- /dev/null +++ b/app/config/packages/doctrine.yaml @@ -0,0 +1,34 @@ +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + types: + uuid: Symfony\Bridge\Doctrine\Types\UuidType + orm: + auto_generate_proxy_classes: true + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + auto_mapping: true + mappings: + App: + is_bundle: false + dir: '%kernel.project_dir%/src/Entity' + prefix: 'App\Entity' + alias: App + +when@prod: + doctrine: + orm: + auto_generate_proxy_classes: false + query_cache_driver: + type: pool + pool: doctrine.system_cache_pool + result_cache_driver: + type: pool + pool: doctrine.result_cache_pool + + framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/app/config/packages/doctrine_migrations.yaml b/app/config/packages/doctrine_migrations.yaml new file mode 100644 index 0000000..a0a17a0 --- /dev/null +++ b/app/config/packages/doctrine_migrations.yaml @@ -0,0 +1,6 @@ +doctrine_migrations: + migrations_paths: + # namespace is arbitrary but should be different from App\Migrations + # as migrations classes should NOT be autoloaded + 'DoctrineMigrations': '%kernel.project_dir%/migrations' + enable_profiler: '%kernel.debug%' diff --git a/app/config/packages/framework.yaml b/app/config/packages/framework.yaml new file mode 100644 index 0000000..7853e9e --- /dev/null +++ b/app/config/packages/framework.yaml @@ -0,0 +1,24 @@ +# see https://symfony.com/doc/current/reference/configuration/framework.html +framework: + secret: '%env(APP_SECRET)%' + #csrf_protection: true + http_method_override: false + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: null + cookie_secure: auto + cookie_samesite: lax + storage_factory_id: session.storage.factory.native + + #esi: true + #fragments: true + php_errors: + log: true + +when@test: + framework: + test: true + session: + storage_factory_id: session.storage.factory.mock_file diff --git a/app/config/packages/lock.yaml b/app/config/packages/lock.yaml new file mode 100644 index 0000000..574879f --- /dev/null +++ b/app/config/packages/lock.yaml @@ -0,0 +1,2 @@ +framework: + lock: '%env(LOCK_DSN)%' diff --git a/app/config/packages/mailer.yaml b/app/config/packages/mailer.yaml new file mode 100644 index 0000000..56a650d --- /dev/null +++ b/app/config/packages/mailer.yaml @@ -0,0 +1,3 @@ +framework: + mailer: + dsn: '%env(MAILER_DSN)%' diff --git a/app/config/packages/messenger.yaml b/app/config/packages/messenger.yaml new file mode 100644 index 0000000..fd1d274 --- /dev/null +++ b/app/config/packages/messenger.yaml @@ -0,0 +1,24 @@ +framework: + messenger: + #failure_transport: failed + + transports: + # https://symfony.com/doc/current/messenger.html#transport-configuration + async: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%' + options: + use_notify: true + check_delayed_interval: 60000 + retry_strategy: + max_retries: 3 + multiplier: 2 + failed: 'doctrine://default?queue_name=failed' + # sync: 'sync://' + + routing: + #Symfony\Component\Mailer\Messenger\SendEmailMessage: async + #Symfony\Component\Notifier\Message\ChatMessage: async + #Symfony\Component\Notifier\Message\SmsMessage: async + + # Route your messages to the transports + # 'App\Message\YourMessage': async diff --git a/app/config/packages/monolog.yaml b/app/config/packages/monolog.yaml new file mode 100644 index 0000000..8c9efa9 --- /dev/null +++ b/app/config/packages/monolog.yaml @@ -0,0 +1,61 @@ +monolog: + channels: + - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists + +when@dev: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + channels: ["!event"] + # uncomment to get logging in your browser + # you may have to allow bigger header sizes in your Web server configuration + #firephp: + # type: firephp + # level: info + #chromephp: + # type: chromephp + # level: info + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] + +when@test: + monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + channels: ["!event"] + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + +when@prod: + monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + buffer_size: 50 # How many messages should be saved? Prevent memory leaks + nested: + type: stream + path: php://stderr + level: debug + formatter: monolog.formatter.json + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine"] + deprecation: + type: stream + channels: [deprecation] + path: php://stderr diff --git a/app/config/packages/nelmio_cors.yaml b/app/config/packages/nelmio_cors.yaml new file mode 100644 index 0000000..c766508 --- /dev/null +++ b/app/config/packages/nelmio_cors.yaml @@ -0,0 +1,10 @@ +nelmio_cors: + defaults: + origin_regex: true + allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] + allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'] + allow_headers: ['Content-Type', 'Authorization'] + expose_headers: ['Link'] + max_age: 3600 + paths: + '^/': null diff --git a/app/config/packages/notifier.yaml b/app/config/packages/notifier.yaml new file mode 100644 index 0000000..3984a48 --- /dev/null +++ b/app/config/packages/notifier.yaml @@ -0,0 +1,16 @@ +framework: + notifier: + #chatter_transports: + # slack: '%env(SLACK_DSN)%' + # telegram: '%env(TELEGRAM_DSN)%' + #texter_transports: + # twilio: '%env(TWILIO_DSN)%' + # nexmo: '%env(NEXMO_DSN)%' + channel_policy: + # use chat/slack, chat/telegram, sms/twilio or sms/nexmo + urgent: ['email'] + high: ['email'] + medium: ['email'] + low: ['email'] + admin_recipients: + - { email: admin@example.com } diff --git a/app/config/packages/parameters.yaml b/app/config/packages/parameters.yaml new file mode 100644 index 0000000..56d976b --- /dev/null +++ b/app/config/packages/parameters.yaml @@ -0,0 +1,31 @@ +parameters: + app: + default_locale: en + supported_locales: ['en', 'de'] + admin_locales: [de, en] + + timezone: 'Europe/Zurich' #default Timezone, users can set their own + date_format: 'yyyy-MM-dd' #default DateFormat, users can set their own, ICU Datetime Pattern (see https://unicode-org.github.io/icu/userguide/format_parse/datetime/) + time_format: 'HH:mm:ss' #default TimeFormat, users can set their own, ICU Datetime Pattern (see https://unicode-org.github.io/icu/userguide/format_parse/datetime/) + + core: + registration_active: true #allow new users to register + passwort_reset_active: true #allow password reset + + login: + identifier: 'both' # username, email or both + registration: + ask_username: true + ask_name: false # firstname and lastname + + mailer: + from_email: 'team@root.dev' + from_name: 'AcmeBotName' + logging_general: true # enable mail logging + logging_full: true # enable full log, sentmail-history with mail body to entity Email, logging_general must be true + text_body: + link_format: 'table' # (none|inline|nextline|table|bbcode) https://github.com/mtibben/html2text/blob/b0fb318e4d97e9e05ffb3569e674dca7b25a6860/src/Html2Text.php#L216 + width: 80 # Maximum width (in chars) on each line, set to 0 for no text wrapping + + easyadmin: + dashboard_title: 'Acme Admin' \ No newline at end of file diff --git a/app/config/packages/reset_password.yaml b/app/config/packages/reset_password.yaml new file mode 100644 index 0000000..21c6f2e --- /dev/null +++ b/app/config/packages/reset_password.yaml @@ -0,0 +1,5 @@ +symfonycasts_reset_password: + request_password_repository: App\Repository\ResetPasswordRequestRepository + lifetime: 900 + throttle_limit: 60 + enable_garbage_collection: true \ No newline at end of file diff --git a/app/config/packages/routing.yaml b/app/config/packages/routing.yaml new file mode 100644 index 0000000..4b766ce --- /dev/null +++ b/app/config/packages/routing.yaml @@ -0,0 +1,12 @@ +framework: + router: + utf8: true + + # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. + # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands + #default_uri: http://localhost + +when@prod: + framework: + router: + strict_requirements: null diff --git a/app/config/packages/scheb_2fa.yaml b/app/config/packages/scheb_2fa.yaml new file mode 100644 index 0000000..42121d1 --- /dev/null +++ b/app/config/packages/scheb_2fa.yaml @@ -0,0 +1,31 @@ +# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/6.x/configuration.html +scheb_two_factor: + security_tokens: + - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken + - Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken + + + # Google Authenticator config + google: + enabled: true # If Google Authenticator should be enabled, default false + server_name: Symfony6Stack # Server name used in QR code + issuer: Symfony6Stack # Issuer name used in QR code + digits: 6 # don't change! it will break. Number of digits in authentication code + window: 1 # How many codes before/after the current one would be accepted as valid + template: view/core/2fa/login_2fa_form.html.twig # Template used to render the authentication form + #form_renderer: acme.custom_form_renderer # Use a custom form renderer service + + # Backup codes feature + backup_codes: + enabled: true # If the backup code feature should be enabled + #manager: acme.custom_backup_code_manager # Use a custom backup code manager + + trusted_device: + enabled: true # If the trusted device feature should be enabled + lifetime: 432000 # Lifetime of the trusted device token + extend_lifetime: false # Automatically extend lifetime of the trusted cookie on re-login + cookie_name: trusted_device # Name of the trusted device cookie + cookie_secure: false # Set the 'Secure' (HTTPS Only) flag on the trusted device cookie + cookie_same_site: "strict" # The same-site option of the cookie, can be "lax" or "strict" + cookie_domain: "localhost" # Domain to use when setting the cookie, fallback to the request domain if not set + cookie_path: "/" # Path to use when setting the cookie \ No newline at end of file diff --git a/app/config/packages/security.yaml b/app/config/packages/security.yaml new file mode 100644 index 0000000..72e43dd --- /dev/null +++ b/app/config/packages/security.yaml @@ -0,0 +1,68 @@ +security: + # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords + password_hashers: + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' + # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider + providers: + # used to reload user from session & other features (e.g. switch_user) + app_user_provider: + entity: + class: App\Entity\User + property: username + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + main: + lazy: true + custom_authenticator: + - App\Security\LoginFormAuthenticator + - App\Security\ApiTokenAuthenticator + logout: + path: app_logout + two_factor: + auth_form_path: 2fa_login # The route name you have used in the routes.yaml + check_path: 2fa_login_check # The route name you have used in the routes.yaml + enable_csrf: true + trusted_parameter_name: _trusted + + login_throttling: + max_attempts: 3 # per minute ... + interval: '1 minutes' # ... or in a custom period + + + # https://symfony.com/doc/current/security/impersonating_user.html + # switch_user: true + + access_control: + - { path: ^/admin, roles: ROLE_ADMIN } + - { path: ^/2fa, role: IS_AUTHENTICATED_2FA_IN_PROGRESS } + + role_hierarchy: + ROLE_ADMIN: ROLE_USER + ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] + +when@test: + security: + password_hashers: + # By default, password hashers are resource intensive and take time. This is + # important to generate secure password hashes. In tests however, secure hashes + # are not important, waste resources and increase test times. The following + # reduces the work factor to the lowest possible values. + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: + algorithm: auto + cost: 4 # Lowest possible value for bcrypt + time_cost: 3 # Lowest possible value for argon + memory_cost: 10 # Lowest possible value for argon +framework: + rate_limiter: + # define 2 rate limiters (one for username+IP, the other for IP) + username_ip_login: + policy: token_bucket + limit: 5 + rate: { interval: '5 minutes' } + + ip_login: + policy: sliding_window + limit: 50 + interval: '15 minutes' \ No newline at end of file diff --git a/app/config/packages/sensio_framework_extra.yaml b/app/config/packages/sensio_framework_extra.yaml new file mode 100644 index 0000000..1821ccc --- /dev/null +++ b/app/config/packages/sensio_framework_extra.yaml @@ -0,0 +1,3 @@ +sensio_framework_extra: + router: + annotations: false diff --git a/app/config/packages/stof_doctrine_extensions.yaml b/app/config/packages/stof_doctrine_extensions.yaml new file mode 100644 index 0000000..13a760d --- /dev/null +++ b/app/config/packages/stof_doctrine_extensions.yaml @@ -0,0 +1,8 @@ +# Read the documentation: https://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html +# See the official DoctrineExtensions documentation for more details: https://github.com/Atlantic18/DoctrineExtensions/tree/master/doc/ +stof_doctrine_extensions: + default_locale: en_US + orm: + default: + timestampable: true + softdeleteable: true \ No newline at end of file diff --git a/app/config/packages/test/parameters.yaml b/app/config/packages/test/parameters.yaml new file mode 100644 index 0000000..91755ae --- /dev/null +++ b/app/config/packages/test/parameters.yaml @@ -0,0 +1,32 @@ +parameters: + app: + default_locale: en + supported_locales: ['en', 'de'] + admin_locales: [de, en] + + timezone: 'Europe/Zurich' #default Timezone, users can set their own + date_format: 'yyyy-MM-dd' #default DateFormat, users can set their own, ICU Datetime Pattern (see https://unicode-org.github.io/icu/userguide/format_parse/datetime/) + time_format: 'HH:mm:ss' #default TimeFormat, users can set their own, ICU Datetime Pattern (see https://unicode-org.github.io/icu/userguide/format_parse/datetime/) + + core: + registration_active: true #allow new users to register + passwort_reset_active: true #allow password reset + + login: + identifier: 'both' # username, email or both + registration: + ask_username: true + ask_name: true # firstname and lastname + ask_locale: true + + mailer: + from_email: 'team@root.dev' + from_name: 'AcmeBotName' + logging_general: true # enable mail logging + logging_full: true # enable full log, sentmail-history with mail body to entity Email, logging_general must be true + text_body: + link_format: 'table' # (none|inline|nextline|table|bbcode) https://github.com/mtibben/html2text/blob/b0fb318e4d97e9e05ffb3569e674dca7b25a6860/src/Html2Text.php#L216 + width: 80 # Maximum width (in chars) on each line, set to 0 for no text wrapping + + easyadmin: + dashboard_title: 'Acme Admin' \ No newline at end of file diff --git a/app/config/packages/translation.yaml b/app/config/packages/translation.yaml new file mode 100644 index 0000000..e014602 --- /dev/null +++ b/app/config/packages/translation.yaml @@ -0,0 +1,6 @@ +framework: + default_locale: en + translator: + default_path: '%kernel.project_dir%/src/Ressources/translations' + fallbacks: + - en \ No newline at end of file diff --git a/app/config/packages/twig.yaml b/app/config/packages/twig.yaml new file mode 100644 index 0000000..45522b0 --- /dev/null +++ b/app/config/packages/twig.yaml @@ -0,0 +1,6 @@ +twig: + default_path: '%kernel.project_dir%/src/Ressources/templates' + +when@test: + twig: + strict_variables: true diff --git a/app/config/packages/validator.yaml b/app/config/packages/validator.yaml new file mode 100644 index 0000000..0201281 --- /dev/null +++ b/app/config/packages/validator.yaml @@ -0,0 +1,13 @@ +framework: + validation: + email_validation_mode: html5 + + # Enables validator auto-mapping support. + # For instance, basic validation constraints will be inferred from Doctrine's metadata. + #auto_mapping: + # App\Entity\: [] + +when@test: + framework: + validation: + not_compromised_password: false diff --git a/app/config/packages/verify_email.yaml b/app/config/packages/verify_email.yaml new file mode 100644 index 0000000..7012d1e --- /dev/null +++ b/app/config/packages/verify_email.yaml @@ -0,0 +1,2 @@ +symfonycasts_verify_email: + lifetime: 1800 \ No newline at end of file diff --git a/app/config/packages/web_profiler.yaml b/app/config/packages/web_profiler.yaml new file mode 100644 index 0000000..b946111 --- /dev/null +++ b/app/config/packages/web_profiler.yaml @@ -0,0 +1,17 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + + framework: + profiler: + only_exceptions: false + collect_serializer_data: true + +when@test: + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } diff --git a/app/config/preload.php b/app/config/preload.php new file mode 100644 index 0000000..5ebcdb2 --- /dev/null +++ b/app/config/preload.php @@ -0,0 +1,5 @@ +addSql('ALTER TABLE `user` MODIFY COLUMN `pid` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL AFTER `id`;'); + $this->addSql('ALTER TABLE `user` MODIFY COLUMN `is_active` TINYINT(1) NOT NULL AFTER `password`;'); + $this->addSql('ALTER TABLE `email` MODIFY COLUMN `pid` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL AFTER `id`;'); + $this->addSql('ALTER TABLE `log` MODIFY COLUMN `user_id` INT NULL DEFAULT NULL AFTER `message`;'); + $this->addSql('ALTER TABLE `user_role` MODIFY COLUMN `parent_role_id` INT NULL DEFAULT NULL AFTER `description`;'); + } +} + + diff --git a/app/phpunit.xml.dist b/app/phpunit.xml.dist new file mode 100644 index 0000000..ec017e9 --- /dev/null +++ b/app/phpunit.xml.dist @@ -0,0 +1,39 @@ + + + + + ./src + + + + + tests + + + + + + + + + + + + + + + + + + diff --git a/app/public/assets/css/easyadmin.css b/app/public/assets/css/easyadmin.css new file mode 100644 index 0000000..a8f1a7e --- /dev/null +++ b/app/public/assets/css/easyadmin.css @@ -0,0 +1,24 @@ +.badge.even-larger-badge{ + font-size: 1.25em; + line-height: 32px; +} + +.container2fa{ + max-width: 650px !important; +} + +.col2fa-colors{ + background-color: var(--page-login-form-bg); + border-radius: var(--border-radius); + box-shadow: var(--shadow-lg); + flex-wrap: wrap; +} + +/* + * === Popover + */ + +ul { + list-style: inside; + list-style-position: outside; +} \ No newline at end of file diff --git a/app/public/index.php b/app/public/index.php new file mode 100644 index 0000000..9982c21 --- /dev/null +++ b/app/public/index.php @@ -0,0 +1,9 @@ +security = $security; + } + + public function t(string $message, array $parameters = []): TranslatableMessage + { + return new TranslatableMessage($message, $parameters, 'admin'); + } + + #[IsGranted('ROLE_ADMIN')] + #[Route('/admin', name: 'admin')] + public function index(): Response + { + return $this->render('@EasyAdmin/pages/dashboard.html.twig'); + } + + public function configureDashboard(): Dashboard + { + return Dashboard::new() + ->setTranslationDomain('admin') + ->setTitle($this->getParameter('app')['easyadmin']['dashboard_title']); + } + + public function configureMenuItems(): iterable + { + yield MenuItem::linktoDashboard($this->t('Dashboard'), 'fa-solid fa-house'); + + if ($this->isGranted('ROLE_ADMIN')) { + yield MenuItem::section($this->t('admin.dashboard.menu.label.administration')); + yield MenuItem::linkToCrud($this->t('admin.dashboard.menu.label.users'), 'fas fa-user', User::class); + yield MenuItem::linkToCrud($this->t('admin.dashboard.menu.label.user_roles'), 'fas fa-user-tag', UserRole::class); + yield MenuItem::section($this->t('admin.dashboard.menu.label.system')); + yield MenuItem::linkToCrud($this->t('admin.dashboard.menu.label.logs'), 'fas fa-list', Log::class); + if ($this->isGranted('ROLE_SUPER_ADMIN')) { + yield MenuItem::linkToRoute($this->t('admin.dashboard.menu.label.phpinfo'), 'fa-brands fa-php', 'admin_phpinfo'); + } + } + } + + public function configureUserMenu(UserInterface $user): UserMenu + { + $menuItems[] = MenuItem::linkToCrud($this->t('admin.dashboard.menu.label.my_profile'), 'fa fa-id-card', User::class) + ->setAction('edit') + ->setEntityId($this->security->getUser()->getId()); + + if (!$this->security->getUser()->isTwoFactorEnabled()) { + $menuItems[] = MenuItem::section(); + $menuItems[] = MenuItem::linkToRoute('Activate 2FA', 'fa fa-lock', 'app_2fa_enable'); + } + + return parent::configureUserMenu($user) + ->displayUserAvatar(true) + ->setGravatarEmail($this->security->getUser()->getEmail()) + ->addMenuItems($menuItems); + } + + //Default Crud Settings + public function configureCrud(): Crud + { + return Crud::new() + ->setPaginatorPageSize(30) + ->setTimezone($this->security->getUser()->getTimeZone()) + ->setDateTimeFormat($this->security->getUser()->getDateFormat().' '.$this->security->getUser()->getTimeFormat()) + ->setDateFormat($this->security->getUser()->getDateFormat()) + ->setTimeFormat($this->security->getUser()->getTimeFormat()) + ; + } + + + public function configureAssets(): Assets + { + return Assets::new()->addCssFile('assets/css/easyadmin.css'); + } +} diff --git a/app/src/Controller/Admin/LogCrudController.php b/app/src/Controller/Admin/LogCrudController.php new file mode 100644 index 0000000..9be4849 --- /dev/null +++ b/app/src/Controller/Admin/LogCrudController.php @@ -0,0 +1,103 @@ +setEntityLabelInSingular('Log') + ->setEntityLabelInPlural($this->t('admin.crud.logs.titles.index_page')) + ->setPageTitle('index', '%entity_label_plural%') + ->setDateFormat('full') + ->setDefaultSort(['id' => 'DESC']) + ->setPaginatorPageSize(100) + ->setSearchFields(['type', 'context', 'action']) + ->setEntityPermission('ROLE_ADMIN') + ; + } + + public function configureFields(string $pageName): iterable + { + yield IntegerField::new('id') + ->setCssClass('col-auto'); + yield ChoiceField::new('level', $this->t('admin.crud.logs.label.level')) + ->renderAsBadges([ + 'ERROR' => 'danger', + 'WARNING' => 'warning', + 'INFO' => 'success', + 'NOTICE' => 'info', + 'DEBUG' => 'info', + 'NO_LEVEL' => 'secondary' + ]) + ->setChoices(['ERROR'=>'ERROR', 'WARNING'=>'WARNING', 'INFO'=>'INFO', 'NOTICE'=>'NOTICE', 'DEBUG'=>'DEBUG', 'NO_LEVEL'=>'NO_LEVEL']); + yield TextField::new('context', $this->t('admin.crud.logs.label.context')); + yield TextField::new('subcontext', $this->t('admin.crud.logs.label.subcontext')); + yield TextareaField::new('message', $this->t('admin.crud.logs.label.message')); + yield DateTimeField::new('createdAt', $this->t('admin.crud.generic.created_at')); + + yield FormField::addPanel($this->t('admin.crud.logs.titles.request_information')); + yield TextField::new('requestMethod', $this->t('admin.crud.logs.label.request_method'))->hideOnIndex(); + yield TextField::new('requestPath', $this->t('admin.crud.logs.label.request_path'))->hideOnIndex(); + yield TextField::new('clientIP', $this->t('admin.crud.logs.label.client_ip'))->hideOnIndex(); + yield AssociationField::new('user', $this->t('admin.crud.user.label.user'))->hideOnIndex(); + yield TextField::new('clientLocale', $this->t('admin.crud.logs.label.client_locale'))->hideOnIndex(); + + return $this; + } + + public function configureFilters(Filters $filters): Filters + { + return $filters + ->add('level', $this->t('admin.crud.logs.label.level')) + ->add('context', $this->t('admin.crud.logs.label.context')) + ->add('message', $this->t('admin.crud.logs.label.message')) + ->add('user', $this->t('admin.crud.user.label.user')) + ->add('createdAt', $this->t('admin.crud.generic.created_at')) + ; + } + + public function configureActions(Actions $actions): Actions + { + return $actions + ->disable('new') + ->disable('edit') + ->disable('delete') + ->add(Crud::PAGE_INDEX, Action::DETAIL) + + ->remove(Crud::PAGE_INDEX, Action::NEW) + ->remove(Crud::PAGE_INDEX, Action::EDIT) + ->remove(Crud::PAGE_INDEX, Action::DELETE) + ->remove(Crud::PAGE_DETAIL, Action::DELETE) + ->remove(Crud::PAGE_DETAIL, Action::EDIT) + ; + } +} diff --git a/app/src/Controller/Admin/PhpInfoController.php b/app/src/Controller/Admin/PhpInfoController.php new file mode 100644 index 0000000..62913f9 --- /dev/null +++ b/app/src/Controller/Admin/PhpInfoController.php @@ -0,0 +1,54 @@ + + #phpinfo {} + #phpinfo pre {margin: 0; font-family: monospace;} + #phpinfo a:link {color: #009; text-decoration: none; background-color: #fff;} + #phpinfo a:hover {text-decoration: underline;} + #phpinfo table {border-collapse: collapse; border: 0; width: 934px; box-shadow: 1px 2px 3px #ccc;} + #phpinfo .center {text-align: center;} + #phpinfo .center table {margin: 1em auto; text-align: left;} + #phpinfo .center th {text-align: center !important;} + #phpinfo td, th {border: 1px solid #666; font-size: 75%; vertical-align: baseline; padding: 4px 5px;} + #phpinfo h1 {font-size: 150%;} + #phpinfo h2 {font-size: 125%;} + #phpinfo .p {text-align: left;} + #phpinfo .e {background-color: #ccf; width: 300px; font-weight: bold;} + #phpinfo .h {background-color: #99c; font-weight: bold;} + #phpinfo .v {background-color: #ddd; max-width: 300px; overflow-x: auto; word-wrap: break-word;} + #phpinfo .v i {color: #999;} + #phpinfo img {float: right; border: 0;} + #phpinfo hr {width: 934px; background-color: #ccc; border: 0; height: 1px;} + h1.p{ font-size: 500% !important; } + +
+ $output +
+ "; + return $this->render('@EasyAdmin/pages/phpinfo.html.twig', ['phpinfo' => $output]); + } +} diff --git a/app/src/Controller/Admin/TwoFactorController.php b/app/src/Controller/Admin/TwoFactorController.php new file mode 100644 index 0000000..ea31396 --- /dev/null +++ b/app/src/Controller/Admin/TwoFactorController.php @@ -0,0 +1,107 @@ +log = $log; + $this->security = $security; + } + + #[Route("/authentication/2fa/enable", name:"app_2fa_enable")] + #[IsGranted("ROLE_USER")] + public function enable2fa(Request $request, GoogleAuthenticatorInterface $googleAutInterface, EntityManagerInterface $entityManager) + { + $errorMsg = null; + $user = $this->getUser(); + if (!$user) { + return $this->redirectToRoute('app_logout'); + } + $isLoggedInUser = ($user->getId() == $this->security->getUser()->getId()); + + $verificationCode = (int) $request->request->get('verificationCode'); + if ($verificationCode) { + if (!$user->isGoogleAuthenticatorEnabled() and $isLoggedInUser) { + if ($googleAutInterface->checkCode($user, $verificationCode)) { + $user->setTwoFactorEnabled(true); + $user->invalidateAllBackupCodes(); + $user->generateBackUpCode($count = 5); + $entityManager->flush(); + } else { + $errorMsg = 'admin.crud.user.twofactor.messages.verification_code_wrong'; + } + } + } else { + if (!$user->isGoogleAuthenticatorEnabled()) { + $user->setGoogleAuthenticatorSecret($googleAutInterface->generateSecret()); + $user->setTwoFactorEnabled(false); + $user->invalidateAllBackupCodes(); + $entityManager->flush(); + } + } + + + return $this->render('view/core/2fa/enable2fa.html.twig', [ + 'isEnabled' => $user->isTwoFactorEnabled(), + 'isLoggedInUser' => $isLoggedInUser, + 'disableURL' => '/admin?routeName=app_2fa_disable&disable=1', + 'errorMsg' => $errorMsg + ]); + } + + #[Route("/authentication/2fa/disable", name:"app_2fa_disable")] + #[IsGranted("ROLE_USER")] + public function disable2fa(Request $request, EntityManagerInterface $entityManager) + { + $user = $this->getUser(); + if (!$user) { + return $this->redirectToRoute('app_logout'); + } + + $disable = (1 == $request->get('disable')); + if ($disable) { + if ($user->isGoogleAuthenticatorEnabled()) { + $user->setTwoFactorEnabled(true); + $user->setGoogleAuthenticatorSecret(null); + $entityManager->flush(); + } + } + return $this->redirect('/admin?routeName=app_2fa_enable'); + } + + + #[Route("/authentication/2fa/qr-code", name: "app_2fa_qr_code")] + #[IsGranted("ROLE_USER")] + public function displayGoogleAuthenticatorQrCodeSVG(GoogleAuthenticatorInterface $googleAutInterface) + { + $qrContent = $googleAutInterface->getQRContent($this->getUser()); + + $result = Builder::create() + ->data($qrContent) + ->encoding(new Encoding('UTF-8')) + ->size(350) + ->margin(5) + ->writer(new SvgWriter()) + ->build(); + + return new Response($result->getString(), 200, ['Content-Type' => 'image/svg+xml']); + } +} diff --git a/app/src/Controller/Admin/UserCrudController.php b/app/src/Controller/Admin/UserCrudController.php new file mode 100644 index 0000000..7eb1a2d --- /dev/null +++ b/app/src/Controller/Admin/UserCrudController.php @@ -0,0 +1,315 @@ +adminContextProvider = $adminContextProvider; + $this->adminUrlGenerator = $adminUrlGenerator; + $this->security = $security; + $this->entityManager = $entityManager; + $this->passwordHasher = $passwordHasher; + $this->params = $params; + $this->userRepository = $userRepository; + } + + public function t(string $message, array $parameters = []): TranslatableMessage + { + return new TranslatableMessage($message, $parameters, 'admin'); + } + + public static function getEntityFqcn(): string + { + return User::class; + } + + public function configureCrud(Crud $crud): Crud + { + return parent::configureCrud($crud) + ->setEntityLabelInPlural($this->t('admin.crud.user.titles.index_page')) + ->setPageTitle('index', '%entity_label_plural%') + //->setPageTitle('edit', 'Edit %entity_label_singular%: %email %') + ->setPageTitle('edit', fn (User $user) => sprintf('Edit %s', $user->getUsername())) + ->setSearchFields(['username', 'email']) + ; + } + + /* + * Checks if logged in user ist the same as in the CRUD request + */ + private function getIsLoggedInUserEditingUserCrud(): bool + { + $requestUserId = $this->adminContextProvider->getContext()->getRequest()->query->get('entityId'); + $loggedInUserId = $this->security->getUser()->getId(); + return ($requestUserId == $loggedInUserId and $requestUserId != null); + } + + public function configureFields(string $pageName): iterable + { + if (Crud::PAGE_INDEX === $pageName) { + if ($this->isGranted('ROLE_ADMIN')) { + yield IntegerField::new('id'); + yield TextField::new('username', $this->t('admin.crud.user.label.username')); + yield TextField::new('email', $this->t('admin.crud.user.label.email')); + yield TextField::new('fullname', $this->t('admin.crud.user.label.fullname')); + yield ChoiceField::new('roles', $this->t('admin.crud.user.label.user_roles')) + ->setChoices(array_combine($this->getUserRolesField(), $this->getUserRolesField())) + ->renderAsBadges(); + + yield BooleanField::new('isActive', $this->t('admin.crud.generic.is_active')) + ->renderAsSwitch(false); + + yield DateTimeField::new('createdAt', $this->t('admin.crud.generic.created_at')); + } + } else { + if ($this->getIsLoggedInUserEditingUserCrud() or $this->isGranted('ROLE_ADMIN')) { + + /* + * ===== Tab: Account Information ===== + */ + yield FormField::addTab($this->t('admin.crud.user.titles.account_information')) + ->setIcon('far fa-address-card'); + + yield FormField::addPanel($this->t('admin.crud.user.titles.account_information')) + ->setIcon('far fa-address-card') + ->setCssClass('col-12 col-sm-12 col-md-8 col-lg-8 col-xl-8'); + + yield TextField::new('username', $this->t('admin.crud.user.label.username')) + ->setColumns('col-12'); + + yield TextField::new('email', $this->t('admin.crud.user.label.email')) + ->setColumns('col-12'); + + yield TextField::new('firstname', $this->t('admin.crud.user.label.firstname')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6'); + + yield TextField::new('lastname', $this->t('admin.crud.user.label.lastname')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6'); + + + yield FormField::addPanel($this->t('admin.crud.user.titles.user_settings')) + ->setIcon('fa fa-solid fa-screwdriver-wrench') + ->setCssClass('col-12 col-sm-12 col-md-8 col-lg-8 col-xl-8'); + + + yield LocaleField::new('locale', $this->t('admin.crud.user.label.locale')) + ->includeOnly($this->params->get('app')['admin_locales']) + ->setColumns('col-12'); + + yield CountryField::new('country', $this->t('admin.crud.user.label.country')) + ->setColumns('col-12'); + + yield TimezoneField::new('timezone', $this->t('admin.crud.user.label.time_zone')) + ->setColumns('col-12'); + + + yield ChoiceField::new('date_format', $this->t('admin.crud.user.label.date_format')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6') + ->setChoices([ + '2022-06-23 (yyyy-MM-dd)' => 'yyyy-MM-dd', + '6/23/2022 (M/d/yyyy)' => 'M/d/yyyy', + '23.06.2022 (dd.MM.yyyy)' => 'dd.MM.yyyy', + '23/06/2022 (dd/MM/yyyy)' => 'dd/MM/yyyy', + ]); + + yield ChoiceField::new('time_format', $this->t('admin.crud.user.label.time_format')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6') + ->setChoices([ + '15:23:42 (HH:mm:ss)' => 'HH:mm:ss', + '15:23 (HH:mm)' => 'HH:mm', + '3:23:42 PM (h:mm:ss a) '=> 'hh:mm:ss a', + '3:23 PM (h:mm a) '=> 'hh:mm:ss a', + ]); + + /* + * ===== Tab: Account Security ===== + */ + yield FormField::addTab('admin.crud.user.titles.security') + ->setIcon('far fa-lock'); + yield FormField::addPanel($this->t('admin.crud.user.titles.change_password')) + ->setIcon('fa fa-solid fa-key') + ->setCssClass('col-12 col-sm-12 col-md-8 col-lg-8 col-xl-8'); + yield Field::new('plainPassword', $this->t('admin.crud.user.label.new_password')) + ->onlyOnForms() + ->setFormType(RepeatedType::class) + ->setFormTypeOption('empty_data', '') + ->setFormTypeOptions([ + 'type' => PasswordType::class, + 'first_options' => ['label' => $this->t('admin.crud.user.label.new_password')], + 'second_options' => ['label' => $this->t('admin.crud.user.label.new_password_repeat')], + ]); + + + // 2Factor + $usrId = $this->adminContextProvider->getContext()->getRequest()->query->get('entityId'); + $twofactorEnabled = $this->userRepository->findOneBy(['id' => $usrId])->isTwoFactorEnabled(); + $backupCodes = $this->userRepository->findOneBy(['id' => $usrId])->getBackupCodes(); + yield FormField::addPanel() + ->setCssClass('col-12 col-sm-12 col-md-8 col-lg-8 col-xl-8') + ->setHelp( + $this->render('view/core/2fa/enable2fa_crud.html.twig', [ + 'isEnabled' => $twofactorEnabled, + 'isLoggedInUser' => $this->getIsLoggedInUserEditingUserCrud(), + 'enableTwoFactorURL' => '/admin?routeName=app_2fa_enable', + 'disableTwoFactorURL' => '/admin?routeName=app_2fa_disable', + 'backupCodes' => $backupCodes + ])->getContent() + ); + if (!$this->getIsLoggedInUserEditingUserCrud() and $twofactorEnabled and $this->isGranted('ROLE_ADMIN')) { + yield BooleanField::new('TwoFactorEnabled', $this->t('admin.crud.user.label.TwoFactorEnabled')); + } + } + + /* + * ===== Tab: Admin ===== + */ + if ($this->isGranted('ROLE_ADMIN')) { + yield FormField::addTab('Admin') + ->setIcon('far fa-users-cog'); + + yield FormField::addPanel($this->t('admin.crud.user.titles.admin_settings')) + ->setIcon('fas fa-users-cog') + ->setCssClass('col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6'); + + yield ChoiceField::new('roles', $this->t('admin.crud.user.label.user_roles')) + ->setColumns('col-12') + ->allowMultipleChoices() + ->autocomplete() + ->setChoices($this->getUserRolesField()); + + yield BooleanField::new('is_active', $this->t('admin.crud.generic.is_active')); + yield BooleanField::new('is_verified', $this->t('admin.crud.user.label.mail_verified')) + ->setFormTypeOption('disabled', 'disabled'); + + yield TextField::new('pid', 'PID') + ->setColumns('col-12') + ->setFormTypeOption('disabled', 'disabled'); + + yield DateTimeField::new('createdAt', $this->t('admin.crud.generic.created_at')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6') + ->setFormTypeOption('disabled', 'disabled'); + yield DateTimeField::new('updatedAt', $this->t('admin.crud.generic.updated_at')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6') + ->setFormTypeOption('disabled', 'disabled'); + yield DateTimeField::new('deletedAt', $this->t('admin.crud.generic.deleted_at')) + ->setColumns('col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6') + ->setFormTypeOption('disabled', 'disabled'); + } + + + yield FormField::addPanel('Logs')->setIcon('fas fa-log'); + + //yield AssociationField::new('logs'); + //yield ArrayField::new('logs') + // ->setFormTypeOption('label', false) + // ->setFormTypeOption('allow_delete', false) + // ->setFormTypeOption('allow_add', false) + // ->setFormTypeOption('disabled', 'disabled'); + } + } + + + public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void + { + + // set new password with encoder interface + if (method_exists($entityInstance, 'setPassword')) { + $passwords = $this->adminContextProvider->getContext()->getRequest()->request->all()['User']['plainPassword']; + + if (isset($passwords['first']) and empty(trim($passwords['first'])) == false) { + if (trim($passwords['first']) == trim($passwords['second'])) { + $plainPassword = trim($passwords['first']); + } else { + $this->addFlash('warning', $this->t('admin.crud.user.messages.passwort_not_match')); + } + if (!empty($plainPassword)) { + $encodedPassword = $this->passwordHasher->hashPassword( + $this->getUser(), + $plainPassword + ); + $entityInstance->setPassword($encodedPassword); + } else { + $entityInstance->eraseCredentials(); + } + } else { + $entityInstance->eraseCredentials(); + } + } + + //UserRoles + $roles = $this->adminContextProvider->getContext()->getRequest()->request->all()['User']['roles']; + $rolesToSave = $this->entityManager->getRepository(UserRole::class)->getAllRolesToSave($roles); + $entityInstance->setRoles($rolesToSave); + + parent::updateEntity($entityManager, $entityInstance); + } + + /* + public function configureActions(Actions $actions): Actions + { + return $actions + ->disable('new') + ->remove(Crud::PAGE_EDIT, Action::SAVE_AND_CONTINUE); + }*/ + + public function configureFilters(Filters $filters): Filters + { + return $filters + ->add('username', $this->t('admin.crud.user.label.username')) + ->add('email', $this->t('admin.crud.user.label.email')) + ->add('roles', $this->t('admin.crud.user.label.user_roles')) + ->add('isActive', $this->t('admin.crud.generic.is_active')); + } + + private function getUserRolesField(): array + { + $return = []; + $roles = $this->entityManager->getRepository(UserRole::class)->findAllActive(); + foreach ($roles as $r) { + $return[$r->getName()] = $r->getRole(); + } + return $return; + } +} diff --git a/app/src/Controller/Admin/UserRoleCrudController.php b/app/src/Controller/Admin/UserRoleCrudController.php new file mode 100644 index 0000000..5019017 --- /dev/null +++ b/app/src/Controller/Admin/UserRoleCrudController.php @@ -0,0 +1,92 @@ +setEntityLabelInPlural($this->t('admin.crud.user_roles.titles.index_page')) + ->setPageTitle('index', '%entity_label_plural%') + ->setPageTitle('new', $this->t('admin.crud.user_roles.label.new_role')) + + ->setDateFormat('full') + ->setDefaultSort(['id' => 'ASC']) + ->setSearchFields(['role', 'description']) + ->setEntityPermission('ROLE_ADMIN') + ; + } + + public function configureFields(string $pageName): iterable + { + if (Crud::PAGE_INDEX === $pageName) { + yield TextField::new('role', $this->t('admin.crud.user_roles.label.role')); + yield TextField::new('name', $this->t('admin.crud.user_roles.label.name')); + yield TextField::new('description', $this->t('admin.crud.user_roles.label.description')); + yield ArrayField::new('ParentRoleRecursive', $this->t('admin.crud.user_roles.label.parent_roles')); + yield BooleanField::new('active', $this->t('admin.crud.generic.is_active'))->renderAsSwitch(false); + yield DateTimeField::new('createdAt', $this->t('admin.crud.generic.created_at')); + } else { + yield FormField::addPanel($this->t('admin.crud.user_roles.label.role'))->setIcon('fa fa-user-tag'); + if (Crud::PAGE_NEW === $pageName) { + yield TextField::new('role', $this->t('admin.crud.user_roles.label.role')); + } elseif (Crud::PAGE_EDIT === $pageName) { + yield TextField::new('role', $this->t('admin.crud.user_roles.label.role'))->setFormTypeOption('disabled', 'disabled'); + } + + yield TextField::new('name', $this->t('admin.crud.user_roles.label.name')); + yield TextField::new('description', $this->t('admin.crud.user_roles.label.description')); + yield AssociationField::new('parentRole', $this->t('admin.crud.user_roles.label.parent_roles')); + yield BooleanField::new('active', $this->t('admin.crud.generic.is_active')); + yield BooleanField::new('systemrole', 'is systemrole')->setFormTypeOption('disabled', 'disabled'); + yield FormField::addPanel('Timestamps')->setIcon('fa fa-clock'); + + yield DateTimeField::new('createdAt', $this->t('admin.crud.generic.created_at'))->setColumns('col-4')->setFormTypeOption('disabled', 'disabled'); + yield DateTimeField::new('updatedAt', $this->t('admin.crud.generic.updated_at'))->setColumns('col-4')->setFormTypeOption('disabled', 'disabled'); + } + return $this; + } + + public function configureActions(Actions $actions): Actions + { + + // hide delete action if a UserRole is a Systemrole + $delete_action = parent::configureActions($actions)->getAsDto(Crud::PAGE_INDEX)->getAction(Crud::PAGE_INDEX, Action::DELETE); + if (!is_null($delete_action)) { + $delete_action->setDisplayCallable(function (UserRole $userrole) { + return $userrole->isSystemrole() === false; + }); + } + + return $actions + ->remove(Crud::PAGE_EDIT, Action::SAVE_AND_CONTINUE) + ->remove(Crud::PAGE_NEW, Action::SAVE_AND_ADD_ANOTHER) + ->Add(Crud::PAGE_NEW, Action::DELETE) + ; + } +} diff --git a/app/src/Controller/Core/LoginFormAuthenticatorController.php b/app/src/Controller/Core/LoginFormAuthenticatorController.php new file mode 100644 index 0000000..b309b4d --- /dev/null +++ b/app/src/Controller/Core/LoginFormAuthenticatorController.php @@ -0,0 +1,87 @@ +log = $log; + $this->security = $security; + } + + #[Route(path: '/authbridge', name: 'app_auth_bridge')] + public function auth_bridge(): Response + { + if ($this->getUser()) { + if ($this->security->isGranted('ROLE_ADMIN')) { + return $this->redirectToRoute('admin'); + } else { + return $this->redirectToRoute('missing_userforward'); + } + } + return $this->redirectToRoute('app_login'); + } + + #[Route(path: '/login', name: 'app_login_base')] + public function login_base(): Response + { + return $this->redirectToRoute('app_login'); + } + + #[Route(path: '/{_locale}/login', name: 'app_login')] + public function login(AuthenticationUtils $authenticationUtils, Request $request): Response + { + if (!in_array($request->getLocale(), $this->getParameter('app')['admin_locales'])) { + return $this->redirectToRoute('app_login_base'); + } + + if ($this->getUser()) { + return $this->redirectToRoute('app_auth_bridge'); + } + + // get the login error if there is one + $error = $authenticationUtils->getLastAuthenticationError(); + // last username entered by the user + $lastUsername = $authenticationUtils->getLastUsername(); + + $params = $this->getParameter('app')['core']; + $registrationActive = isset($params['registration_active']) ? $params['registration_active'] : false; + $passwordResetActive = isset($params['passwort_reset_active']) ? $params['passwort_reset_active'] : false; + + $userIdentifierType = ( + isset($params['login']['identifier']) and + in_array($params['login']['identifier'], ['email', 'username','both']) + ) ? $params['login']['identifier'] : 'email'; + + + return $this->render('view/core/login/login.html.twig', [ + 'lastIdentifier' => $lastUsername, + 'error' => $error, + + 'csrfTokenIntention' => 'authenticate', + 'registrationActive' => $registrationActive, + 'passwordResetActive' => $passwordResetActive, + 'userIdentifierType' => $userIdentifierType + ]); + } + + #[Route(path: '/logout', name: 'app_logout')] + public function logout(): void + { + throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); + } +} diff --git a/app/src/Controller/Core/RegistrationController.php b/app/src/Controller/Core/RegistrationController.php new file mode 100644 index 0000000..dfdfa4c --- /dev/null +++ b/app/src/Controller/Core/RegistrationController.php @@ -0,0 +1,167 @@ +emailVerifier = $emailVerifier; + $this->log = $log; + $this->translator = $translator; + } + + private function t($message, $params=[]) + { + return $this->translator->trans($message, $params, 'core'); + } + + #[Route('/register', name: 'app_register')] + public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response + { + if ($this->getUser()) { + return $this->redirectToRoute('app_auth_bridge'); + } + + $this->isActive = isset($this->getParameter('app')['core']['registration_active']) ? $this->getParameter('app')['core']['registration_active'] : false; + if (!$this->isActive) { + return $this->redirectToRoute('app_auth_bridge'); + } + + $options = [ + 'ask_username' => $this->getParameter('app')['core']['registration']['ask_username'], + 'ask_name' => $this->getParameter('app')['core']['registration']['ask_name'] + ]; + + $user = new User(); + $form = $this->createForm(RegistrationFormType::class, $user, $options); + $form->handleRequest($request); + $mailSent = false; + + if ($form->isSubmitted() && $form->isValid()) { + if (empty($user->getUsername())) { + $user->setUsername($user->getEmail()); + } + // encode the plain password + $user->setPassword( + $userPasswordHasher->hashPassword( + $user, + $form->get('plainPassword')->getData() + ) + ); + + $user->setActive(true); + $user->setTimezone($this->getParameter('app')['timezone']); //Load global timezone + $user->setDateFormat($this->getParameter('app')['date_format']); //Load global date format + $user->setTimeFormat($this->getParameter('app')['time_format']); //Load global time format + $user->setLocale($this->getParameter('app')['default_locale']); //Load global locale + + try { + $entityManager->persist($user); + $entityManager->flush(); + } finally { + $this->log->user_created($user); + } + + $mailSent = $this->sendVerificationMail($user); + + } + + return $this->render('view/core/registration/register.html.twig', [ + 'registrationForm' => $form->createView(), + 'askUsername' => $options['ask_username'], + 'askName' => $options['ask_name'], + 'mailSent' => $mailSent + ]); + } + + private function sendVerificationMail(?User $user) + { + $sendTo = empty($user->getFullName()) ? new Address($user->getEmail()) : new Address($user->getEmail(), $user->getFullName()); + $this->emailVerifier->sendEmailConfirmation( + 'app_verify_email', + $user, + (new TemplatedEmail()) + ->to($sendTo) + ->subject($this->t('service.registration.email.subject')) + ->htmlTemplate('email/core/registration_confirmation_email.html.twig') + ); + return true; + } + + #[Route('/verify/email', name: 'app_verify_email')] + public function verifyUserEmail(Request $request, TranslatorInterface $translator, UserRepository $userRepository): Response + { + $this->isActive = isset($this->getParameter('app')['core']['registration_active']) ? $this->getParameter('app')['core']['registration_active'] : false; + if (!$this->isActive) { + return $this->redirectToRoute('app_login'); + } + + $pid = $request->get('id'); + + if (null === $pid) { + return $this->redirectToRoute('app_register'); + } + + $user = $userRepository->findOneBy(['pid' => $pid]); + + if (null === $user) { + return $this->redirectToRoute('app_register'); + } + + // validate email confirmation link, sets User::isVerified=true and persists + try { + $this->emailVerifier->handleEmailConfirmation($request, $user); + } catch (VerifyEmailExceptionInterface $exception) { + $this->addFlash('verify_email_error', $translator->trans($exception->getReason(), [], 'VerifyEmailBundle')); + + return $this->redirectToRoute('app_login'); + } + + // @TODO Change the redirect on success and handle or remove the flash message in your templates + $this->addFlash('success', 'Your email address has been verified.'); + + return $this->redirectToRoute('app_login'); + } + + + #[Route('/request-verify-email', name: 'app_request_verify_email')] + public function requestVerifyUserEmail(Request $request, UserRepository $userRepository): Response + { + if ($this->getUser()) { + return $this->redirectToRoute('app_home'); + } + + $form = $this->createForm(ResetPasswordRequestFormType::class); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $user = $userRepository->findOneByEmail($form->get('email')->getData()); + if ($user) { + $this->sendVerificationMail($user); + return $this->redirectToRoute('app_login'); + } + } + return $this->render('view/core/resend_verifcation/resend_verifcation.html.twig', [ + 'requestForm' => $form->createView(), + ]); + } +} diff --git a/app/src/Controller/Core/ResetPasswordController.php b/app/src/Controller/Core/ResetPasswordController.php new file mode 100644 index 0000000..36febb7 --- /dev/null +++ b/app/src/Controller/Core/ResetPasswordController.php @@ -0,0 +1,203 @@ +translator->trans($message, $params, 'core'); + } + /** + * Display & process form to request a password reset. + */ + #[Route('', name: 'app_forgot_password_request')] + public function request(Request $request, TranslatorInterface $translator): Response + { + if ($this->getUser()) { + return $this->redirectToRoute('app_auth_bridge'); + } + + $this->isActive = isset($this->getParameter('app')['core']['passwort_reset_active']) ? $this->getParameter('app')['core']['passwort_reset_active'] : false; + if (!$this->isActive) { + return $this->redirectToRoute('app_login'); + } + + $form = $this->createForm(ResetPasswordRequestFormType::class); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + return $this->processSendingPasswordResetEmail( + $form->get('email')->getData(), + $this->mailer, + $translator + ); + } + + return $this->render('view/core/reset_password/request.html.twig', [ + 'requestForm' => $form->createView(), + ]); + } + + /** + * Confirmation page after a user has requested a password reset. + */ + #[Route('/check-email', name: 'app_check_email')] + public function checkEmail(): Response + { + $this->isActive = isset($this->getParameter('app')['core']['passwort_reset_active']) ? $this->getParameter('app')['core']['passwort_reset_active'] : false; + if (!$this->isActive) { + return $this->redirectToRoute('app_login'); + } + // Generate a fake token if the user does not exist or someone hit this page directly. + // This prevents exposing whether or not a user was found with the given email address or not + if (null === ($resetToken = $this->getTokenObjectFromSession())) { + $resetToken = $this->resetPasswordHelper->generateFakeResetToken(); + } + + return $this->render('view/core/reset_password/check_email.html.twig', [ + 'resetToken' => $resetToken, + ]); + } + + /** + * Validates and process the reset URL that the user clicked in their email. + */ + #[Route('/reset/{token}', name: 'app_reset_password')] + public function reset(Request $request, UserPasswordHasherInterface $passwordHasher, TranslatorInterface $translator, string $token = null): Response + { + $this->isActive = isset($this->getParameter('app')['core']['passwort_reset_active']) ? $this->getParameter('app')['core']['passwort_reset_active'] : false; + if (!$this->isActive) { + return $this->redirectToRoute('app_login'); + } + + if ($token) { + // We store the token in session and remove it from the URL, to avoid the URL being + // loaded in a browser and potentially leaking the token to 3rd party JavaScript. + $this->storeTokenInSession($token); + + return $this->redirectToRoute('app_reset_password'); + } + + $token = $this->getTokenFromSession(); + if (null === $token) { + throw $this->createNotFoundException('No reset password token found in the URL or in the session.'); + } + + try { + $user = $this->resetPasswordHelper->validateTokenAndFetchUser($token); + } catch (ResetPasswordExceptionInterface $e) { + $this->addFlash('reset_password_error', sprintf( + '%s - %s', + $translator->trans(ResetPasswordExceptionInterface::MESSAGE_PROBLEM_VALIDATE, [], 'ResetPasswordBundle'), + $translator->trans($e->getReason(), [], 'ResetPasswordBundle') + )); + + return $this->redirectToRoute('app_forgot_password_request'); + } + + // The token is valid; allow the user to change their password. + $form = $this->createForm(ChangePasswordFormType::class); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + // A password reset token should be used only once, remove it. + $this->resetPasswordHelper->removeResetRequest($token); + + // Encode(hash) the plain password, and set it. + $encodedPassword = $passwordHasher->hashPassword( + $user, + $form->get('plainPassword')->getData() + ); + $user->setPassword($encodedPassword); + $user->setIsVerified(true); + $this->entityManager->flush(); + + // The session is cleaned up after the password has been changed. + $this->cleanSessionAfterReset(); + + return $this->redirectToRoute('app_login'); + } + + return $this->render('view/core/reset_password/reset.html.twig', [ + 'resetForm' => $form->createView(), + ]); + } + + private function processSendingPasswordResetEmail(string $emailFormData, MailSender $mailer, TranslatorInterface $translator): RedirectResponse + { + $user = $this->entityManager->getRepository(User::class)->findOneBy([ + 'email' => $emailFormData, + ]); + + // Do not reveal whether a user account was found or not. + if (!$user) { + return $this->redirectToRoute('app_check_email'); + } + + try { + $resetToken = $this->resetPasswordHelper->generateResetToken($user); + } catch (ResetPasswordExceptionInterface $e) { + // If you want to tell the user why a reset email was not sent, uncomment + // the lines below and change the redirect to 'app_forgot_password_request'. + // Caution: This may reveal if a user is registered or not. + // + // $this->addFlash('reset_password_error', sprintf( + // '%s - %s', + // $translator->trans(ResetPasswordExceptionInterface::MESSAGE_PROBLEM_HANDLE, [], 'ResetPasswordBundle'), + // $translator->trans($e->getReason(), [], 'ResetPasswordBundle') + // )); + + return $this->redirectToRoute('app_check_email'); + } + + $sendTo = empty($user->getFullName()) ? new Address($user->getEmail()) : new Address($user->getEmail(), $user->getFullName()); + $email = (new TemplatedEmail()) + ->to($sendTo) + ->subject($this->t('service.password_reset.email.subject')) + ->htmlTemplate('email/core/reset_password.email.html.twig') + ->context([ + 'resetToken' => $resetToken, + 'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime(), + 'greeetingName' => (!empty($user->getFirstname()) ? $user->getFirstname() : $user->getUsername()), + ]) + ; + + $mailer->sendMail($email, $user); + + // Store the token object in session for retrieval in check-email route. + $this->setTokenObjectInSession($resetToken); + + return $this->redirectToRoute('app_check_email'); + } +} diff --git a/app/src/Controller/Core/TermsController.php b/app/src/Controller/Core/TermsController.php new file mode 100644 index 0000000..cd5c177 --- /dev/null +++ b/app/src/Controller/Core/TermsController.php @@ -0,0 +1,27 @@ +redirectToRoute('app_terms', ['_locale' => $this->getParameter('app')['default_locale']]); + } + + #[Route(path: '/{_locale}/terms', name: 'app_terms')] + public function terms($_locale, Request $request): Response + { + if (in_array($request->getLocale(), $this->getParameter('app')['admin_locales'])) { + return $this->render('view/core/terms/terms.html.twig'); + } else { + return $this->redirectToRoute('app_terms_base'); + } + } +} diff --git a/app/src/DataFixtures/AppFixtures.php b/app/src/DataFixtures/AppFixtures.php new file mode 100644 index 0000000..987f6fe --- /dev/null +++ b/app/src/DataFixtures/AppFixtures.php @@ -0,0 +1,17 @@ +persist($product); + + $manager->flush(); + } +} diff --git a/app/src/DataFixtures/SetupFixtures.php b/app/src/DataFixtures/SetupFixtures.php new file mode 100644 index 0000000..6355851 --- /dev/null +++ b/app/src/DataFixtures/SetupFixtures.php @@ -0,0 +1,99 @@ +log = $log; + $this->passwordHasher = $passwordHasher; + $this->params = $params; + } + public function load(ObjectManager $manager) + { + $this->loadDefaultAdminUser($manager); + $this->loadDefaultUserRoles($manager); + $this->log->fixtures('setup', 'SetupFixtures loaded', true); + } + + public function loadDefaultAdminUser(ObjectManager $manager) + { + $user = new User(); + $user->setUsername('admin'); + $user->setEmail('admin@admin.com'); + $user->setTimezone($this->params->get('app')['timezone']); //Load global Timezone + $user->setDateFormat($this->params->get('app')['date_format']); //Load global Timezone + $user->setTimeFormat($this->params->get('app')['time_format']); //Load global Timezone + $user->setLocale($this->params->get('app')['default_locale']); + $user->setCountry('CH'); + $user->setPassword( + $this->passwordHasher->hashPassword( + $user, + 'admin' + ) + ); + $user->setIsVerified(true); + $user->setActive(true); + #$user->setPid(); + $user->setRoles(['ROLE_SUPER_ADMIN']); + + $manager->persist($user); + $manager->flush(); + } + + public function loadDefaultUserRoles(ObjectManager $manager) + { + $roles = [ 'Super Admin' => 'ROLE_SUPER_ADMIN', + 'Admin' => 'ROLE_ADMIN', + 'User' => 'ROLE_USER']; + + foreach ($roles as $k => $v) { + $role = new Userrole(); + $role->setRole($v); + $role->setName($k); + $role->setDescription($k.' (System Role)'); + $role->setSystemrole(true); + $manager->persist($role); + } + + $role_test = new Userrole(); + $role_test->setRole('ROLE_TEST'); + $role_test->setName('ROLE_TEST'); + $role_test->setDescription('Testrole'); + $role_test->setSystemrole(false); + $role_test->setParentRole($role); + $manager->persist($role_test); + + $role_test2 = new Userrole(); + $role_test2->setRole('ROLE_TEST2'); + $role_test2->setName('ROLE_TEST2'); + $role_test2->setDescription('Testrole 2'); + $role_test2->setSystemrole(false); + $role_test2->setParentRole($role_test); + $manager->persist($role_test2); + + $manager->flush(); + } +} diff --git a/app/src/DataFixtures/TestFixtures.php b/app/src/DataFixtures/TestFixtures.php new file mode 100644 index 0000000..6a0dc35 --- /dev/null +++ b/app/src/DataFixtures/TestFixtures.php @@ -0,0 +1,99 @@ +log = $log; + $this->passwordHasher = $passwordHasher; + $this->params = $params; + } + public function load(ObjectManager $manager) + { + $this->loadDefaultAdminUser($manager); + $this->loadDefaultUserRoles($manager); + $this->log->fixtures('test', 'TestFixtures loaded', true); + } + + public function loadDefaultAdminUser(ObjectManager $manager) + { + $user = new User(); + $user->setUsername('admin'); + $user->setEmail('admin@admin.com'); + $user->setTimezone($this->params->get('app')['timezone']); //Load global Timezone + $user->setDateFormat($this->params->get('app')['date_format']); //Load global Timezone + $user->setTimeFormat($this->params->get('app')['time_format']); //Load global Timezone + $user->setLocale($this->params->get('app')['default_locale']); + $user->setCountry('CH'); + $user->setPassword( + $this->passwordHasher->hashPassword( + $user, + 'admin' + ) + ); + $user->setIsVerified(true); + $user->setActive(true); + #$user->setPid(); + $user->setRoles(['ROLE_SUPER_ADMIN']); + + $manager->persist($user); + $manager->flush(); + } + + public function loadDefaultUserRoles(ObjectManager $manager) + { + $roles = [ 'Super Admin' => 'ROLE_SUPER_ADMIN', + 'Admin' => 'ROLE_ADMIN', + 'User' => 'ROLE_USER']; + + foreach ($roles as $k => $v) { + $role = new Userrole(); + $role->setRole($v); + $role->setName($k); + $role->setDescription($k.' (System Role)'); + $role->setSystemrole(true); + $manager->persist($role); + } + + $role_test = new Userrole(); + $role_test->setRole('ROLE_TEST'); + $role_test->setName('ROLE_TEST'); + $role_test->setDescription('Testrole'); + $role_test->setSystemrole(false); + $role_test->setParentRole($role); + $manager->persist($role_test); + + $role_test2 = new Userrole(); + $role_test2->setRole('ROLE_TEST2'); + $role_test2->setName('ROLE_TEST2'); + $role_test2->setDescription('Testrole 2'); + $role_test2->setSystemrole(false); + $role_test2->setParentRole($role_test); + $manager->persist($role_test2); + + $manager->flush(); + } +} diff --git a/app/src/Entity/.gitignore b/app/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/app/src/Entity/ApiToken.php b/app/src/Entity/ApiToken.php new file mode 100644 index 0000000..6213028 --- /dev/null +++ b/app/src/Entity/ApiToken.php @@ -0,0 +1,63 @@ +id; + } + + public function getToken(): ?string + { + return $this->token; + } + + public function setToken(string $token): self + { + $this->token = $token; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } +} diff --git a/app/src/Entity/Email.php b/app/src/Entity/Email.php new file mode 100644 index 0000000..83222b7 --- /dev/null +++ b/app/src/Entity/Email.php @@ -0,0 +1,164 @@ +id; + } + + public function getSenderEmail(): ?string + { + return $this->senderEmail; + } + + public function setSenderEmail(string $senderEmail): self + { + $this->senderEmail = $senderEmail; + + return $this; + } + + public function getRecieverEmail(): ?string + { + return $this->recieverEmail; + } + + public function setRecieverEmail(string $recieverEmail): self + { + $this->recieverEmail = $recieverEmail; + + return $this; + } + + public function getSubject(): ?string + { + return $this->subject; + } + + public function setSubject(string $subject): self + { + $this->subject = $subject; + + return $this; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(?string $text): self + { + $this->text = $text; + + return $this; + } + + public function getHtml(): ?string + { + return $this->html; + } + + public function setHtml(?string $html): self + { + $this->html = $html; + + return $this; + } + + public function getMessageId(): ?string + { + return $this->MessageId; + } + + public function setMessageId(?string $MessageId): self + { + $this->MessageId = $MessageId; + + return $this; + } + + public function getFailed(): ?\DateTimeInterface + { + return $this->failed; + } + + public function setFailed(?\DateTimeInterface $failed): self + { + $this->failed = $failed; + + return $this; + } + + public function getOpened(): ?\DateTimeInterface + { + return $this->opened; + } + + public function setOpened(?\DateTimeInterface $opened): self + { + $this->opened = $opened; + + return $this; + } + + public function getUser(): ?User + { + return $this->User; + } + + public function setUser(?User $User): self + { + $this->User = $User; + + return $this; + } +} diff --git a/app/src/Entity/Log.php b/app/src/Entity/Log.php new file mode 100644 index 0000000..64d50f3 --- /dev/null +++ b/app/src/Entity/Log.php @@ -0,0 +1,191 @@ +subcontext = ''; + } + + public function __toString() + { + return (string) $this->message; + } + + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(name: 'id', type: 'integer')] + private ?int $id = null; + + #[ORM\Column(name: 'level', length: 255)] + private ?string $level = null; + + #[ORM\Column(name: 'context', length: 255)] + private ?string $context = null; + + #[ORM\Column(name: 'subcontext', length: 255)] + private ?string $subcontext = null; + + #[ORM\Column(name: 'message', type: Types::TEXT, nullable: true)] + private ?string $message = null; + + #[ORM\Column(name: 'is_success', nullable: true)] + private ?bool $success = null; + + #[ORM\ManyToOne(inversedBy: 'logs')] + private ?User $user = null; + + #[ORM\Column(name: 'clientIP', length: 255, nullable: true)] + private ?string $clientIP = null; + + #[ORM\Column(name: 'clientLocale', length: 20, nullable: true)] + private ?string $clientLocale = null; + + #[ORM\Column(name: 'requestMethod', length: 255, nullable: true)] + private ?string $requestMethod = null; + + #[ORM\Column(name: 'requestPath', type: Types::TEXT, nullable: true)] + private ?string $requestPath = null; + + + public function getId(): ?int + { + return $this->id; + } + + public function getLevel(): ?string + { + return $this->level; + } + + public function setLevel(string $level): self + { + $level = strtoupper($level); + if (in_array($level, self::ALLOWED_LEVELS)) { + $this->level = $level; + } else { + $this->level = 'NO_LEVEL'; + } + return $this; + } + + public function getContext(): ?string + { + return $this->context; + } + + public function setContext(string $context): self + { + $this->context = $context; + + return $this; + } + + public function getSubcontext(): ?string + { + return $this->subcontext; + } + + public function setSubcontext(string $subcontext): self + { + $this->subcontext = $subcontext; + + return $this; + } + + public function getMessage(): ?string + { + return $this->message; + } + + public function setMessage(?string $message): self + { + $this->message = $message; + + return $this; + } + + public function isSuccess(): ?bool + { + return $this->success; + } + + public function setSuccess(bool $success): self + { + $this->success = $success; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } + + public function getClientIP(): ?string + { + return $this->clientIP; + } + + public function setClientIP(?string $clientIP): self + { + $this->clientIP = $clientIP; + + return $this; + } + + public function getClientLocale(): ?string + { + return $this->clientLocale; + } + + public function setClientLocale(?string $clientLocale): self + { + $this->clientLocale = $clientLocale; + + return $this; + } + + public function getRequestMethod(): ?string + { + return $this->requestMethod; + } + + public function setRequestMethod(?string $requestMethod): self + { + $this->requestMethod = $requestMethod; + + return $this; + } + + public function getRequestPath(): ?string + { + return $this->requestPath; + } + + public function setRequestPath(?string $requestPath): self + { + $this->requestPath = $requestPath; + + return $this; + } +} diff --git a/app/src/Entity/ResetPasswordRequest.php b/app/src/Entity/ResetPasswordRequest.php new file mode 100644 index 0000000..712ebf6 --- /dev/null +++ b/app/src/Entity/ResetPasswordRequest.php @@ -0,0 +1,39 @@ +user = $user; + $this->initialize($expiresAt, $selector, $hashedToken); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getUser(): object + { + return $this->user; + } +} diff --git a/app/src/Entity/Traits/ActiveTrait.php b/app/src/Entity/Traits/ActiveTrait.php new file mode 100644 index 0000000..381a1f0 --- /dev/null +++ b/app/src/Entity/Traits/ActiveTrait.php @@ -0,0 +1,28 @@ +isActive; + } + /** + * @param bool $active + * @return ActiveTrait + */ + public function setActive(bool $isActive): self + { + $this->isActive = $isActive; + return $this; + } +} diff --git a/app/src/Entity/Traits/TimestampableCreatedTrait.php b/app/src/Entity/Traits/TimestampableCreatedTrait.php new file mode 100644 index 0000000..a3d1656 --- /dev/null +++ b/app/src/Entity/Traits/TimestampableCreatedTrait.php @@ -0,0 +1,37 @@ +createdAt; + } + + /** + * Set createdAt + * @param datetime $createdAt + */ + public function setCreatedAt(\DateTimeInterface $createdAt): self + { + $this->createdAt = $createdAt; + return $this; + } +} diff --git a/app/src/Entity/Traits/TimestampableDeletedTrait.php b/app/src/Entity/Traits/TimestampableDeletedTrait.php new file mode 100644 index 0000000..ebe2ed8 --- /dev/null +++ b/app/src/Entity/Traits/TimestampableDeletedTrait.php @@ -0,0 +1,46 @@ +deletedAt; + } + + /** + * Set or clear the deleted at timestamp. + * @return self + */ + public function setDeletedAt(?\DateTimeInterface $deletedAt = null): self + { + $this->deletedAt = $deletedAt; + return $this; + } + + /** + * Check if the entity has been soft deleted. + * @return bool + */ + public function isDeleted() + { + return null !== $this->deletedAt; + } +} diff --git a/app/src/Entity/Traits/TimestampableUpdatedTrait.php b/app/src/Entity/Traits/TimestampableUpdatedTrait.php new file mode 100644 index 0000000..c56322b --- /dev/null +++ b/app/src/Entity/Traits/TimestampableUpdatedTrait.php @@ -0,0 +1,37 @@ +updatedAt; + } + + /** + * Set updatedAt + * @param datetime $updatedAt + */ + public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + { + $this->updatedAt = $updatedAt; + return $this; + } +} diff --git a/app/src/Entity/Traits/UuidTrait.php b/app/src/Entity/Traits/UuidTrait.php new file mode 100644 index 0000000..fe8869b --- /dev/null +++ b/app/src/Entity/Traits/UuidTrait.php @@ -0,0 +1,32 @@ +pid; + } + + public function setPid(string $pid): self + { + $this->pid = $pid; + return $this; + } + + /** + * The Logic on how an UUID will be generated + * @return string + */ + public function generatePid(): string + { + return strtoupper(Uuid::v4()->__toString()); + } +} diff --git a/app/src/Entity/User.php b/app/src/Entity/User.php new file mode 100644 index 0000000..fbdf7e4 --- /dev/null +++ b/app/src/Entity/User.php @@ -0,0 +1,466 @@ +logs = new ArrayCollection(); + $this->emails = new ArrayCollection(); + $this->apiTokens = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + + public function getUsername(): ?string + { + return $this->username; + } + + public function setUsername(string $username): self + { + $this->username = $username; + + return $this; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(string $email): self + { + $this->email = $email; + + return $this; + } + + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUserIdentifier(): string + { + return (string) $this->email; + } + + + public function getFirstName(): ?string + { + return $this->firstName; + } + + public function setFirstName(?string $firstName): self + { + $this->firstName = $firstName; + + return $this; + } + + public function getLastName(): ?string + { + return $this->lastName; + } + + public function setLastName(?string $lastName): self + { + $this->lastName = $lastName; + + return $this; + } + + public function getFullName(): ?string + { + return trim($this->firstName . ' ' . $this->lastName); + } + /** + * @see UserInterface + */ + public function getRoles(): array + { + $roles = $this->roles; + // guarantee every user at least has ROLE_USER + $roles[] = 'ROLE_USER'; + + return array_unique($roles); + } + + public function setRoles(array $roles): self + { + $this->roles = $roles; + + return $this; + } + + /** + * @see PasswordAuthenticatedUserInterface + */ + public function getPassword(): string + { + return $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + public function eraseCredentials() + { + $this->plainPassword = null; + } + + public function getPlainPassword(): ?string + { + return $this->plainPassword; + } + + public function setPlainPassword(string $password): void + { + $this->plainPassword = $password; + } + + public function isVerified(): bool + { + return $this->isVerified; + } + + public function setIsVerified(bool $isVerified): self + { + $this->isVerified = $isVerified; + + return $this; + } + + public function getTimezone(): ?string + { + return $this->timezone; + } + + public function setTimezone(string $timezone): self + { + $this->timezone = $timezone; + + return $this; + } + + public function getCountry(): ?string + { + return $this->country; + } + + public function setCountry(?string $country): self + { + $this->country = $country; + + return $this; + } + + public function getDateFormat(): ?string + { + return $this->date_format; + } + + public function setDateFormat(?string $date_format): self + { + $this->date_format = $date_format; + + return $this; + } + + public function getTimeFormat(): ?string + { + return $this->time_format; + } + + public function setTimeFormat(?string $time_format): self + { + $this->time_format = $time_format; + + return $this; + } + + public function getLocale(): ?string + { + return $this->locale; + } + + public function setLocale(string $locale): self + { + $this->locale = $locale; + + return $this; + } + + public function __toString() + { + return (string) $this->getUsername(); + } + + /** + * @return Collection + */ + public function getLogs(): Collection + { + return $this->logs; + } + + public function addLog(Log $log): self + { + if (!$this->logs->contains($log)) { + $this->logs->add($log); + $log->setUser($this); + } + + return $this; + } + + /** + * @return Collection + */ + public function getEmails(): Collection + { + return $this->emails; + } + + public function addEmail(Email $email): self + { + if (!$this->emails->contains($email)) { + $this->emails->add($email); + $email->setUser($this); + } + + return $this; + } + + public function removeEmail(Email $email): self + { + if ($this->emails->removeElement($email)) { + // set the owning side to null (unless already changed) + if ($email->getUser() === $this) { + $email->setUser(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getApiTokens(): Collection + { + return $this->apiTokens; + } + + public function addApiToken(ApiToken $apiToken): self + { + if (!$this->apiTokens->contains($apiToken)) { + $this->apiTokens->add($apiToken); + $apiToken->setUser($this); + } + + return $this; + } + + public function removeApiToken(ApiToken $apiToken): self + { + if ($this->apiTokens->removeElement($apiToken)) { + // set the owning side to null (unless already changed) + if ($apiToken->getUser() === $this) { + $apiToken->setUser(null); + } + } + + return $this; + } + + + /* + * ====== 2FA + */ + + public function isTwoFactorEnabled(): bool + { + return ($this->twoFactor_active == true); + } + + public function setTwoFactorEnabled(?bool $twoFactor_active): void + { + $this->twoFactor_active = $twoFactor_active; + } + + + public function isGoogleAuthenticatorEnabled(): bool + { + return (null !== $this->twoFactor_secret_google) and $this->isTwoFactorEnabled(); + } + + public function getGoogleAuthenticatorUsername(): string + { + return $this->username; + } + + public function getGoogleAuthenticatorSecret(): ?string + { + return $this->twoFactor_secret_google; + } + + public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void + { + $this->twoFactor_secret_google = $googleAuthenticatorSecret; + } + + public function getBackupCodes(): ?array + { + return $this->twoFactor_backupCodes; + } + public function isBackupCode(string $code): bool + { + return in_array($code, $this->twoFactor_backupCodes); + } + + public function invalidateBackupCode(string $code): void + { + $key = array_search($code, $this->twoFactor_backupCodes); + if ($key !== false) { + unset($this->twoFactor_backupCodes[$key]); + } + $this->generateBackUpCode(); + } + + public function invalidateAllBackupCodes(): void + { + $this->twoFactor_backupCodes = []; + } + + + public function addBackUpCode(string $backUpCode): void + { + if (!in_array($backUpCode, $this->twoFactor_backupCodes)) { + $this->twoFactor_backupCodes[] = $backUpCode; + } + } + + public function generateBackUpCode($count=1): void + { + $codeLen = 6; + for ($i = 0; $i < $count; $i++) { + $backUpCode = substr(str_shuffle(str_repeat('0123456789', mt_rand(1, 10))), 1, $codeLen); + $this->addBackUpCode($backUpCode); + } + } + + public function getTrustedTokenVersion(): int + { + return $this->twoFactor_trustedTokenVersion; + } +} diff --git a/app/src/Entity/UserRole.php b/app/src/Entity/UserRole.php new file mode 100644 index 0000000..1d05178 --- /dev/null +++ b/app/src/Entity/UserRole.php @@ -0,0 +1,138 @@ +isActive = true; + $this->parentRole = null; + $this->systemrole = false; + } + + + public function __toString() + { + return (string) $this->role; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getRole(): ?string + { + return $this->role; + } + + public function setRole(string $role): self + { + $this->role = $role; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(string $description): self + { + $this->description = $description; + + return $this; + } + + public function isSystemrole(): ?bool + { + return $this->systemrole; + } + + public function setSystemrole(bool $systemrole): self + { + $this->systemrole = $systemrole; + + return $this; + } + + public function getParentRole(): ?self + { + return $this->parentRole; + } + + public function setParentRole(?self $parentRole): self + { + $this->parentRole = $parentRole; + + return $this; + } + + /* + * Recursive fetch all Parent Roles + */ + public function getParentRoleRecursive(): ?array + { + $return = []; + $parent = $this->parentRole; + while ($parent) { + $return[] = $parent->getRole() ; + $parent = $parent->parentRole; + } + return $return; + } + + public function getRoleAndParents(): ?array + { + return array_filter(array_unique(array_merge([$this->role], $this->getParentRoleRecursive()))); + } +} diff --git a/app/src/EventListener/EntityUUIDListener.php b/app/src/EventListener/EntityUUIDListener.php new file mode 100644 index 0000000..2df7639 --- /dev/null +++ b/app/src/EventListener/EntityUUIDListener.php @@ -0,0 +1,22 @@ +getEntity(); + + + if (is_callable([$entity, 'generatePid'])) { + $entity->setPid($entity->generatePid()); + } + } +} diff --git a/app/src/EventListener/LogoutSuccessEventListener.php b/app/src/EventListener/LogoutSuccessEventListener.php new file mode 100644 index 0000000..f3bd519 --- /dev/null +++ b/app/src/EventListener/LogoutSuccessEventListener.php @@ -0,0 +1,20 @@ +log = $log; + } + + public function onLogoutSuccess(LogoutEvent $logoutEvent): void + { + $user = $logoutEvent->getToken()->getUser(); + $this->log->logout($user); + } +} diff --git a/app/src/Form/Core/ChangePasswordFormType.php b/app/src/Form/Core/ChangePasswordFormType.php new file mode 100644 index 0000000..b36e495 --- /dev/null +++ b/app/src/Form/Core/ChangePasswordFormType.php @@ -0,0 +1,61 @@ +translator = $translator; + } + + private function t($message, $params=[]) + { + return $this->translator->trans($message, $params, 'core'); + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('plainPassword', RepeatedType::class, [ + 'type' => PasswordType::class, + 'invalid_message' => $this->t('service.registration.form.password.messages.no_match'), + 'options' => ['attr' => ['class' => 'password-field']], + 'required' => true, + 'first_options' => [ 'label' => $this->t('service.registration.form.password.label'), + 'attr' => [ 'class' => 'form-control'], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.password.messages.blank'), + ]), + new Length([ + 'min' => 6, + 'minMessage' => $this->t('service.registration.form.password.messages.min_lenght', ['limit' => 6]), + 'max' => 4096, + ]), + ], + ], + 'second_options' => [ 'label' => $this->t('service.registration.form.password.repeat_label'), + 'attr' => [ 'class' => 'form-control'], + ], + 'mapped' => false, + 'attr' => ['autocomplete' => 'new-password'], + + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([]); + } +} diff --git a/app/src/Form/Core/RegistrationFormType.php b/app/src/Form/Core/RegistrationFormType.php new file mode 100644 index 0000000..b844fc9 --- /dev/null +++ b/app/src/Form/Core/RegistrationFormType.php @@ -0,0 +1,137 @@ +translator = $translator; + } + + private function t($message, $params=[]) + { + return $this->translator->trans($message, $params, 'core'); + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + if ($options['ask_username']) { + $builder ->add('username', TextType::class, [ + 'label' => $this->t('service.registration.form.username.label'), + 'attr' => [ 'placeholder' => $this->t('service.registration.form.username.placeholder'), + 'autocomplete' => 'username', + 'class' => 'form-control' + ], + ]); + } + + if ($options['ask_name']) { + $builder ->add('firstname', TextType::class, [ + 'label' => $this->t('service.registration.form.firstname.label'), + 'attr' => [ 'placeholder' => $this->t('service.registration.form.firstname.placeholder'), + 'autocomplete' => 'firstname', + 'class' => 'form-control' + ], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.firstname.messages.blank'), + ]), + ], + ]); + $builder ->add('lastname', TextType::class, [ + 'label' => $this->t('service.registration.form.lastname.label'), + 'attr' => [ 'placeholder' => $this->t('service.registration.form.lastname.placeholder'), + 'autocomplete' => 'lastname', + 'class' => 'form-control' + ], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.lastname.messages.blank'), + ]), + ], + ]); + } + + $builder + ->add('email', EmailType::class, [ + 'label' => $this->t('service.registration.form.email.label'), + 'attr' => [ 'placeholder' => $this->t('service.registration.form.email.placeholder'), + 'autocomplete' => 'email', + 'class' => 'form-control' + ], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.email.messages.blank'), + ]), + ], + ]) + ->add('plainPassword', RepeatedType::class, [ + 'type' => PasswordType::class, + 'invalid_message' => $this->t('service.registration.form.password.messages.no_match'), + 'options' => ['attr' => ['class' => 'password-field']], + 'required' => true, + 'first_options' => [ 'label' => $this->t('service.registration.form.password.label'), + 'attr' => [ 'class' => 'form-control'], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.password.messages.blank'), + ]), + new Length([ + 'min' => 6, + 'minMessage' => $this->t('service.registration.form.password.messages.min_lenght', ['limit' => 6]), + 'max' => 4096, + ]), + ], + ], + 'second_options' => [ 'label' => $this->t('service.registration.form.password.repeat_label'), + 'attr' => [ 'class' => 'form-control'], + ], + 'mapped' => false, + 'attr' => ['autocomplete' => 'new-password'], + + ]) + ->add('agreeTerms', CheckboxType::class, [ + 'label' => $this->t('service.registration.form.terms.label'), + 'attr' => [ 'required' => 'true', + 'class' => 'form-check-input', + 'style' => 'width: 3em;', + 'role' => 'switch', + 'for' => 'term' + ], + 'mapped' => false, + 'constraints' => [ + new IsTrue([ + 'message' => $this->t('service.registration.form.terms.messages.agree'), + ]), + ], + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => User::class, + 'ask_username' => false, + 'ask_name' => false, + 'fistname' => null, + 'lastname' => null, + + ]); + } +} diff --git a/app/src/Form/Core/ResetPasswordRequestFormType.php b/app/src/Form/Core/ResetPasswordRequestFormType.php new file mode 100644 index 0000000..5895fbf --- /dev/null +++ b/app/src/Form/Core/ResetPasswordRequestFormType.php @@ -0,0 +1,45 @@ +translator = $translator; + } + + private function t($message, $params=[]) + { + return $this->translator->trans($message, $params, 'core'); + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('email', EmailType::class, [ + 'attr' => [ 'placeholder' => $this->t('service.registration.form.email.placeholder'), + 'autocomplete' => 'email', + 'class' => 'form-control' + ], + 'constraints' => [ + new NotBlank([ + 'message' => $this->t('service.registration.form.email.messages.blank'), + ]), + ], + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([]); + } +} diff --git a/app/src/Kernel.php b/app/src/Kernel.php new file mode 100644 index 0000000..d9a2e34 --- /dev/null +++ b/app/src/Kernel.php @@ -0,0 +1,17 @@ +getContainer()->getParameter('app')['timezone']); + } +} diff --git a/app/src/Repository/ApiTokenRepository.php b/app/src/Repository/ApiTokenRepository.php new file mode 100644 index 0000000..2bd5a1d --- /dev/null +++ b/app/src/Repository/ApiTokenRepository.php @@ -0,0 +1,66 @@ + + * + * @method ApiToken|null find($id, $lockMode = null, $lockVersion = null) + * @method ApiToken|null findOneBy(array $criteria, array $orderBy = null) + * @method ApiToken[] findAll() + * @method ApiToken[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ApiTokenRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ApiToken::class); + } + + public function add(ApiToken $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ApiToken $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return ApiToken[] Returns an array of ApiToken objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('a') +// ->andWhere('a.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('a.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?ApiToken +// { +// return $this->createQueryBuilder('a') +// ->andWhere('a.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/app/src/Repository/EmailRepository.php b/app/src/Repository/EmailRepository.php new file mode 100644 index 0000000..bffbc2f --- /dev/null +++ b/app/src/Repository/EmailRepository.php @@ -0,0 +1,66 @@ + + * + * @method Email|null find($id, $lockMode = null, $lockVersion = null) + * @method Email|null findOneBy(array $criteria, array $orderBy = null) + * @method Email[] findAll() + * @method Email[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class EmailRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Email::class); + } + + public function add(Email $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(Email $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return Email[] Returns an array of Email objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('e') +// ->andWhere('e.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('e.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?Email +// { +// return $this->createQueryBuilder('e') +// ->andWhere('e.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/app/src/Repository/LogRepository.php b/app/src/Repository/LogRepository.php new file mode 100644 index 0000000..dddef7a --- /dev/null +++ b/app/src/Repository/LogRepository.php @@ -0,0 +1,66 @@ + + * + * @method Log|null find($id, $lockMode = null, $lockVersion = null) + * @method Log|null findOneBy(array $criteria, array $orderBy = null) + * @method Log[] findAll() + * @method Log[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class LogRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Log::class); + } + + public function add(Log $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(Log $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return Log[] Returns an array of Log objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('l') +// ->andWhere('l.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('l.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?Log +// { +// return $this->createQueryBuilder('l') +// ->andWhere('l.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/app/src/Repository/ResetPasswordRequestRepository.php b/app/src/Repository/ResetPasswordRequestRepository.php new file mode 100644 index 0000000..97724d6 --- /dev/null +++ b/app/src/Repository/ResetPasswordRequestRepository.php @@ -0,0 +1,51 @@ + + * + * @method ResetPasswordRequest|null find($id, $lockMode = null, $lockVersion = null) + * @method ResetPasswordRequest|null findOneBy(array $criteria, array $orderBy = null) + * @method ResetPasswordRequest[] findAll() + * @method ResetPasswordRequest[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ResetPasswordRequestRepository extends ServiceEntityRepository implements ResetPasswordRequestRepositoryInterface +{ + use ResetPasswordRequestRepositoryTrait; + + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ResetPasswordRequest::class); + } + + public function add(ResetPasswordRequest $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ResetPasswordRequest $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function createResetPasswordRequest(object $user, \DateTimeInterface $expiresAt, string $selector, string $hashedToken): ResetPasswordRequestInterface + { + return new ResetPasswordRequest($user, $expiresAt, $selector, $hashedToken); + } +} diff --git a/app/src/Repository/UserRepository.php b/app/src/Repository/UserRepository.php new file mode 100644 index 0000000..f061e35 --- /dev/null +++ b/app/src/Repository/UserRepository.php @@ -0,0 +1,93 @@ + + * + * @method User|null find($id, $lockMode = null, $lockVersion = null) + * @method User|null findOneBy(array $criteria, array $orderBy = null) + * @method User[] findAll() + * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface +{ + public function __construct(ManagerRegistry $registry, ApiTokenRepository $apiTokenRepository) + { + parent::__construct($registry, User::class); + $this->apiTokenRepository = $apiTokenRepository; + } + + public function add(User $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(User $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + /** + * Used to upgrade (rehash) the user's password automatically over time. + */ + public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void + { + if (!$user instanceof User) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); + } + + $user->setPassword($newHashedPassword); + + $this->add($user, true); + } + + public function findByApiToken(string $token): ?User + { + return $this->apiTokenRepository->findOneBy([ + 'token' => $token, + 'isActive' => true, + 'deletedAt' => null + ])?->getUser(); + } + +// /** +// * @return User[] Returns an array of User objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('u') +// ->andWhere('u.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('u.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?User +// { +// return $this->createQueryBuilder('u') +// ->andWhere('u.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/app/src/Repository/UserRoleRepository.php b/app/src/Repository/UserRoleRepository.php new file mode 100644 index 0000000..23938dd --- /dev/null +++ b/app/src/Repository/UserRoleRepository.php @@ -0,0 +1,54 @@ + + * + * @method UserRole|null find($id, $lockMode = null, $lockVersion = null) + * @method UserRole|null findOneBy(array $criteria, array $orderBy = null) + * @method UserRole[] findAll() + * @method UserRole[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class UserRoleRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, UserRole::class); + } + + public function findAllActive() + { + return $this->findBy(array('isActive' => 1, 'deletedAt' => null), null); + } + + public function getRoleAndParents(string $role): array + { + $role = $this->createQueryBuilder('r') + ->andWhere('r.role = :role')->andWhere('r.isActive = 1')->andWhere('r.deletedAt IS NULL') + ->setParameter('role', $role) + ->getQuery()->getResult(); + + if ($role[0]) { + $return = $role[0]->getRoleAndParents(); + } else { + $this->addFlash('danger', $role.' is not active anymore , and was removed'); + $return = []; + } + return $return; + } + + public function getAllRolesToSave(array $roles) + { + $rolesToSave = []; + foreach ($roles as $r) { + $rolesToSave = array_merge($rolesToSave, $this->getRoleAndParents($r)); + } + + return array_filter(array_unique($rolesToSave)); + } +} diff --git a/app/src/Ressources/templates/bundles/EasyAdminBundle/fields/array_readonly.html.twig b/app/src/Ressources/templates/bundles/EasyAdminBundle/fields/array_readonly.html.twig new file mode 100644 index 0000000..ae6e996 --- /dev/null +++ b/app/src/Ressources/templates/bundles/EasyAdminBundle/fields/array_readonly.html.twig @@ -0,0 +1,16 @@ +{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} +{# @var field \EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto #} +{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #} + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +{% if ea.crud.currentAction == 'detail' %} +
    + {% for item in field.value %} +
  • {{ item }}
  • + {% endfor %} +
+{% else %} + + {{ field.formattedValue }} +{% endif %} diff --git a/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/dashboard.html.twig b/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/dashboard.html.twig new file mode 100644 index 0000000..0d621c5 --- /dev/null +++ b/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/dashboard.html.twig @@ -0,0 +1,12 @@ +{% extends '@EasyAdmin/page/content.html.twig' %} + +{% block page_title 'Welcome to the Dashboard' %} + +{% block page_content %} + You find this page here:
src/Ressources/templates/bundles/EasyAdminBundle/pages/dashboard.html.twig
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Amet justo donec enim diam vulputate ut. Id ornare arcu odio ut sem nulla pharetra diam. Accumsan tortor posuere ac ut consequat. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Volutpat blandit aliquam etiam erat velit. Vel quam elementum pulvinar etiam. Velit scelerisque in dictum non. Dui id ornare arcu odio. Elementum curabitur vitae nunc sed velit. Vitae congue eu consequat ac felis donec et. Malesuada pellentesque elit eget gravida cum sociis. Nisi quis eleifend quam adipiscing vitae. Euismod in pellentesque massa placerat duis ultricies lacus sed. Senectus et netus et malesuada fames ac turpis egestas integer. Eros donec ac odio tempor orci dapibus ultrices in iaculis. +

+ +{% endblock %} \ No newline at end of file diff --git a/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/phpinfo.html.twig b/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/phpinfo.html.twig new file mode 100644 index 0000000..104576c --- /dev/null +++ b/app/src/Ressources/templates/bundles/EasyAdminBundle/pages/phpinfo.html.twig @@ -0,0 +1,5 @@ +{% extends '@EasyAdmin/page/content.html.twig' %} + +{% block page_content %} + {{ phpinfo | raw }} +{% endblock %} \ No newline at end of file diff --git a/app/src/Ressources/templates/email/base.email.html.twig b/app/src/Ressources/templates/email/base.email.html.twig new file mode 100644 index 0000000..4d6d734 --- /dev/null +++ b/app/src/Ressources/templates/email/base.email.html.twig @@ -0,0 +1,35 @@ +{% trans_default_domain 'core' %} + + + + + {% block email_subject %}Subject{% endblock %} + + + + + + + + +
+ + {% block email_header %} + {% include 'email/include/header.email.html.twig' %} + {% endblock %} + + + + {% block email_footer %} + {% include 'email/include/footer.email.html.twig' %} + {% endblock %} +
+ {% block email_body %} + {% embed 'email/include/body.email.html.twig' %}{% endembed %} + {% endblock %} +
+
+ + \ No newline at end of file diff --git a/app/src/Ressources/templates/email/core/registration_confirmation_email.html.twig b/app/src/Ressources/templates/email/core/registration_confirmation_email.html.twig new file mode 100644 index 0000000..12fd981 --- /dev/null +++ b/app/src/Ressources/templates/email/core/registration_confirmation_email.html.twig @@ -0,0 +1,37 @@ +{% extends 'email/base.email.html.twig' %} +{% trans_default_domain 'core' %} + +{% block email_body %} + {% embed 'email/include/body.email.html.twig' %} + {% trans_default_domain 'core' %} + {% set email_body_title = 'service.registration.email.body_title' | trans %} + + {% block email_body_content %} +

+ {{ 'service.generic.email.greeting' | trans }} {{ greeetingName }} +

+

+ {{ 'service.registration.email.body_text' | trans }} +

+ + {% include 'email/include/spacingTable.html.twig' %} + +
+ {% set btnURL = signedUrl|raw %} + {% set btnText = 'service.registration.email.button_text' | trans %} + {% include 'email/include/button.html.twig' with {'btnURL': btnURL, 'btnText' : btnText} %} +
+ + {% include 'email/include/spacingTable.html.twig' %} + +

+ {{ 'service.generic.expire'| trans({'expire' : expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle')}) }} +

+ +

+ {{ 'service.generic.email.farewell' | trans }} +

+ + {% endblock email_body_content %} + {% endembed %} +{% endblock email_body %} \ No newline at end of file diff --git a/app/src/Ressources/templates/email/core/reset_password.email.html.twig b/app/src/Ressources/templates/email/core/reset_password.email.html.twig new file mode 100644 index 0000000..294ece0 --- /dev/null +++ b/app/src/Ressources/templates/email/core/reset_password.email.html.twig @@ -0,0 +1,38 @@ +{% extends 'email/base.email.html.twig' %} +{% trans_default_domain 'core' %} + + +{% block email_body %} + {% embed 'email/include/body.email.html.twig' %} + {% trans_default_domain 'core' %} + {% set email_body_title = 'service.password_reset.email.body_title'|trans %} + + {% block email_body_content %} +

+ {{ 'service.generic.email.greeting'|trans }} {{ greeetingName }} +

+

+ {{ 'service.password_reset.email.body_text'|trans }} +

+ + {% include 'email/include/spacingTable.html.twig' %} + +
+ {% set btnURL = url('app_reset_password', {token: resetToken.token}) %} + {% set btnText = 'service.password_reset.email.button_text'|trans %} + {% include 'email/include/button.html.twig' with {'btnURL': btnURL, 'btnText' : btnText} %} +
+ + {% include 'email/include/spacingTable.html.twig' %} + +

+ {{ 'service.generic.expire'|trans({'expire' : resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle')}) }} +

+ +

+ {{ 'service.generic.email.farewell'|trans }} +

+ + {% endblock email_body_content %} + {% endembed %} +{% endblock email_body %} diff --git a/app/src/Ressources/templates/email/include/body.email.html.twig b/app/src/Ressources/templates/email/include/body.email.html.twig new file mode 100644 index 0000000..c176140 --- /dev/null +++ b/app/src/Ressources/templates/email/include/body.email.html.twig @@ -0,0 +1,31 @@ +{% trans_default_domain 'core' %} + +{% if email_body_title is not defined %} + {% set email_body_title = 'Lorem ipsum' %} +{% endif %} + + + + {% if email_body_title %} + + + + {% endif %} + + + +
+

{{ email_body_title }}

+
+ {% block email_body_content %} +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras viverra quis leo vitae molestie. + Nullam imperdiet massa quis cursus luctus. Ut auctor pulvinar enim, eu luctus urna posuere sit amet. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis gravida diam, sed laoreet quam. + Praesent volutpat, quam nec ultricies cursus, enim elit cursus sem, nec porta enim enim id risus. + Fusce facilisis quam eu arcu sollicitudin, in facilisis massa accumsan. + Aenean dapibus nisi dui, vitae ullamcorper est viverra vel. + Donec non arcu tincidunt, egestas ex ac, tempor nisi. Nulla suscipit pellentesque arcu sit amet fermentum. +

+ {% endblock %} +
\ No newline at end of file diff --git a/app/src/Ressources/templates/email/include/button.html.twig b/app/src/Ressources/templates/email/include/button.html.twig new file mode 100644 index 0000000..9dd2015 --- /dev/null +++ b/app/src/Ressources/templates/email/include/button.html.twig @@ -0,0 +1,34 @@ +{% if btnBackgroundColor is not defined or btnBackgroundColor is null %} + {% set btnBackgroundColor = '#6174d1' %} +{% endif %} + +{% if btnFontColor is not defined or btnFontColor is null %} + {% set btnFontColor = '#FFFFFF' %} +{% endif %} + +{% if btnURL is not defined or btnURL is null %} + {% set btnURL = '#noURLdefined' %} +{% endif %} + +{% if btnText is not defined or btnText is null %} + {% set btnText = '#missingButtonText' %} +{% endif %} + + + +
+ + {{ btnText }} + +
+ + + + diff --git a/app/src/Ressources/templates/email/include/footer.email.html.twig b/app/src/Ressources/templates/email/include/footer.email.html.twig new file mode 100644 index 0000000..54dd0bc --- /dev/null +++ b/app/src/Ressources/templates/email/include/footer.email.html.twig @@ -0,0 +1,22 @@ +{% trans_default_domain 'core' %} +{% if footer_background_color is not defined or footer_background_color is null %} + {%set footer_background_color = '#ee4c50' %} +{% endif %} +{% if footer_font_color is not defined or footer_font_color is null %} + {%set footer_font_color = '#ffffff' %} +{% endif %} + + + + + + + + +
+ {% block email_footer_content %} +

{{ 'service.generic.email.footer'|trans }}

+ {% endblock %} +
+ + \ No newline at end of file diff --git a/app/src/Ressources/templates/email/include/header.email.html.twig b/app/src/Ressources/templates/email/include/header.email.html.twig new file mode 100644 index 0000000..9055c4f --- /dev/null +++ b/app/src/Ressources/templates/email/include/header.email.html.twig @@ -0,0 +1,15 @@ +{% trans_default_domain 'core' %} +{% if header_background_color is not defined or header_background_color is null %} + {%set header_background_color = '#70bbd9' %} +{% endif %} +{% if header_font_color is not defined or header_font_color is null %} + {%set header_font_color = '#000000' %} +{% endif %} + + + + {%block email_header_content %} + {{ 'service.generic.email.header'|trans|raw }} + {% endblock %} + + \ No newline at end of file diff --git a/app/src/Ressources/templates/email/include/spacingTable.html.twig b/app/src/Ressources/templates/email/include/spacingTable.html.twig new file mode 100644 index 0000000..8c249d5 --- /dev/null +++ b/app/src/Ressources/templates/email/include/spacingTable.html.twig @@ -0,0 +1,6 @@ + + + + + +
 
\ No newline at end of file diff --git a/app/src/Ressources/templates/email/include/stylesButton.html.twig b/app/src/Ressources/templates/email/include/stylesButton.html.twig new file mode 100644 index 0000000..d615275 --- /dev/null +++ b/app/src/Ressources/templates/email/include/stylesButton.html.twig @@ -0,0 +1,17 @@ +color: {{btnFontColor}}; +background-color: {{btnBackgroundColor}}; +strokecolor: {{btnBackgroundColor}}; +fillcolor: {{btnBackgroundColor}}; +border: 0px solid {{btnBackgroundColor}}; +border-radius:4px; +display:inline-block; +font-family: Arial, Helvetica; +font-size:15pt; +font-weight:bold; +line-height:40px; +text-align: center; +vertical-align: middle; +text-decoration:none; +width:75%; +min-height:40px; +-webkit-text-size-adjust:none; diff --git a/app/src/Ressources/templates/email/include/stylesButtonMso.html.twig b/app/src/Ressources/templates/email/include/stylesButtonMso.html.twig new file mode 100644 index 0000000..4075b9a --- /dev/null +++ b/app/src/Ressources/templates/email/include/stylesButtonMso.html.twig @@ -0,0 +1,4 @@ +height:40px; +min-height:40px; +v-text-anchor:middle; +width:300px; \ No newline at end of file diff --git a/app/src/Ressources/templates/email/test_email.html.twig b/app/src/Ressources/templates/email/test_email.html.twig new file mode 100644 index 0000000..ef23121 --- /dev/null +++ b/app/src/Ressources/templates/email/test_email.html.twig @@ -0,0 +1,15 @@ +{% extends 'email/base.email.html.twig' %} +{% trans_default_domain 'core' %} + + +{% block email_body %} + {% embed 'email/include/body.email.html.twig' %} + {% trans_default_domain 'core' %} + + {% set email_body_title = 'This is a test title' %} + + {% block email_body_content %} +

This is the email body, with a link

+ {% endblock email_body_content %} + {% endembed %} +{% endblock email_body %} diff --git a/app/src/Ressources/templates/view/base.html.twig b/app/src/Ressources/templates/view/base.html.twig new file mode 100644 index 0000000..f3e6710 --- /dev/null +++ b/app/src/Ressources/templates/view/base.html.twig @@ -0,0 +1,19 @@ + + + + + {% block page_title %}{% endblock %} + + {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #} + {% block stylesheets %} + + {{ encore_entry_link_tags('app') }} + {% endblock %} + {% block javascripts %} + {{ encore_entry_script_tags('app') }} + {% endblock %} + + + {% block body %}{% endblock %} + + diff --git a/app/src/Ressources/templates/view/core/2fa/enable2fa.html.twig b/app/src/Ressources/templates/view/core/2fa/enable2fa.html.twig new file mode 100644 index 0000000..d6b1b8a --- /dev/null +++ b/app/src/Ressources/templates/view/core/2fa/enable2fa.html.twig @@ -0,0 +1,141 @@ +{% extends '@EasyAdmin/page/content.html.twig' %} +{% trans_default_domain 'admin' %} + + +{% block page_title 'Two Factor Authentication' %} +{% block content_title '' %} + + + +{% block page_content %} +
+
+
+
+ {% if isEnabled %} +

+ + + {{ 'admin.crud.user.twofactor.badge.enabled'| trans }} + +

+

+ {{ 'admin.crud.user.twofactor.label.link_disable_intro'| trans }} + {{ 'admin.crud.user.twofactor.label.link_disable'| trans }}. +

+ + + {% else %} +

+ + {{ 'admin.crud.user.twofactor.badge.disabled'| trans }} + +

+ +

+ {{ 'admin.crud.user.twofactor.label.explain_paragraph'| trans }} +

+ + + + + {% endif %} +
+
+ {% if not isEnabled and isLoggedInUser %} +
+
+
+

{{ 'admin.crud.user.twofactor.label.step2'| trans }}

+
+
+ +
+
+
+
+
+
+
+
+

{{ 'admin.crud.user.twofactor.label.step2'| trans }}

+
+
+
+
+ +
+ +
+
+ + {% if errorMsg|default(false) %} +
+ {{ errorMsg|trans }} +
+ {% endif %} + + +
+ +
+
+
+
+
+
+
+ {% endif %} +
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/2fa/enable2fa_crud.html.twig b/app/src/Ressources/templates/view/core/2fa/enable2fa_crud.html.twig new file mode 100644 index 0000000..9f64ddd --- /dev/null +++ b/app/src/Ressources/templates/view/core/2fa/enable2fa_crud.html.twig @@ -0,0 +1,64 @@ + +{% trans_default_domain 'admin' %} + +
+
+
+ {% if isEnabled %} +

+ + {{ 'admin.crud.user.twofactor.badge.enabled'| trans }} + +

+ + {% if isLoggedInUser %} +
+ + {{ 'admin.crud.user.twofactor.label.link_disable_intro'| trans }} + + {{ 'admin.crud.user.twofactor.label.link_disable'| trans }} + . +
+
+

+ + {% if backupCodes|default(false) %} +

{{ 'admin.crud.user.twofactor.backup.title'| trans }}

+

{{ 'admin.crud.user.twofactor.backup.intro'| trans }}

+
+ + {% for c in backupCodes %} + {{c}}
+ {% endfor %} +
+
+ {% endif %} + {% endif %} + + + + + {% else %} +

+ + {{ 'admin.crud.user.twofactor.badge.disabled'| trans }} + +

+ + {% if isLoggedInUser %} +

+ {{ 'admin.crud.user.twofactor.label.explain_paragraph'| trans }} +

+ +

+

+

+ {% endif %} + {% endif %} +
+
+
diff --git a/app/src/Ressources/templates/view/core/2fa/login_2fa_form.html.twig b/app/src/Ressources/templates/view/core/2fa/login_2fa_form.html.twig new file mode 100644 index 0000000..f50da09 --- /dev/null +++ b/app/src/Ressources/templates/view/core/2fa/login_2fa_form.html.twig @@ -0,0 +1,86 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title = 'service.login.twofactor.page_title'|trans %} +{% block title %}{{'service.login.twofactor.page_title'|trans}}{% endblock %} + +{% block login_alert %} + {% if authenticationError %} +
+

{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}

+
+ {% endif %} +{% endblock %} + +{% block page_content %} + {% block login_form %} +

+ {{ 'service.login.twofactor.info_text'|trans }} +

+ + {% if authenticationError %} +

{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}

+ {% endif %} + + {# Let the user select the authentication method #} + {% if availableTwoFactorProviders|length > 1 %} +

{{ "choose_provider"|trans({}, 'SchebTwoFactorBundle') }}: + {% for provider in availableTwoFactorProviders %} + {{ provider }} + {% endfor %} +

+ {% endif %} + +
+ +
+ +
+ +
+
+ + {% if displayTrustedOption %} +

+ +

+ {% endif %} + {% if isCsrfProtectionEnabled %} + + {% endif %} + +
+ +
+
+ + {# The logout link gives the user a way out if they can't complete two-factor authentication #} +
+
+ +
+
+ {% endblock %} +{% endblock %} diff --git a/app/src/Ressources/templates/view/core/core_base.html.twig b/app/src/Ressources/templates/view/core/core_base.html.twig new file mode 100644 index 0000000..550c7c9 --- /dev/null +++ b/app/src/Ressources/templates/view/core/core_base.html.twig @@ -0,0 +1,37 @@ +{% extends '@!EasyAdmin/page/login.html.twig' %} +{% trans_default_domain 'core' %} + +{% if page_title is not defined or page_title is empty %} + {% set page_title = 'missing page_title' %} +{% endif %} + +{% block wrapper_wrapper %} + +{% endblock %} \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/login/login.html.twig b/app/src/Ressources/templates/view/core/login/login.html.twig new file mode 100644 index 0000000..deceb4c --- /dev/null +++ b/app/src/Ressources/templates/view/core/login/login.html.twig @@ -0,0 +1,93 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title = 'service.login.page.page_title' | trans %} + +{% block login_alert %} + {% if error|default(false) %} + {% if error.messageKey == 'login_email_not_verified' %} +
+ {{ 'service.verify_mail.message.not_verified'|trans({'url': path('app_request_verify_email')})|raw }} +
+ {% else %} +
+ {{ error.messageKey|trans(error.messageData, 'security') }} +
+ {% endif %} + + {% endif %} +{% endblock %} + +{% block page_content %} + {% block login_form %} +
+ {% if csrfTokenIntention|default(false) %} + + {% endif %} + + + {% if userIdentifierType == 'username'%} + {% set identifier_placholder = 'service.login.form.placeholder_username'|trans %} + {% elseif userIdentifierType == 'both'%} + {% set identifier_placholder = 'service.login.form.placeholder_both'|trans %} + {% else %} + {% set identifier_placholder = 'service.login.form.placeholder_email'|trans %} + {% endif %} + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ + {% if registrationActive %} +
+
+ +
+
+ {% endif %} + {% if passwordResetActive %} +
+
+ +
+
+ {% endif %} + + {% endblock %} +{% endblock %} \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/login/login_raw.html.twig b/app/src/Ressources/templates/view/core/login/login_raw.html.twig new file mode 100644 index 0000000..af85114 --- /dev/null +++ b/app/src/Ressources/templates/view/core/login/login_raw.html.twig @@ -0,0 +1,44 @@ +{% extends 'view/base.html.twig' %} + +{% block title %}Log in!{% endblock %} + +{% block body %} +
+ {% if error %} +
{{ error.messageKey|trans(error.messageData, 'security') }}
+ {% endif %} + + {% if app.user %} +
+ You are logged in as {{ app.user.userIdentifier }}, Logout +
+ {% endif %} + +

Please sign in

+ + + + + + + + {# + Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. + See https://symfony.com/doc/current/security/remember_me.html + +
+ +
+ #} + + +
+ +{% endblock %} + diff --git a/app/src/Ressources/templates/view/core/registration/register.html.twig b/app/src/Ressources/templates/view/core/registration/register.html.twig new file mode 100644 index 0000000..212b2ae --- /dev/null +++ b/app/src/Ressources/templates/view/core/registration/register.html.twig @@ -0,0 +1,103 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title ='service.registration.page.page_title' | trans %} + +{% block page_content %} + {% block login_form %} + {% for flashError in app.flashes('verify_email_error') %} + + {% endfor %} + + {% if mailSent|default(false) %} +
+ {{ 'service.registration.page.header_mailsent_text' | trans }} +
+
+
+ +
+
+ + {% else %} + {{ form_start(registrationForm) }} +
+ {{ 'service.registration.page.header_text' | trans }} +
+ + + {% if askUsername %} +
+ +
+ {{ form_row(registrationForm.username) }} +
+
+ {% endif %} + + {% if askName %} +
+ +
+ {{ form_row(registrationForm.firstname) }} +
+
+
+ +
+ {{ form_row(registrationForm.lastname) }} +
+
+ {% endif %} + + +
+ +
+ {{ form_row(registrationForm.email) }} +
+
+ +
+ +
+ {{ form_row(registrationForm.plainPassword) }} +
+
+ + +
+ {{ form_widget(registrationForm.agreeTerms) }} + +
+ + +
+ +
+ {{ form_end(registrationForm) }} +
+
+ +
+
+ {% endif %} + {% endblock %} +{% endblock %} + + + \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/registration/register_raw.html.twig b/app/src/Ressources/templates/view/core/registration/register_raw.html.twig new file mode 100644 index 0000000..887d475 --- /dev/null +++ b/app/src/Ressources/templates/view/core/registration/register_raw.html.twig @@ -0,0 +1,19 @@ +{% extends 'views/base.html.twig' %} + +{% block title %}Register{% endblock %} + +{% block body %} + {% for flash_error in app.flashes('verify_email_error') %} + + {% endfor %} + +

Register

+ + {{ form_start(registrationForm) }} + {{ form_row(registrationForm.email) }} + {{ form_row(registrationForm.plainPassword}) }} + {{ form_row(registrationForm.agreeTerms) }} + + + {{ form_end(registrationForm) }} +{% endblock %} diff --git a/app/src/Ressources/templates/view/core/resend_verifcation/resend_verifcation.html.twig b/app/src/Ressources/templates/view/core/resend_verifcation/resend_verifcation.html.twig new file mode 100644 index 0000000..3911a2d --- /dev/null +++ b/app/src/Ressources/templates/view/core/resend_verifcation/resend_verifcation.html.twig @@ -0,0 +1,37 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title ='service.verify_mail.page.title' | trans %} + +{% block page_content %} + {% block login_form %} + {{ form_start(requestForm) }} + +
+ {{ 'service.verify_mail.page.text' | trans }} +
+
+ +
+ {{ form_widget(requestForm.email) }} +
+
+ +
+ +
+ {{ form_end(requestForm) }} +
+
+ +
+
+ {% endblock %} +{% endblock %} + + + \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/reset_password/check_email.html.twig b/app/src/Ressources/templates/view/core/reset_password/check_email.html.twig new file mode 100644 index 0000000..cb6a807 --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/check_email.html.twig @@ -0,0 +1,28 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title = 'service.password_reset.page_sent.title' | trans %} + +{% block page_content %} + {% block login_form %} +
+

+ {{ 'service.password_reset.page_sent.text_intro' | trans }} + {{ 'service.generic.expire'| trans({'expire' : resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle')}) }} +

+

+ {{ 'service.password_reset.page_sent.text_outro'| trans({'url' : path('app_forgot_password_request') })|raw }} +

+
+
+ +
+
+
+ {% endblock %} +{% endblock %} + + + \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/reset_password/check_email_raw.html.twig b/app/src/Ressources/templates/view/core/reset_password/check_email_raw.html.twig new file mode 100644 index 0000000..74032a1 --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/check_email_raw.html.twig @@ -0,0 +1,11 @@ +{% extends 'view/base.html.twig' %} + +{% block title %}Password Reset Email Sent{% endblock %} + +{% block body %} +

+ If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password. + This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}. +

+

If you don't receive an email please check your spam folder or try again.

+{% endblock %} diff --git a/app/src/Ressources/templates/view/core/reset_password/request.html.twig b/app/src/Ressources/templates/view/core/reset_password/request.html.twig new file mode 100644 index 0000000..631faca --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/request.html.twig @@ -0,0 +1,36 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title ='service.password_reset.page.title' | trans %} + +{% block page_content %} + {% block login_form %} + {{ form_start(requestForm) }} +
+ {{ 'service.password_reset.page.text' | trans }} +
+
+ +
+ {{ form_widget(requestForm.email) }} +
+
+ +
+ +
+ {{ form_end(requestForm) }} +
+
+ +
+
+ {% endblock %} +{% endblock %} + + + \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/reset_password/request_raw.html.twig b/app/src/Ressources/templates/view/core/reset_password/request_raw.html.twig new file mode 100644 index 0000000..6f33777 --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/request_raw.html.twig @@ -0,0 +1,22 @@ +{% extends 'view/base.html.twig' %} + +{% block title %}Reset your password{% endblock %} + +{% block body %} + {% for flash_error in app.flashes('reset_password_error') %} + + {% endfor %} +

Reset your password

+ + {{ form_start(requestForm) }} + {{ form_row(requestForm.email) }} +
+ + Enter your email address and we will send you a + link to reset your password. + +
+ + + {{ form_end(requestForm) }} +{% endblock %} diff --git a/app/src/Ressources/templates/view/core/reset_password/reset.html.twig b/app/src/Ressources/templates/view/core/reset_password/reset.html.twig new file mode 100644 index 0000000..b8c3d67 --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/reset.html.twig @@ -0,0 +1,30 @@ +{% extends 'view/core/core_base.html.twig' %} +{% trans_default_domain 'core' %} + +{% set page_title ='service.password_reset.page_reset.title' | trans %} + +{% block page_content %} + {% block login_form %} + {{ form_start(resetForm) }} + +
+ {{ 'service.password_reset.page_reset.text' | trans }} +
+
+ +
+ {{ form_row(resetForm.plainPassword) }} +
+
+
+ +
+ + {{ form_end(resetForm) }} + {% endblock %} +{% endblock %} + + + \ No newline at end of file diff --git a/app/src/Ressources/templates/view/core/reset_password/reset_raw.html.twig b/app/src/Ressources/templates/view/core/reset_password/reset_raw.html.twig new file mode 100644 index 0000000..7b8a286 --- /dev/null +++ b/app/src/Ressources/templates/view/core/reset_password/reset_raw.html.twig @@ -0,0 +1,12 @@ +{% extends 'view/base.html.twig' %} + +{% block title %}Reset your password{% endblock %} + +{% block body %} +

Reset your password

+ + {{ form_start(resetForm) }} + {{ form_row(resetForm.plainPassword) }} + + {{ form_end(resetForm) }} +{% endblock %} diff --git a/app/src/Ressources/templates/view/core/terms/terms.html.twig b/app/src/Ressources/templates/view/core/terms/terms.html.twig new file mode 100644 index 0000000..6677c17 --- /dev/null +++ b/app/src/Ressources/templates/view/core/terms/terms.html.twig @@ -0,0 +1,73 @@ +{% extends 'view/base.html.twig' %} +{% trans_default_domain "tos" %} + +{% block page_title %}{{ 'basics.title.page'|trans }}{% endblock %} +{% block body %} +
+
+
+
+ +

{{ 'basics.title.tos'|trans }}

+
+ {% block content %} + {% set hasChapterContent = false %} + {% for c in 1..50 %} + {% set hasChapterContent = false %} + {% set chapter_title = 'chapter_' ~ c ~ '.title' %} + {% set chapter_text = 'chapter_' ~ c ~ '.text' %} + {% set chapter_next = 'chapter_' ~ (c+1) ~ '.text' %} + {% set chapter_break = chapter_next|trans != chapter_next %} + + {% if chapter_title|trans != chapter_title %} +

{{ c }}. {{ chapter_title|trans }}

+ {% endif %} + {% if chapter_text|trans != chapter_text %} + {{ chapter_text|trans|raw }} + {% set hasChapterContent = true %} + {% endif %} + + {% for sc in 1..30 %} + {% set subchapter_title = 'chapter_' ~ c ~ '.subchapter_' ~ sc ~ '.title' %} + {% set subchapter_text = 'chapter_' ~ c ~ '.subchapter_' ~ sc ~ '.text' %} + {% set subchapter_break = (subchapter_title|trans == subchapter_title) %} + + {% if not subchapter_break %} + {% if subchapter_title|trans != subchapter_title %} +

{{ c }}.{{ sc }}. {{ subchapter_title|trans }}

+ {% endif %} + {% if subchapter_text|trans != subchapter_text %} + {{ subchapter_text|trans|raw }} + {% set hasChapterContent = true %} + {% endif %} + + {% for ssc in 1..10 %} + {% set subsubchapter_title = 'chapter_' ~ c ~ '.subchapter_' ~ sc ~ '.subsubchapter_' ~ ssc ~ '.title' %} + {% set subsubchapter_text = 'chapter_' ~ c ~ '.subchapter_' ~ sc ~ '.subsubchapter_' ~ ssc ~ '.text' %} + {% set subsubchapter_break = (subsubchapter_text|trans == subsubchapter_text) %} + + {% if not subsubchapter_break %} + {% if subsubchapter_title|trans != subsubchapter_title %} +

{{ c }}.{{ sc }}.{{ ssc }}. {{ subsubchapter_title|trans }}

+ {% endif %} + {% if subsubchapter_text|trans != subsubchapter_text %} + {{ subsubchapter_text|trans|raw }} + {% set hasChapterContent = true %} + {% endif %} + {% endif %} + {% endfor %} + + {% endif %} + {% endfor %} + + {% if hasChapterContent and chapter_next|trans != chapter_next %} +
+ {% endif %} + {% endfor %} + {% endblock %} +
+
+
+
+{% endblock %} + diff --git a/app/src/Ressources/translations/admin+intl-icu.en.yaml b/app/src/Ressources/translations/admin+intl-icu.en.yaml new file mode 100644 index 0000000..aa51ca9 --- /dev/null +++ b/app/src/Ressources/translations/admin+intl-icu.en.yaml @@ -0,0 +1,85 @@ +admin: + dashboard: + menu: + label: + dashboard: Dashboard + administration: Administration + users: Users + user_roles: 'User Roles' + system: System + logs: Logs + phpinfo: phpinfo + my_profile: 'My Profile' + crud: + generic: + is_active: 'is active' + created_at: 'created at' + updated_at: 'updated at' + user: + titles: + index_page: Users + account_information: 'Account Information' + change_password: 'Change password' + admin_settings: 'Admin Settings' + user_settings: 'User Settings' + security: 'Security' + label: + username: Username + email: eMail + user_roles: 'User Roles' + fullname: 'Full name' + firstname: Firstname + lastname: Lastname + new_password: Password + new_password_repeat: 'Repeat password' + time_zone: Timezone + country: Country + mail_verified: 'Email is verfied' + user: User + date_format: 'Date format' + time_format: 'Time format' + locale: Language + messages: + passwort_not_match: 'Passwords dont match' + twofactor: + badge: + enabled: 'two-step verification is enabled' + disabled: 'two-step verification is not enabled' + label: + explain_paragraph: 'The two-step verification increases the security of your account. In addition to your password, a code is required in a second step, which is displayed on your smartphone.' + apps_intro: 'You may use one of the following apps for verification:' + link_enable: 'Click here to enable two-step verifcation' + link_disable_intro: 'If you want to disable the two-step verifcation:' + link_disable: 'Click here to disable' + step1: 'Step 1: scan this QR-Code' + step2: 'Step 2: verfication code' + submit_enable: 'Enable verification' + backup: + title: 'Backup Codes' + intro: 'Backup codes are one-time authentication codes, which can be used instead of the actual codes. They''re meant as emergency codes, when the authentication device is not available, and you have to pass the two-factor authentication process.' + messages: + verification_code_wrong: 'the verification code is wrong' + + user_roles: + titles: + index_page: 'User Roles' + label: + new_role: 'New Role' + role: Role + name: Name + description: Description + parent_roles: 'Parent Roles' + logs: + titles: + index_page: Logs + general: General + request_information: 'Request Information' + label: + level: Level + context: Context + subcontext: Subcontext + message: Message + request_method: 'Request Method' + request_path: 'Request Path' + client_ip: 'Client IP' + client_locale: 'Client locale' diff --git a/app/src/Ressources/translations/core+intl-icu.en.yaml b/app/src/Ressources/translations/core+intl-icu.en.yaml new file mode 100644 index 0000000..bbc0a1d --- /dev/null +++ b/app/src/Ressources/translations/core+intl-icu.en.yaml @@ -0,0 +1,97 @@ +service: + generic: + email: + greeting: Hey + farewell: Cheers + header: '' + footer: 'This is the footer' + expire: 'This link will expire in {expire}.' + form: + submit: + label_back: Back to login + login: + page: + page_title: 'Acme Login' + submit_label: 'Log in' + reset_link: 'Reset password' + register_link: Register + form: + placeholder_email: Email + placeholder_username: Username + placeholder_both: Username or Email + twofactor: + page_title: 'Two Factor Authentication' + info_text: 'Open your Authenticator app and type in the number.' + registration: + email: + subject: 'Please confirm your email' + body_title: 'Please confirm your email' + body_text: 'Please confirm your email address by clicking the following link:' + button_text: 'Confirm my Email' + page: + page_title: Registration + header_text: 'Please fill out the following fields to register' + header_mailsent_text: 'We sent you a link to verify your email address. Open the email and click the link. if you did not recieved the mail. you can login to resend the mail.' + form: + username: + label: Username + placeholder: 'Your username' + messages: + blank: 'Please enter your username' + alphanummeric: 'Only letters and numbers are allowed' + email: + label: Email + placeholder: john@doe.com + messages: + blank: 'Please enter your email' + firstname: + label: Firstname + placeholder: Firstname + messages: + blank: 'Please enter your firstname' + lastname: + label: Lastname + placeholder: Lastname + messages: + blank: 'Please enter your lastname' + password: + label: Password + repeat_label: 'Repeat Password' + messages: + blank: 'Please enter a password' + no_match: 'The password fields must match.' + min_lenght: 'Your password should be at least {limit} characters' + terms: + label: 'Agree terms' + url: /en/terms + messages: + agree: 'You should agree to our terms.' + submit: + label: Register + verify_mail: + page: + title: 'Resend Email Verification' + text: 'Enter your email address and we will send you a link to verify your account' + submit_label: 'Send email' + message: + not_verified: Your mailadress is not verfied yet. Send mail again + password_reset: + email: + subject: 'Your password reset request' + body_title: 'Reset password' + body_text: 'To reset your password, please click button below' + button_text: 'Reset Password' + page: + title: 'Reset Password' + text: 'Enter your email address and we will send you a link to reset your password.' + submit_label: 'Send password reset email' + page_sent: + title: 'Password Reset Email Sent' + text_intro: 'If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password.' + text_outro: 'If you don''t receive an email please check your spam folder or try again.' + submit_label: 'Back to page' + page_reset: + title: 'Reset Password' + text: '' + submit_label: 'Reset password now' + diff --git a/app/src/Ressources/translations/messages+intl-icu.en.yaml b/app/src/Ressources/translations/messages+intl-icu.en.yaml new file mode 100644 index 0000000..e69de29 diff --git a/app/src/Ressources/translations/tos+intl-icu.en.yaml b/app/src/Ressources/translations/tos+intl-icu.en.yaml new file mode 100644 index 0000000..0af9fe0 --- /dev/null +++ b/app/src/Ressources/translations/tos+intl-icu.en.yaml @@ -0,0 +1,73 @@ +basics: + title: + page: 'Terms and Conditions of Use' + tos: 'Terms and Conditions of Use' + +chapter_1: + title: 'Chapter' + text: | +

Lorem Ipsum

+ subchapter_1: + title: 'Subchapter' + text: | +

Lorem Ipsum

+ subsubchapter_1: + title: 'SubSubChapter' + text: | +

Lorem Ipsum

+ subsubchapter_2: + title: 'SubSubChapter' + text: | +

Lorem Ipsum

+chapter_2: + title: 'Terms' + text: | +

By accessing this Website, accessible from foo.com, you are agreeing to be bound by these Website Terms and Conditions of Use and agree that you are responsible for the agreement with any applicable local laws. If you disagree with any of these terms, you are prohibited from accessing this site. The materials contained in this Website are protected by copyright and trade mark law.

+ +chapter_3: + title: 'Use License' + text: | +

Permission is granted to temporarily download one copy of the materials on AcmeCorps's Website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:

+
    +
  • modify or copy the materials;
  • +
  • use the materials for any commercial purpose or for any public display;
  • +
  • attempt to reverse engineer any software contained on AcmeCorps's Website;
  • +
  • remove any copyright or other proprietary notations from the materials; or
  • +
  • transferring the materials to another person or "mirror" the materials on any other server.
  • +
+

This will let AcmeCorps to terminate upon violations of any of these restrictions. Upon termination, your viewing right will also be terminated and you should destroy any downloaded materials in your possession whether it is printed or electronic format. These Terms of Service has been created with the help of the Terms Of Service Generator.

+ +chapter_4: + title: 'Disclaimer' + text: | +

All the materials on AcmeCorps’s Website are provided "as is". AcmeCorps makes no warranties, may it be expressed or implied, therefore negates all other warranties. Furthermore, AcmeCorps does not make any representations concerning the accuracy or reliability of the use of the materials on its Website or otherwise relating to such materials or any sites linked to this Website.

+ +chapter_5: + title: 'Limitations' + text: | +

AcmeCorps or its suppliers will not be hold accountable for any damages that will arise with the use or inability to use the materials on AcmeCorps’s Website, even if AcmeCorps or an authorize representative of this Website has been notified, orally or written, of the possibility of such damage. Some jurisdiction does not allow limitations on implied warranties or limitations of liability for incidental damages, these limitations may not apply to you.

+ +chapter_6: + title: 'Limitations' + text: | +

The materials appearing on AcmeCorps’s Website may include technical, typographical, or photographic errors. AcmeCorps will not promise that any of the materials in this Website are accurate, complete, or current. AcmeCorps may change the materials contained on its Website at any time without notice. AcmeCorps does not make any commitment to update the materials.

+ +chapter_7: + title: 'Links' + text: | +

AcmeCorps has not reviewed all of the sites linked to its Website and is not responsible for the contents of any such linked site. The presence of any link does not imply endorsement by AcmeCorps of the site. The use of any linked website is at the user’s own risk.

+ +chapter_8: + title: 'Site Terms of Use Modifications' + text: | +

AcmeCorps may revise these Terms of Use for its Website at any time without prior notice. By using this Website, you are agreeing to be bound by the current version of these Terms and Conditions of Use.

+ +chapter_9: + title: 'Your Privacy' + text: | +

Please read our Privacy Policy.

+ +chapter_10: + title: 'Governing Law' + text: | +

Any claim related to AcmeCorps's Website shall be governed by the laws of ch without regards to its conflict of law provisions.

\ No newline at end of file diff --git a/app/src/Ressources/translations/validators+intl-icu.en.yaml b/app/src/Ressources/translations/validators+intl-icu.en.yaml new file mode 100644 index 0000000..b016ddd --- /dev/null +++ b/app/src/Ressources/translations/validators+intl-icu.en.yaml @@ -0,0 +1,9 @@ +validators: + general: + blank: 'This value cant be blank' + username: + alphanummeric: 'Only letters and numbers are allowed' + email: + invalid: 'The email is not a valid email.' + + diff --git a/app/src/Security/ApiTokenAuthenticator.php b/app/src/Security/ApiTokenAuthenticator.php new file mode 100644 index 0000000..99e3b41 --- /dev/null +++ b/app/src/Security/ApiTokenAuthenticator.php @@ -0,0 +1,63 @@ +userRepository = $userRepository; + } + + public function supports(Request $request): ?bool + { + return $request->headers->has('x-api-token'); + } + + public function authenticate(Request $request): Passport + { + $apiToken = $request->headers->get('x-api-token'); + if ($apiToken === null) { + throw new CustomUserMessageAuthenticationException('No API token provided'); + } + + return new SelfValidatingPassport( + new UserBadge( + $apiToken, + function ($apiToken) { + $user = $this->userRepository->findByApiToken($apiToken); + + if (!$user) { + throw new UserNotFoundException(); + } + + return $user; + } + ) + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + return null; + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + $data = ['message'=> strstr($exception->getMessageKey(), implode(', ', $exception->getMessageData())) ]; + return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); + } +} diff --git a/app/src/Security/EmailVerifier.php b/app/src/Security/EmailVerifier.php new file mode 100644 index 0000000..a0b8fa1 --- /dev/null +++ b/app/src/Security/EmailVerifier.php @@ -0,0 +1,58 @@ +verifyEmailHelper->generateSignature( + $verifyEmailRouteName, + $user->getId(), + $user->getEmail(), + ['id' => $user->getPid()] + ); + + $context = $email->getContext(); + $context['signedUrl'] = $signatureComponents->getSignedUrl(); + $context['greeetingName'] = (!empty($user->getFirstname()) ? $user->getFirstname() : $user->getUsername()); + $context['expiresAtMessageKey'] = $signatureComponents->getExpirationMessageKey(); + $context['expiresAtMessageData'] = $signatureComponents->getExpirationMessageData(); + + $email->context($context); + + $this->mailer->sendMail($email, $user); + } + + /** + * @throws VerifyEmailExceptionInterface + */ + public function handleEmailConfirmation(Request $request, UserInterface $user): void + { + $this->verifyEmailHelper->validateEmailConfirmation($request->getUri(), $user->getId(), $user->getEmail()); + + $user->setIsVerified(true); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $this->log->user_emailverified($user); + } +} diff --git a/app/src/Security/LoginFormAuthenticator.php b/app/src/Security/LoginFormAuthenticator.php new file mode 100644 index 0000000..c593675 --- /dev/null +++ b/app/src/Security/LoginFormAuthenticator.php @@ -0,0 +1,106 @@ +entityManager = $entityManager; + $this->log = $log; + } + + public function authenticate(Request $request): Passport + { + $userIdentifier = $request->request->get('username', ''); + + $request->getSession()->set(Security::LAST_USERNAME, $userIdentifier); + + return new Passport( + new UserBadge($userIdentifier, function ($userIdentifier) { + $user_username_exists = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $userIdentifier]); + $user_email_exists = null; + $activeParams = null; + + if (!$user_username_exists) { + $user_email_exists = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $userIdentifier]); + + if (!$user_email_exists) { + $this->log->login('User could not be found.', false); + throw new UserNotFoundException(); + } else { + $user_username_exists = null; + $activeParams['email'] = $userIdentifier; + } + } else { + $activeParams['username'] = $userIdentifier; + } + + if ($activeParams != null) { + $activeParams['deletedAt'] = null; + + $user = $this->entityManager->getRepository(User::class)->findOneBy($activeParams); + + if (!$user) { + $this->log->login('User not found', false); + throw new UserNotFoundException(); + } else { + if ($user->isActive() and $user->isVerified()) { + $this->log->login('', true); + return $user; + } elseif (!$user->isVerified() and $user->isActive()) { + $this->log->login('email not verified', false); + throw new CustomUserMessageAuthenticationException('login_email_not_verified'); + } else { + $this->log->login('User not active', false); + throw new UserNotFoundException(); + } + } + } + }), + new PasswordCredentials($request->request->get('password', '')), + [ + new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')), + ] + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) { + return new RedirectResponse($targetPath); + } + + return new RedirectResponse($this->urlGenerator->generate('admin')); + } + + protected function getLoginUrl(Request $request): string + { + return $this->urlGenerator->generate(self::LOGIN_ROUTE); + } +} diff --git a/app/src/Service/Log/LogMailerService.php b/app/src/Service/Log/LogMailerService.php new file mode 100644 index 0000000..85b200b --- /dev/null +++ b/app/src/Service/Log/LogMailerService.php @@ -0,0 +1,129 @@ +generalLogging = $generalLogging; + $this->fullLogging = $fullLogging; + return $this; + } + + + public function sendMail($mail, ?String $message=null, ?bool $success=false, ?User $user = null): self + { + $message = $this->getMessagePropertyString($mail); + + if ($user) { + $this->log->setUser($user); + } + + if ($success) { + if ($this->generalLogging) { + $subContext = 'sent'; + $this->info('mailer', $subContext, $message, $success); + } + } else { + $subContext = 'not sent'; + $this->error('mailer', $subContext, $message, $success); + } + + if ($this->generalLogging) { + $this->setSentMailDetailedLog($mail, $success, $user); + } + return $this; + } + + + private function getMessageProperties($message): ?array + { + $collection = []; + $collection['messageId'] = ''; + + if ($message instanceof SentMessage) { + $collection['from'] = $message->getEnvelope()->getSender()->getAddress(); + + $collection['to'] = join( + ', ', + array_map(function ($entry) { + return $entry->getAddress(); + }, $message->getEnvelope()->getRecipients()) + ); + + $collection['messageId'] = $message->getMessageId(); + $collection['subject'] = $message->getOriginalMessage()->getHeaders()->get('Subject')->getValue(); + $collection['bodyHTML'] = $message->getOriginalMessage()->getHtmlBody(); + $collection['bodyText'] = $message->getOriginalMessage()->getTextBody(); + } else { + $collection['from'] = join( + ', ', + array_map(function ($entry) { + return $entry->getAddress(); + }, $message->getFrom()) + ); + $collection['to'] = join( + ', ', + array_map(function ($entry) { + return $entry->getAddress(); + }, $message->getTo()) + ); + $collection['subject'] = $message->getSubject(); + $collection['bodyHTML'] = $message->getHtmlBody(); + $collection['bodyText'] = $message->getTextBody(); + } + return array_filter($collection); + } + + private function getMessagePropertyString($message, $withBody = false): ?String + { + $return = ""; + foreach ($this->getMessageProperties($message) as $key => $value) { + if ($value) { + if (($withBody and str_contains($key, 'body')) or !str_contains($key, 'body')) { + $return .= strtoupper($key) . ': ' . $value . PHP_EOL; + } + } + } + return $return; + } + + private function setSentMailDetailedLog($message, ?bool $success, ?User $user): void + { + $properties = $this->getMessageProperties($message); + + $maillog = new EntityEmail(); + $maillog->setSubject($properties['subject']); + $maillog->setSenderEmail($properties['from']); + $maillog->setRecieverEmail($properties['to']); + + if ($this->fullLogging) { + $maillog->setHtml($properties['bodyHTML']); + $maillog->setText($properties['bodyText']); + } + + if (isset($properties['messageId'])) { + $maillog->setMessageId($properties['messageId']); + } + + if ($user) { + $maillog->setUser($user); + } + if (!$success) { + $maillog->setFailed(new \DateTime()); + } + + $this->manager->persist($maillog); + $this->manager->flush(); + } +} diff --git a/app/src/Service/Log/LogService.php b/app/src/Service/Log/LogService.php new file mode 100644 index 0000000..748ce49 --- /dev/null +++ b/app/src/Service/Log/LogService.php @@ -0,0 +1,73 @@ +manager = $manager; + $this->security = $security; + $this->requestStack = $requestStack; + + $this->log = new Log(); + $this->log->setUser($this->security->getUser()) ; + + if (!empty($this->requestStack->getCurrentRequest())) { + $this->log->setClientIP($this->requestStack->getCurrentRequest()->getClientIp()); + $this->log->setClientLocale($this->requestStack->getCurrentRequest()->getLocale()); + $this->log->setRequestMethod($this->requestStack->getCurrentRequest()->getMethod()); + $this->log->setRequestPath($this->requestStack->getCurrentRequest()->getPathInfo()); + } + } + + private function logEvent(?String $level, ?String $context, ?String $subcontext = null, ?String $message, ?bool $isSuccess = null): self + { + $this->log->setLevel($level); + $this->log->setContext($context); + $this->log->setSubcontext($subcontext); + $this->log->setMessage($message); + $this->log->setSuccess($isSuccess); + + $this->manager->persist($this->log); + $this->manager->flush(); + return $this; + } + + public function info(?String $context, ?String $subcontext, ?String $message, ?bool $isSuccess = null): self + { + $this->logEvent('INFO', $context, $subcontext, $message, $isSuccess); + return $this; + } + + public function debug(?String $context, ?String $subcontext, ?String $message, ?bool $isSuccess = null): self + { + $this->logEvent('DEBUG', $context, $subcontext, $message, $isSuccess); + return $this; + } + + public function warning(?String $context, ?String $subcontext, ?String $message, ?bool $isSuccess = false): self + { + $this->logEvent('WARNING', $context, $subcontext, $message, $isSuccess); + return $this; + } + + public function error(?String $context, ?String $subcontext, ?String $message, ?bool $isSuccess = false): self + { + $this->logEvent('ERROR', $context, $subcontext, $message, $isSuccess); + return $this; + } +} diff --git a/app/src/Service/Log/LogSystemService.php b/app/src/Service/Log/LogSystemService.php new file mode 100644 index 0000000..b780b12 --- /dev/null +++ b/app/src/Service/Log/LogSystemService.php @@ -0,0 +1,14 @@ +debug('fixtures', $subContext, $message, $success); + return $this; + } +} diff --git a/app/src/Service/Log/LogUserService.php b/app/src/Service/Log/LogUserService.php new file mode 100644 index 0000000..8cd5f02 --- /dev/null +++ b/app/src/Service/Log/LogUserService.php @@ -0,0 +1,61 @@ +requestStack->getCurrentRequest()->get('email'); + $userByEmail = $this->manager->getRepository(User::class)->findOneBy(['email' => $userIdentifier]); + + if ($userByEmail == null) { + $userByUsername = $this->manager->getRepository(User::class)->findOneBy(['username' => $userIdentifier]); + $user = $userByUsername; + } else { + $user = $userByEmail; + } + if ($user) { + $this->log->setUser($user); + } + + if ($success) { + $this->info('user', 'login', $userIdentifier.' login successful '.$message, true); + } else { + $this->info('user', 'login', $userIdentifier.' failed logging in '.$message, false); + } + return $this; + } + + public function logout($user): self + { + $this->log->setUser($user); + $this->info('user', 'logout', $user.' logged out ', true); + return $this; + } + + public function user_created($user): self + { + $this->log->setUser($user); + $this->info('user', 'created', $user.' created', true); + return $this; + } + + public function user_emailverified($user): self + { + $this->log->setUser($user); + $this->info('user', 'email verified', $user->getEmail().' verifed', true); + return $this; + } + + + public function passwordResetMail($success=false): self + { + $this->info('user', 'sent password reset mail', $this->log->getUser().' logged out ', true); + return $this; + } +} diff --git a/app/src/Service/MailSender.php b/app/src/Service/MailSender.php new file mode 100644 index 0000000..9d1762a --- /dev/null +++ b/app/src/Service/MailSender.php @@ -0,0 +1,51 @@ +log = $log; + $params = $params->get('app')['mailer']; + $this->log->setMailLogging($params['logging_general'], $params['logging_full']); + + $this->fromMail = $params['from_email']; + $this->fromName = $params['from_name']; + $this->textMailLinkFomat = $params['text_body']['link_format'] ?? 'table'; + $this->textMailWidth = $params['text_body']['width'] ?? '70'; + } + + public function sendMail(Email $message, ?User $user = null): void + { + //If template is used, render it + if (!empty($message->getHtmlTemplate())) { + $renderedHtmlBody = $this->twig->render($message->getHtmlTemplate(), $message->getContext()); + $message->html($renderedHtmlBody); + $textContent = new Html2Text($renderedHtmlBody, ['do_links' => $this->textMailLinkFomat, 'width' => $this->textMailWidth]); + $message->text(trim($textContent->getText())); + } + + $message->from($this->fromName == null ? new Address($this->fromMail) : new Address($this->fromMail, $this->fromName)); + try { + $message = $this->mailer->send($message); + $this->log->sendMail($message, null, true, $user); + } catch (TransportExceptionInterface $e) { + $this->log->sendMail($message, $e->getMessage(), false, $user); + } + } +} diff --git a/app/src/Service/Utils/ConfigParamsTestHelper.php b/app/src/Service/Utils/ConfigParamsTestHelper.php new file mode 100644 index 0000000..6fe0211 --- /dev/null +++ b/app/src/Service/Utils/ConfigParamsTestHelper.php @@ -0,0 +1,224 @@ +separator = $separator; + $this->pathPrefix = $pathPrefix; + + $this->projectDir = Path::canonicalize(__DIR__.'/../../..'); + $this->configDir = Path::canonicalize($this->projectDir.$configDirectory); + $this->configDirTest = Path::canonicalize($this->projectDir.$configDirectory.'/test'); + $this->paramFileOrginal = Path::canonicalize($this->configDir .'/'.$paramsFile); + $this->paramFileTest = Path::canonicalize($this->configDirTest .'/'.$paramsFile); + + $this->setup(); + } + + /** + * setup + * + * @return bool + */ + public function setup(): ?bool + { + if (!$this->isParamFileOrginalExisting()) { + return false; + } + $this->copyParamFileTest(); + $this->loadTestFile(); + + return null; + } + + /** + * isParamFileOrginalExisting checks wether /config/packages/parameters.yaml exists. + * paramsFile can be changed when creating + * + * @return bool + */ + public function isParamFileOrginalExisting(): bool + { + $fs = new Filesystem(); + if ($fs->exists($this->configDir)) { + if ($fs->exists($this->paramFileOrginal)) { + return true; + } else { + throw new \ErrorException('Config file not found:'. $this->paramFileOrginal.'.'); + } + } else { + throw new \ErrorException('configDirectory not found:'. $this->configDir.'.'); + } + return false; + } + + + /** + * refreshParamFileTest + * copies orignal param file to test file + * @return void + */ + public function copyParamFileTest(): void + { + $fs = new Filesystem(); + $fs->remove($this->paramFileTest); + $fs->copy($this->paramFileOrginal, $this->paramFileTest, true); + $this->loadTestFile(); + } + + + public function loadTestFile(): void + { + $this->yamlTest = Yaml::parseFile($this->paramFileTest); + $this->yamlTestPaths = $this->generateYamlPaths($this->yamlTest); + } + + /** + * generateYamlPaths + * generate path, and sanetize it + * @param mixed $tree + * @return array + */ + protected function generateYamlPaths($tree): ?array + { + $paths = $this->generateYamlPathsTree($tree); + + array_walk($paths, array($this, 'cleanupGeneratedYamlSubstringPaths'), $paths); + $paths = array_filter($paths); + + $pattern = '/'.preg_quote(self::END_OF_PATH_DISTINCT_VALUE, '/').'$/'; + $paths = preg_replace($pattern, '', $paths); + return $paths; + } + + /** + * generateYamlPathsTree + * recoursive loop thru fields to greate paths + * @param mixed $tree nested arrray below + * @param mixed $parent parent above + * @return Array + */ + protected function generateYamlPathsTree($tree, $parent=null): array + { + $paths = array(); + + if ($parent !== null) { + $parent = $parent.$this->separator; + } + foreach ($tree as $k => $v) { + if (is_array($v)) { + $currentPath = $parent.$k; + $paths[] = $currentPath; + $paths = array_merge($paths, $this->generateYamlPathsTree($v, $currentPath)); + } else { + $paths[] = $parent.$k.self::END_OF_PATH_DISTINCT_VALUE; + } + } + return $paths; + } + + /** + * cleanupGeneratedYamlSubstringPaths + * keep only last element of chain. + * e.g will be kept 'house.room.table', but 'house'|'house.room' will be purged + * + * @param mixed $value + * @param mixed $key + * @param mixed $paths + * @return void + */ + protected function cleanupGeneratedYamlSubstringPaths(&$value, $key, $paths) + { + unset($paths[$key]); + if ($this->substring_in_array($value, $paths)) { + $value = null; + } + } + + /** + * substring_in_array + * is substring in found in array values + * + * @param mixed $needle + * @param mixed $haystack + * @return bool + */ + protected function substring_in_array($needle, $haystack): bool + { + $found_keys=[]; + foreach ($haystack as $key => $value) { + if (false !== strpos($value, $needle)) { + $found_keys[] = $key; + } + } + return !empty($found_keys); + } + + /** + * updateValue + * update yml by path and save it. + * + * @param mixed $path + * @param mixed $value + * @return bool + */ + public function updateValue(string $path, $value): bool + { + $pathPrefix = (!empty($this->pathPrefix)) ? $this->pathPrefix.$this->separator : ''; + + + if (!in_array($pathPrefix.$path, $this->yamlTestPaths)) { + $pattern = '/^'.preg_quote($pathPrefix, '.').'/'; + $allowedPathsNoPrefix =preg_replace($pattern, '', $this->yamlTestPaths); + $allowedPaths = join(PHP_EOL, $allowedPathsNoPrefix); + throw new \LogicException('path not found: '. $path.PHP_EOL.'Allowed paths are:'.PHP_EOL.$allowedPaths); + } + + $pathParts = explode($this->separator, $path); + $yaml = &$this->yamlTest; + + foreach ($pathParts as $part) { + $yaml = &$yaml[$part]; + } + $yaml = $value; + return $this->saveTestFile(); + } + + /** + * saveTestFile + * + * @return bool + */ + public function saveTestFile(): bool + { + if (!empty($this->yamlTest)) { + $yaml = Yaml::dump($this->yamlTest, 10, 4); + return file_put_contents($this->paramFileTest, $yaml.PHP_EOL.PHP_EOL) != false; + } + return false; + } +} diff --git a/app/symfony.lock b/app/symfony.lock new file mode 100644 index 0000000..ab456f1 --- /dev/null +++ b/app/symfony.lock @@ -0,0 +1,378 @@ +{ + "api-platform/core": { + "version": "2.6", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.5", + "ref": "05b57782a78c21a664a42055dc11cf1954ca36bb" + }, + "files": [ + "config/packages/api_platform.yaml", + "config/routes/api_platform.yaml", + "src/Entity/.gitignore" + ] + }, + "doctrine/annotations": { + "version": "1.13", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.10", + "ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05" + } + }, + "doctrine/doctrine-bundle": { + "version": "2.7", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.4", + "ref": "ddddd8249dd55bbda16fa7a45bb7499ef6f8e90e" + }, + "files": [ + "config/packages/doctrine.yaml", + "src/Entity/.gitignore", + "src/Repository/.gitignore" + ] + }, + "doctrine/doctrine-fixtures-bundle": { + "version": "3.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.0", + "ref": "1f5514cfa15b947298df4d771e694e578d4c204d" + }, + "files": [ + "src/DataFixtures/AppFixtures.php" + ] + }, + "doctrine/doctrine-migrations-bundle": { + "version": "3.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.1", + "ref": "ee609429c9ee23e22d6fa5728211768f51ed2818" + }, + "files": [ + "config/packages/doctrine_migrations.yaml", + "migrations/.gitignore" + ] + }, + "easycorp/easyadmin-bundle": { + "version": "4.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.0", + "ref": "b131e6cbfe1b898a508987851963fff485986285" + } + }, + "nelmio/cors-bundle": { + "version": "2.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.5", + "ref": "6bea22e6c564fba3a1391615cada1437d0bde39c" + }, + "files": [ + "config/packages/nelmio_cors.yaml" + ] + }, + "phpunit/phpunit": { + "version": "9.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "9.3", + "ref": "a6249a6c4392e9169b87abf93225f7f9f59025e6" + }, + "files": [ + ".env.test", + "phpunit.xml.dist", + "tests/bootstrap.php" + ] + }, + "scheb/2fa-bundle": { + "version": "6.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.0", + "ref": "1e6f68089146853a790b5da9946fc5974f6fcd49" + }, + "files": [ + "config/packages/scheb_2fa.yaml", + "config/routes/scheb_2fa.yaml" + ] + }, + "sensio/framework-extra-bundle": { + "version": "6.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.2", + "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b" + }, + "files": [ + "config/packages/sensio_framework_extra.yaml" + ] + }, + "stof/doctrine-extensions-bundle": { + "version": "1.7", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "1.2", + "ref": "e805aba9eff5372e2d149a9ff56566769e22819d" + } + }, + "symfony/console": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" + }, + "files": [ + "bin/console" + ] + }, + "symfony/debug-bundle": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b" + }, + "files": [ + "config/packages/debug.yaml" + ] + }, + "symfony/flex": { + "version": "2.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" + }, + "files": [ + ".env" + ] + }, + "symfony/framework-bundle": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.4", + "ref": "3cd216a4d007b78d8554d44a5b1c0a446dab24fb" + }, + "files": [ + "config/packages/cache.yaml", + "config/packages/framework.yaml", + "config/preload.php", + "config/routes/framework.yaml", + "config/services.yaml", + "public/index.php", + "src/Controller/.gitignore", + "src/Kernel.php" + ] + }, + "symfony/lock": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.2", + "ref": "a1c8800e40ae735206bb14586fdd6c4630a51b8d" + }, + "files": [ + "config/packages/lock.yaml" + ] + }, + "symfony/mailer": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "4.3", + "ref": "97a61eabb351d7f6cb7702039bcfe07fe9d7e03c" + }, + "files": [ + "config/packages/mailer.yaml" + ] + }, + "symfony/maker-bundle": { + "version": "1.45", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" + } + }, + "symfony/messenger": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.0", + "ref": "2523f7d31488903e247a522e760dc279be7f7aaf" + }, + "files": [ + "config/packages/messenger.yaml" + ] + }, + "symfony/monolog-bundle": { + "version": "3.8", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.7", + "ref": "213676c4ec929f046dfde5ea8e97625b81bc0578" + }, + "files": [ + "config/packages/monolog.yaml" + ] + }, + "symfony/notifier": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.0", + "ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9" + }, + "files": [ + "config/packages/notifier.yaml" + ] + }, + "symfony/phpunit-bridge": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "97cb3dc7b0f39c7cfc4b7553504c9d7b7795de96" + }, + "files": [ + ".env.test", + "bin/phpunit", + "phpunit.xml.dist", + "tests/bootstrap.php" + ] + }, + "symfony/routing": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.1", + "ref": "a44010c0d06989bd4f154aa07d2542d47caf5b83" + }, + "files": [ + "config/packages/routing.yaml", + "config/routes.yaml" + ] + }, + "symfony/security-bundle": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.0", + "ref": "8a5b112826f7d3d5b07027f93786ae11a1c7de48" + }, + "files": [ + "config/packages/security.yaml" + ] + }, + "symfony/translation": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "da64f5a2b6d96f5dc24914517c0350a5f91dee43" + }, + "files": [ + "config/packages/translation.yaml", + "translations/.gitignore" + ] + }, + "symfony/twig-bundle": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.4", + "ref": "bb2178c57eee79e6be0b297aa96fc0c0def81387" + }, + "files": [ + "config/packages/twig.yaml", + "templates/base.html.twig" + ] + }, + "symfony/validator": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "c32cfd98f714894c4f128bb99aa2530c1227603c" + }, + "files": [ + "config/packages/validator.yaml" + ] + }, + "symfony/web-profiler-bundle": { + "version": "6.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.1", + "ref": "e42b3f0177df239add25373083a564e5ead4e13a" + }, + "files": [ + "config/packages/web_profiler.yaml", + "config/routes/web_profiler.yaml" + ] + }, + "symfony/webapp-pack": { + "version": "1.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "2fb3513dbc139884fc5b7c751242b66f9f10f0c3" + }, + "files": [ + "config/packages/messenger.yaml" + ] + }, + "symfonycasts/reset-password-bundle": { + "version": "1.14", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "97c1627c0384534997ae1047b93be517ca16de43" + }, + "files": [ + "config/packages/reset_password.yaml" + ] + }, + "symfonycasts/verify-email-bundle": { + "version": "v1.11.0" + }, + "twig/extra-bundle": { + "version": "v3.4.0" + } +} diff --git a/app/tests/Core/AuthTest.php b/app/tests/Core/AuthTest.php new file mode 100644 index 0000000..f99b872 --- /dev/null +++ b/app/tests/Core/AuthTest.php @@ -0,0 +1,111 @@ +get(UserRepository::class); + $user = $userRepository->findOneByUsername('admin'); + $client->loginUser($user); + return $client; + } + + + public function testOpenAdminAsAnonymous(): void + { + $client = static::createClient(); + $client->request('GET', '/admin'); + $this->assertResponseRedirects('/en/login'); + } + + public function testOpenAdminAsAdminUser(): void + { + + $client = $this->clientLoginAsAdmin(); + $client->request('GET', '/admin'); + $this->assertResponseIsSuccessful(); + $this->assertResponseStatusCodeSame(200); + } + + public function testLoginRedirect(): void + { + $client = static::createClient(); + $client->request('GET', '/login'); + $this->assertResponseRedirects('/en/login'); + } + + public function testUserAccessingAuthPages(): void + { + $pages = ['/en/login','/register','/reset-password']; + $client = $this->clientLoginAsAdmin(); + foreach ($pages as $page) + { + $client->request('GET', $page); + $this->assertResponseRedirects(); + $this->assertTrue($client->getResponse()->isRedirect('/authbridge'), $page); + } + + } + + public function testAnonymousAccessingAuthPages(): void + { + $pages = ['/en/login','/register','/reset-password']; + $client = static::createClient(); + foreach ($pages as $page) + { + $client->request('GET', $page); + $assert = $client->getResponse()->isRedirect('/authbridge') == false ; + $this->assertTrue($assert, $page); + } + } + + public function testLogout(): void + { + $client = $this->clientLoginAsAdmin(); + $client->request('GET', '/logout'); + $this->assertTrue($client->getResponse()->isRedirect()); + } + + /** + * @testdox Error 404 + */ + public function test404Page(): void + { + $client = static::createClient(); + $client->request('GET', '/foobarXCFASDFGKPKéSFD'); + $this->assertResponseStatusCodeSame(404); + } + + + public function testParamRegistrationActive(): void + { + $client = static::createClient(); + $client->request('GET', '/register'); + $this->assertResponseIsSuccessful(); + $this->assertSelectorTextContains('h3', 'Registration'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK, $client->getResponse()->getStatusCode()); + } + + public function testParamPasswortResetActive(): void + { + $client = static::createClient(); + $client->request('GET', '/reset-password'); + $this->assertResponseIsSuccessful(); + $this->assertSelectorTextContains('h3', 'Reset Password'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK, $client->getResponse()->getStatusCode()); + } +} diff --git a/app/tests/bootstrap.php b/app/tests/bootstrap.php new file mode 100644 index 0000000..2e56d9a --- /dev/null +++ b/app/tests/bootstrap.php @@ -0,0 +1,11 @@ +bootEnv(dirname(__DIR__).'/.env.test'); +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..277d494 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,46 @@ +version: "3.8" +services: + + # PHP service + app: + container_name: symfony6app-php + build: ./docker/php/. + working_dir: /var/www/site + volumes: + - ./app:/var/www/site + networks: + - app-network + + # Nginx service + nginx: + container_name: symfony6app-nginx + image: nginx:alpine + working_dir: /var/www/site + ports: + - 8001:80 + volumes: + - ./app:/var/www/site + - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ + networks: + - app-network + + # Mysql service + # change databasename in /docker/mysql/init.sql + mysql: + container_name: symfony6app-mysql + image: mysql:8.0 + command: --default-authentication-plugin=mysql_native_password --init-file="/tmp/mysql/init.sql" + restart: always + environment: + - MYSQL_ROOT_PASSWORD=P@ssw0rd + volumes: + - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf + - ./docker/mysql:/tmp/mysql + ports: + - 8989:3306 + networks: + - app-network + +networks: + app-network: + driver: bridge \ No newline at end of file diff --git a/docker/mysql/init.sql b/docker/mysql/init.sql new file mode 100644 index 0000000..e763d6b --- /dev/null +++ b/docker/mysql/init.sql @@ -0,0 +1,3 @@ +CREATE DATABASE IF NOT EXISTS `default_app` DEFAULT CHARACTER SET = `utf8mb4`; +CREATE DATABASE IF NOT EXISTS `default_test` DEFAULT CHARACTER SET = `utf8mb4`; +USE `default_app`; \ No newline at end of file diff --git a/docker/mysql/my.cnf b/docker/mysql/my.cnf new file mode 100644 index 0000000..c506c08 --- /dev/null +++ b/docker/mysql/my.cnf @@ -0,0 +1,10 @@ +[client] +default-character-set=utf8mb4 + +[mysql] +default-character-set=utf8mb4 + +[mysqld] +collation-server = utf8mb4_general_ci +init-connect='SET NAMES utf8mb4' +character-set-server = utf8mb4 \ No newline at end of file diff --git a/docker/nginx/conf.d/app.conf b/docker/nginx/conf.d/app.conf new file mode 100644 index 0000000..4d1d18a --- /dev/null +++ b/docker/nginx/conf.d/app.conf @@ -0,0 +1,25 @@ +server { + listen 80; + index index.php index.html; + error_log /var/log/nginx/app.error.log; + access_log /var/log/nginx/app.access.log; + + root /var/www/site/public; + + location ~ \.php$ { + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass app:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + } + + location / { + try_files $uri $uri/ /index.php?$query_string; + gzip_static on; + } +} \ No newline at end of file diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile new file mode 100644 index 0000000..23e93f4 --- /dev/null +++ b/docker/php/Dockerfile @@ -0,0 +1,29 @@ +FROM php:8.1.11-fpm + +RUN apt-get update && apt-get install -y git #In this place you can specify all the extensions you need. +RUN docker-php-ext-install pdo_mysql + +RUN apt-get update && apt-get install -y \ + zlib1g-dev libicu-dev g++ \ + libjpeg62-turbo-dev \ + libzip-dev \ + libpng-dev \ + libwebp-dev \ + libfreetype6-dev \ + libxml2-dev \ + git \ + zip \ + unzip \ + && docker-php-ext-install pdo_mysql \ + && docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2/ \ + && docker-php-ext-install -j$(nproc) gd \ + && docker-php-ext-install -j$(nproc) zip \ + && docker-php-ext-configure intl \ + && docker-php-ext-install intl \ + && docker-php-ext-install opcache + + +COPY --from=composer:2.3.10 /usr/bin/composer /usr/bin/composer + + +WORKDIR /var/www \ No newline at end of file diff --git a/docker/php/php.ini b/docker/php/php.ini new file mode 100644 index 0000000..acb6901 --- /dev/null +++ b/docker/php/php.ini @@ -0,0 +1,10 @@ +memory_limit = 2G +display_errors = 1 +error_reporting = -1 +date.timezone = UTC + +; Optimizations for Symfony, as documented on http://symfony.com/doc/current/performance.html +opcache.memory_consumption = 256 +opcache.max_accelerated_files = 20000 +realpath_cache_size = 4096K +realpath_cache_ttl = 600 \ No newline at end of file diff --git a/symfony6-stack.code-workspace b/symfony6-stack.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/symfony6-stack.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/tools/php-cs-fixer/composer.json b/tools/php-cs-fixer/composer.json new file mode 100644 index 0000000..9558a4c --- /dev/null +++ b/tools/php-cs-fixer/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "friendsofphp/php-cs-fixer": "^3.9" + } +} diff --git a/tools/php-cs-fixer/composer.lock b/tools/php-cs-fixer/composer.lock new file mode 100644 index 0000000..a1a2c57 --- /dev/null +++ b/tools/php-cs-fixer/composer.lock @@ -0,0 +1,2033 @@ +{ + "_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": "d6259871d743287ae7052fe34780cc5a", + "packages": [ + { + "name": "composer/pcre", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.0.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T20:21:48+00:00" + }, + { + "name": "composer/semver", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.13.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", + "symfony/cache": "^4.4 || ^5.2", + "vimeo/psalm": "^4.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.13.3" + }, + "time": "2022-07-02T10:48:51+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-02-28T11:07:21+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.9.5", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "4465d70ba776806857a1ac2a6f877e582445ff36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/4465d70ba776806857a1ac2a6f877e582445ff36", + "reference": "4465d70ba776806857a1ac2a6f877e582445ff36", + "shasum": "" + }, + "require": { + "composer/semver": "^3.2", + "composer/xdebug-handler": "^3.0.3", + "doctrine/annotations": "^1.13", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "php-cs-fixer/diff": "^2.0", + "symfony/console": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0", + "symfony/finder": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php80": "^1.25", + "symfony/polyfill-php81": "^1.25", + "symfony/process": "^5.4 || ^6.0", + "symfony/stopwatch": "^5.4 || ^6.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^1.5", + "mikey179/vfsstream": "^1.6.10", + "php-coveralls/php-coveralls": "^2.5.2", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "symfony/phpunit-bridge": "^6.0", + "symfony/yaml": "^5.4 || ^6.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.9.5" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2022-07-22T08:43:51+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": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "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", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "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": "symfony/console", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/43fcb5c5966b43c56bcfa481368d90d748936ab8", + "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "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": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.1.3" + }, + "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-07-22T14:17:57+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/event-dispatcher", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.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-05T16:51:07+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-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/filesystem", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c780e677cddda78417fa5187a7c6cd2f21110db9", + "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.1.3" + }, + "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-07-20T14:45:06+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.1.3" + }, + "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-07-29T07:42:06+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a3016f5442e28386ded73c43a32a5b68586dd1c4", + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v6.1.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-02-25T11:15:52+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "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\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/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" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "433d05519ce6990bf3530fba6957499d327395c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", + "reference": "433d05519ce6990bf3530fba6957499d327395c2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "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\\Intl\\Grapheme\\": "" + } + }, + "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 intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/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" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "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\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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 intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/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" + }, + { + "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" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "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\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/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-10T07:21:04+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "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\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/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" + }, + { + "name": "symfony/process", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.1.3" + }, + "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-06-27T17:24:16+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-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-05-30T19:18:58+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v6.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/77dedae82ce2a26e2e9b481855473fc3b3e4e54d", + "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v6.1.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-02-25T11:15:52+00:00" + }, + { + "name": "symfony/string", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/f35241f45c30bcd9046af2bb200a7086f70e1d6b", + "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.1.3" + }, + "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-07-27T15:50:51+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +}