diff --git a/.env b/.env index 7adf6f3..1207380 100644 --- a/.env +++ b/.env @@ -23,3 +23,13 @@ APP_SECRET= # To test the production environment, run "make go-prod" or "castor symfony:go-prod" # To come back to the development environment, run "make go-dev" or "castor symfony:go-dev" + +###> doctrine/doctrine-bundle ### +# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml +# +# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" +DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" +###< doctrine/doctrine-bundle ### diff --git a/Makefile b/Makefile index 12e33e3..0024614 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,11 @@ warmup: ## Warmup the dev cache for the static analysis purge: ## Purge all Symfony cache and logs @rm -rf ./var/cache/* ./var/log/* ./var/coverage/* +load-fixtures: ## Reset migrations and load the database fixtures + @rm -f ./var/data.db + @bin/console doctrine:migrations:migrate --env=dev --no-interaction + @bin/console foundry:load-fixtures --env=dev --no-interaction + ## —— Tests ✅ ————————————————————————————————————————————————————————————————— test: ## Run tests with optional suite, filter and options (to debug use "make test options=--debug") @@ -69,7 +74,7 @@ test-unit: testsuite=unit test-unit: test coverage: ## Generate the HTML PHPUnit code coverage report (stored in var/coverage) -coverage: purge +coverage: purge load-fixtures @XDEBUG_MODE=coverage php -d xdebug.enable=1 -d memory_limit=-1 vendor/bin/phpunit --coverage-html=var/coverage --coverage-clover=var/coverage/clover.xml @php bin/coverage-checker.php var/coverage/clover.xml $(COVERAGE_THRESHOLD) @@ -107,11 +112,14 @@ lint-container: ## Lint the Symfony DI container lint-twig: ## Lint Twig files @bin/console lint:twig templates/ +lint-doctrine: ## Validate Doctrine schema + @bin/console doctrine:schema:validate + fix: ## Run all fixers fix: fix-php fix-js-css lint: ## Run all linters -lint: stan lint-php lint-js-css lint-container lint-twig +lint: stan lint-php lint-doctrine lint-js-css lint-container lint-twig ci: ## Run CI locally ci: coverage warmup lint diff --git a/castor.php b/castor.php index e320888..b2607b7 100644 --- a/castor.php +++ b/castor.php @@ -96,6 +96,18 @@ function purge(): void success(exit_code('rm -rf ./var/cache/* ./var/log/* ./var/coverage/*')); } +#[AsTask(namespace: 'app', description: 'Load the database fixtures', aliases: ['load-fixtures'])] +function loadFixtures(): void +{ + title('app:load-fixtures'); + io()->note('Resetting db...'); + success(exit_code('rm -f ./var/data.db')); + io()->note('Running db migrations...'); + success(exit_code('bin/console doctrine:migrations:migrate --no-interaction')); + io()->note('Load fixtures...'); + success(exit_code('bin/console foundry:load-fixtures --env=dev --no-interaction')); +} + const PHP_UNIT_CMD = '/vendor/bin/phpunit --testsuite=%s --filter=%s %s'; const PHP_UNIT_SUITES = ['api', 'e2e', 'functional', 'integration', 'unit']; @@ -111,6 +123,7 @@ function getParameters(): array function test_all(): int { title('test:all'); + loadFixtures(); [$filter, $options] = getParameters(); $ec = exit_code(__DIR__.sprintf(PHP_UNIT_CMD, implode(',', PHP_UNIT_SUITES), $filter, $options)); io()->writeln(''); @@ -177,6 +190,7 @@ function test_unit( function coverage(): int { title('test:coverage'); + loadFixtures(); $ec = exit_code('php -d xdebug.enable=1 -d memory_limit=-1 vendor/bin/phpunit --coverage-html=var/coverage --coverage-clover=var/coverage/clover.xml', context: context()->withEnvironment(['XDEBUG_MODE' => 'coverage']) ); @@ -316,21 +330,31 @@ function lint_twig(): int return exit_code('bin/console lint:twig templates/'); } +#[AsTask(name: 'doctrine', namespace: 'lint', description: 'Validate Doctrine schema', aliases: ['lint-doctrine'])] +function lint_doctrine(): int +{ + title('lint:doctrine'); + + return exit_code('@bin/console doctrine:schema:validate'); +} + #[AsTask(name: 'all', namespace: 'lint', description: 'Run all lints', aliases: ['lint'])] function lint_all(): int { title('lint:all'); $ec1 = stan(); $ec2 = lint_php(); - $ec3 = lint_js_css(); - $ec4 = lint_container(); - $ec5 = lint_twig(); + $ec3 = lint_doctrine(); + $ec4 = lint_js_css(); + $ec5 = lint_container(); + $ec6 = lint_twig(); - return success($ec1 + $ec2 + $ec3 + $ec4 + $ec5); + return success($ec1 + $ec2 + $ec3 + $ec4 + $ec5 + $ec6); // if you want to speed up the process, you can run these commands in parallel // parallel( // fn() => lint_php(), + // fn() => lint_doctrine(), // fn() => lint_container(), // fn() => lint_twig(), // ); @@ -341,6 +365,7 @@ function ci(): void { title('ci:all'); purge(); + loadFixtures(); io()->section('Coverage'); coverage(); io()->section('Lints'); diff --git a/composer.json b/composer.json index 26b12f2..23275db 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,10 @@ "ext-mbstring": "*", "ext-simplexml": "*", "ext-xml": "*", + "doctrine/dbal": "^4.0", + "doctrine/doctrine-bundle": "^3.0", + "doctrine/doctrine-migrations-bundle": "^3.3", + "doctrine/orm": "^3.3", "league/commonmark": "^2.4", "symfony/asset": "~8.0.0", "symfony/asset-mapper": "~8.0.0", @@ -61,7 +65,8 @@ "symfony/maker-bundle": "^1.61", "symfony/requirements-checker": "^2.0", "symfony/stopwatch": "~8.0.0", - "symfony/web-profiler-bundle": "~8.0.0" + "symfony/web-profiler-bundle": "~8.0.0", + "zenstruck/foundry": "^2.4" }, "replace": { "symfony/polyfill-ctype": "*", @@ -97,7 +102,10 @@ }, "platform": { }, - "sort-packages": true + "sort-packages": true, + "audit": { + "block-insecure": false + } }, "extra": { "bamarni-bin": { diff --git a/composer.lock b/composer.lock index 5d4ed11..727d0a7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e58225f25849bd3e6d1ea63c16a5a272", + "content-hash": "f83ee8e221043c7a6a6e92b1066b5111", "packages": [ { "name": "composer/semver", @@ -158,6 +158,1112 @@ }, "time": "2024-07-08T12:26:09+00:00" }, + { + "name": "doctrine/collections", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/7713da39d8e237f28411d6a616a3dce5e20d5de2", + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1", + "php": "^8.1", + "symfony/polyfill-php84": "^1.30" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "ext-json": "*", + "phpstan/phpstan": "^2.1.30", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpunit/phpunit": "^10.5.58 || ^11.5.42 || ^12.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "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" + } + ], + "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/2.6.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%2Fcollections", + "type": "tidelift" + } + ], + "time": "2026-01-15T10:01:58+00:00" + }, + { + "name": "doctrine/dbal", + "version": "4.4.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c", + "reference": "3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1.5", + "php": "^8.2", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "14.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.2", + "phpstan/phpstan": "2.1.30", + "phpstan/phpstan-phpunit": "2.0.7", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "11.5.23", + "slevomat/coding-standard": "8.24.0", + "squizlabs/php_codesniffer": "4.0.0", + "symfony/cache": "^6.3.8|^7.0|^8.0", + "symfony/console": "^5.4|^6.3|^7.0|^8.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "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/4.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%2Fdbal", + "type": "tidelift" + } + ], + "time": "2025-12-04T10:11:03+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "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/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, + { + "name": "doctrine/doctrine-bundle", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "af84173db6978c3d2688ea3bcf3a91720b0704ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/af84173db6978c3d2688ea3bcf3a91720b0704ce", + "reference": "af84173db6978c3d2688ea3bcf3a91720b0704ce", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^4.0", + "doctrine/deprecations": "^1.0", + "doctrine/persistence": "^4", + "doctrine/sql-formatter": "^1.0.1", + "php": "^8.4", + "symfony/cache": "^6.4 || ^7.0 || ^8.0", + "symfony/config": "^6.4 || ^7.0 || ^8.0", + "symfony/console": "^6.4 || ^7.0 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0", + "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3 || ^8.0", + "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0", + "symfony/service-contracts": "^3" + }, + "conflict": { + "doctrine/orm": "<3.0 || >=4.0", + "twig/twig": "<3.0.4" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "doctrine/orm": "^3.4.4", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan-strict-rules": "^2", + "phpstan/phpstan-symfony": "^2.0", + "phpunit/phpunit": "^12.3.10", + "psr/log": "^3.0", + "symfony/doctrine-messenger": "^6.4 || ^7.0 || ^8.0", + "symfony/expression-language": "^6.4 || ^7.0 || ^8.0", + "symfony/messenger": "^6.4 || ^7.0 || ^8.0", + "symfony/property-info": "^6.4 || ^7.0 || ^8.0", + "symfony/security-bundle": "^6.4 || ^7.0 || ^8.0", + "symfony/stopwatch": "^6.4 || ^7.0 || ^8.0", + "symfony/string": "^6.4 || ^7.0 || ^8.0", + "symfony/twig-bridge": "^6.4 || ^7.0 || ^8.0", + "symfony/validator": "^6.4 || ^7.0 || ^8.0", + "symfony/web-profiler-bundle": "^6.4 || ^7.0 || ^8.0", + "symfony/yaml": "^6.4 || ^7.0 || ^8.0", + "twig/twig": "^3.21.1" + }, + "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\\": "src" + } + }, + "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/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-bundle", + "type": "tidelift" + } + ], + "time": "2025-12-24T12:24:29+00:00" + }, + { + "name": "doctrine/doctrine-migrations-bundle", + "version": "3.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", + "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1e380c6dd8ac8488217f39cff6b77e367f1a644b", + "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "^2.4 || ^3.0", + "doctrine/migrations": "^3.2", + "php": "^7.2 || ^8.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "require-dev": { + "composer/semver": "^3.0", + "doctrine/coding-standard": "^12 || ^14", + "doctrine/orm": "^2.6 || ^3", + "phpstan/phpstan": "^1.4 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpstan/phpstan-symfony": "^1.3 || ^2", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/phpunit-bridge": "^6.3 || ^7 || ^8", + "symfony/var-exporter": "^5.4 || ^6 || ^7 || ^8" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\MigrationsBundle\\": "src" + } + }, + "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.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-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2025-11-15T19:02:59+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.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/2.0.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%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2024-05-22T20:47:39+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "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" + } + ], + "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.1.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%2Finflector", + "type": "tidelift" + } + ], + "time": "2025-08-10T19:31:58+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", + "shasum": "" + }, + "require": { + "php": "^8.4" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5.58" + }, + "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/2.1.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%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2026-01-05T06:47:08+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "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": "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/3.0.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%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "doctrine/migrations", + "version": "3.9.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "1b823afbc40f932dae8272574faee53f2755eac5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b823afbc40f932dae8272574faee53f2755eac5", + "reference": "1b823afbc40f932dae8272574faee53f2755eac5", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.6 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/var-exporter": "^6.2 || ^7.0 || ^8.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3 || ^4", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "fig/log-test": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpstan/phpstan-symfony": "^2", + "phpunit/phpunit": "^10.3 || ^11.0 || ^12.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.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", + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "src" + } + }, + "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.9.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%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2025-11-20T11:15:36+00:00" + }, + { + "name": "doctrine/orm", + "version": "3.6.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "2148940290e4c44b9101095707e71fb590832fa5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/2148940290e4c44b9101095707e71fb590832fa5", + "reference": "2148940290e4c44b9101095707e71fb590832fa5", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/collections": "^2.2", + "doctrine/dbal": "^3.8.2 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2", + "doctrine/inflector": "^1.4 || ^2.0", + "doctrine/instantiator": "^1.3 || ^2", + "doctrine/lexer": "^3", + "doctrine/persistence": "^3.3.1 || ^4", + "ext-ctype": "*", + "php": "^8.1", + "psr/cache": "^1 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/var-exporter": "^6.3.9 || ^7.0 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^14.0", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "2.1.23", + "phpstan/phpstan-deprecation-rules": "^2", + "phpunit/phpunit": "^10.5.0 || ^11.5", + "psr/log": "^1 || ^2 || ^3", + "symfony/cache": "^5.4 || ^6.2 || ^7.0 || ^8.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" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "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": "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/3.6.1" + }, + "time": "2026-01-09T05:28:15+00:00" + }, + { + "name": "doctrine/persistence", + "version": "4.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", + "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "^1 || ^2", + "php": "^8.1", + "psr/cache": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "phpstan/phpstan": "2.1.30", + "phpstan/phpstan-phpunit": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.58 || ^12", + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.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/4.1.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%2Fpersistence", + "type": "tidelift" + } + ], + "time": "2025-10-16T20:13:18+00:00" + }, + { + "name": "doctrine/sql-formatter", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a8af23a8e9d622505baa2997465782cbe8bb7fc7", + "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "ergebnis/phpunit-slow-test-detector": "^2.20", + "phpstan/phpstan": "^2.1.31", + "phpunit/phpunit": "^10.5.58" + }, + "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.5.3" + }, + "time": "2025-10-26T09:35:14+00:00" + }, { "name": "league/commonmark", "version": "2.8.0", @@ -934,16 +2040,16 @@ }, { "name": "symfony/asset-mapper", - "version": "v8.0.0", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/asset-mapper.git", - "reference": "82a88a78eca5dd127def692d1b853c5bc245705f" + "reference": "87c12734877c97ac7274ad145592a2c7efcfa34f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/82a88a78eca5dd127def692d1b853c5bc245705f", - "reference": "82a88a78eca5dd127def692d1b853c5bc245705f", + "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/87c12734877c97ac7274ad145592a2c7efcfa34f", + "reference": "87c12734877c97ac7274ad145592a2c7efcfa34f", "shasum": "" }, "require": { @@ -991,7 +2097,7 @@ "description": "Maps directories of assets & makes them available in a public directory with versioned filenames.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset-mapper/tree/v8.0.0" + "source": "https://github.com/symfony/asset-mapper/tree/v8.0.3" }, "funding": [ { @@ -1011,7 +2117,7 @@ "type": "tidelift" } ], - "time": "2025-11-21T13:19:49+00:00" + "time": "2025-12-19T10:01:18+00:00" }, { "name": "symfony/cache", @@ -1505,6 +2611,108 @@ ], "time": "2024-09-25T14:21:43+00:00" }, + { + "name": "symfony/doctrine-bridge", + "version": "v8.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "54d583fc3f855e0982f00eceb528fc0fa501f4c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/54d583fc3f855e0982f00eceb528fc0fa501f4c3", + "reference": "54d583fc3f855e0982f00eceb528fc0fa501f4c3", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "^2", + "doctrine/persistence": "^3.1|^4", + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/collections": "<1.8", + "doctrine/dbal": "<4.3", + "doctrine/lexer": "<1.1", + "doctrine/orm": "<3.4", + "symfony/property-info": "<8.0" + }, + "require-dev": { + "doctrine/collections": "^1.8|^2.0", + "doctrine/data-fixtures": "^1.1|^2", + "doctrine/dbal": "^4.3", + "doctrine/orm": "^3.4", + "psr/log": "^1|^2|^3", + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/doctrine-messenger": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/form": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^8.0", + "symfony/security-core": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/type-info": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" + }, + "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/v8.0.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-23T14:52:06+00:00" + }, { "name": "symfony/dotenv", "version": "v8.0.0", @@ -3516,21 +4724,21 @@ }, { "name": "symfony/property-access", - "version": "v8.0.0", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "74df691dfb7f9b161b7d8cd1695bb918c68f16b5" + "reference": "3e9ed5d66144e02f1f430ef3be8e166920ae5271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/74df691dfb7f9b161b7d8cd1695bb918c68f16b5", - "reference": "74df691dfb7f9b161b7d8cd1695bb918c68f16b5", + "url": "https://api.github.com/repos/symfony/property-access/zipball/3e9ed5d66144e02f1f430ef3be8e166920ae5271", + "reference": "3e9ed5d66144e02f1f430ef3be8e166920ae5271", "shasum": "" }, "require": { "php": ">=8.4", - "symfony/property-info": "^7.4|^8.0" + "symfony/property-info": "^7.4.2|^8.0.3" }, "require-dev": { "symfony/cache": "^7.4|^8.0", @@ -3573,7 +4781,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v8.0.0" + "source": "https://github.com/symfony/property-access/tree/v8.0.3" }, "funding": [ { @@ -3593,20 +4801,20 @@ "type": "tidelift" } ], - "time": "2025-08-12T11:06:01+00:00" + "time": "2025-12-18T11:23:51+00:00" }, { "name": "symfony/property-info", - "version": "v8.0.1", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "afbad53529b39e4c48a3584d87d0afef2375ee31" + "reference": "a756f192435191bd50f55967adf999212c4a7232" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/afbad53529b39e4c48a3584d87d0afef2375ee31", - "reference": "afbad53529b39e4c48a3584d87d0afef2375ee31", + "url": "https://api.github.com/repos/symfony/property-info/zipball/a756f192435191bd50f55967adf999212c4a7232", + "reference": "a756f192435191bd50f55967adf999212c4a7232", "shasum": "" }, "require": { @@ -3659,7 +4867,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v8.0.1" + "source": "https://github.com/symfony/property-info/tree/v8.0.3" }, "funding": [ { @@ -3679,7 +4887,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T14:08:45+00:00" + "time": "2025-12-18T11:23:51+00:00" }, { "name": "symfony/routing", @@ -4086,16 +5294,16 @@ }, { "name": "symfony/stimulus-bundle", - "version": "v2.31.0", + "version": "v2.32.0", "source": { "type": "git", "url": "https://github.com/symfony/stimulus-bundle.git", - "reference": "c5ea8ee2ccd45447b7f4b6b82f704ee5e76127f0" + "reference": "dfbf6b443bb381cb611e06f64dc23603b614b575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/c5ea8ee2ccd45447b7f4b6b82f704ee5e76127f0", - "reference": "c5ea8ee2ccd45447b7f4b6b82f704ee5e76127f0", + "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/dfbf6b443bb381cb611e06f64dc23603b614b575", + "reference": "dfbf6b443bb381cb611e06f64dc23603b614b575", "shasum": "" }, "require": { @@ -4114,28 +5322,94 @@ "symfony/twig-bundle": "^5.4|^6.0|^7.0|^8.0", "zenstruck/browser": "^1.4" }, - "type": "symfony-bundle", + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\UX\\StimulusBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Integration with your Symfony app & Stimulus!", + "keywords": [ + "symfony-ux" + ], + "support": { + "source": "https://github.com/symfony/stimulus-bundle/tree/v2.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-02T07:12:06+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\UX\\StimulusBundle\\": "src" - } + "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": "Integration with your Symfony app & Stimulus!", - "keywords": [ - "symfony-ux" - ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stimulus-bundle/tree/v2.31.0" + "source": "https://github.com/symfony/stopwatch/tree/v8.0.0" }, "funding": [ { @@ -4155,7 +5429,7 @@ "type": "tidelift" } ], - "time": "2025-09-24T13:27:42+00:00" + "time": "2025-08-04T07:36:47+00:00" }, { "name": "symfony/string", @@ -4603,16 +5877,16 @@ }, { "name": "symfony/ux-turbo", - "version": "v2.31.0", + "version": "v2.32.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-turbo.git", - "reference": "06d5e4cf4573efe4faf648f3810a28c63684c706" + "reference": "0deaa8abef20933d11f8bbe9899d950b4333ca1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/06d5e4cf4573efe4faf648f3810a28c63684c706", - "reference": "06d5e4cf4573efe4faf648f3810a28c63684c706", + "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/0deaa8abef20933d11f8bbe9899d950b4333ca1e", + "reference": "0deaa8abef20933d11f8bbe9899d950b4333ca1e", "shasum": "" }, "require": { @@ -4624,7 +5898,7 @@ }, "require-dev": { "dbrekelmans/bdi": "dev-main", - "doctrine/doctrine-bundle": "^2.4.3", + "doctrine/doctrine-bundle": "^2.4.3|^3.0|^4.0", "doctrine/orm": "^2.8|^3.0", "php-webdriver/webdriver": "^1.15", "phpstan/phpstan": "^2.1.17", @@ -4633,7 +5907,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0|^8.0", "symfony/form": "^5.4|^6.0|^7.0|^8.0", "symfony/framework-bundle": "^6.4|^7.0|^8.0", - "symfony/mercure-bundle": "^0.3.7", + "symfony/mercure-bundle": "^0.3.7|^0.4.1", "symfony/messenger": "^5.4|^6.0|^7.0|^8.0", "symfony/panther": "^2.2", "symfony/phpunit-bridge": "^5.4|^6.0|^7.0|^8.0", @@ -4682,7 +5956,7 @@ "turbo-stream" ], "support": { - "source": "https://github.com/symfony/ux-turbo/tree/v2.31.0" + "source": "https://github.com/symfony/ux-turbo/tree/v2.32.0" }, "funding": [ { @@ -4702,7 +5976,7 @@ "type": "tidelift" } ], - "time": "2025-10-16T07:24:06+00:00" + "time": "2025-12-17T06:03:34+00:00" }, { "name": "symfony/validator", @@ -5409,33 +6683,45 @@ "time": "2025-11-24T19:20:55+00:00" }, { - "name": "doctrine/inflector", - "version": "2.1.0", + "name": "fakerphp/faker", + "version": "v1.24.1", "source": { "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" }, "require-dev": { - "doctrine/coding-standard": "^12.0 || ^13.0", - "phpstan/phpstan": "^1.12 || ^2.0", - "phpstan/phpstan-phpunit": "^1.4 || ^2.0", - "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", - "phpunit/phpunit": "^8.5 || ^12.2" + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "src" + "Faker\\": "src/Faker/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5444,59 +6730,20 @@ ], "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": "François Zaninotto" } ], - "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", + "description": "Faker is a PHP library that generates fake data for you.", "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", - "php", - "plural", - "singular", - "strings", - "uppercase", - "words" + "data", + "faker", + "fixtures" ], "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.1.0" + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.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%2Finflector", - "type": "tidelift" - } - ], - "time": "2025-08-10T19:31:58+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { "name": "kocal/biome-js-bundle", @@ -6297,16 +7544,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.4", + "version": "12.5.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4ba0e923f9d3fc655de22f9547c01d15a41fc93a" + "reference": "ab8e4374264bc65523d1458d14bf80261577e01f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4ba0e923f9d3fc655de22f9547c01d15a41fc93a", - "reference": "4ba0e923f9d3fc655de22f9547c01d15a41fc93a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ab8e4374264bc65523d1458d14bf80261577e01f", + "reference": "ab8e4374264bc65523d1458d14bf80261577e01f", "shasum": "" }, "require": { @@ -6320,7 +7567,7 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.1", + "phpunit/php-code-coverage": "^12.5.2", "phpunit/php-file-iterator": "^6.0.0", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", @@ -6374,7 +7621,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.4" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.6" }, "funding": [ { @@ -6398,7 +7645,7 @@ "type": "tidelift" } ], - "time": "2025-12-15T06:05:34+00:00" + "time": "2026-01-16T16:28:10+00:00" }, { "name": "roave/security-advisories", @@ -6406,12 +7653,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "412d91dc6342787fd733523797d9c9faf2ad3ea5" + "reference": "57ac71b06405e32e77d960bb8490683138573f04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/412d91dc6342787fd733523797d9c9faf2ad3ea5", - "reference": "412d91dc6342787fd733523797d9c9faf2ad3ea5", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/57ac71b06405e32e77d960bb8490683138573f04", + "reference": "57ac71b06405e32e77d960bb8490683138573f04", "shasum": "" }, "conflict": { @@ -6426,12 +7673,14 @@ "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-laravel": "==2021.10", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "airesvsg/acf-to-rest-api": "<=3.1", "akaunting/akaunting": "<2.1.13", "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", - "alextselegidis/easyappointments": "<1.5.2.0-beta1", + "alextselegidis/easyappointments": "<=1.5.2", "alexusmai/laravel-file-manager": "<=3.3.1", + "algolia/algoliasearch-magento-2": "<=3.16.1|>=3.17.0.0-beta1,<=3.17.1", "alt-design/alt-redirect": "<1.6.4", "altcha-org/altcha": "<1.3.1", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", @@ -6472,7 +7721,7 @@ "backpack/filemanager": "<2.0.2|>=3,<3.0.9", "bacula-web/bacula-web": "<9.7.1", "badaso/core": "<=2.9.11", - "bagisto/bagisto": "<=2.3.7", + "bagisto/bagisto": "<2.3.10", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", "barryvdh/laravel-translation-manager": "<0.6.8", @@ -6505,7 +7754,7 @@ "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", "cadmium-org/cadmium-cms": "<=0.4.9", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", @@ -6544,10 +7793,11 @@ "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", "contao/managed-edition": "<=1.5", + "coreshop/core-shop": "<=4.1.7", "corveda/phpsandbox": "<1.3.5", "cosenary/instagram": "<=2.3", "couleurcitron/tarteaucitron-wp": "<0.3", - "craftcms/cms": "<=4.16.5|>=5,<=5.8.6", + "craftcms/cms": "<=4.16.16|>=5,<=5.8.20", "croogo/croogo": "<=4.0.7", "cuyz/valinor": "<0.12", "czim/file-handling": "<1.5|>=2,<2.3", @@ -6595,7 +7845,7 @@ "drupal/commerce_alphabank_redirect": "<1.0.3", "drupal/commerce_eurobank_redirect": "<2.1.1", "drupal/config_split": "<1.10|>=2,<2.0.2", - "drupal/core": ">=6,<6.38|>=7,<7.102|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", + "drupal/core": ">=6,<6.38|>=7,<7.103|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", "drupal/currency": "<3.5", "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", @@ -6710,7 +7960,7 @@ "geshi/geshi": "<=1.0.9.1", "getformwork/formwork": "<2.2", "getgrav/grav": "<1.11.0.0-beta1", - "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<5.1.4", + "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<=5.2.1", "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", "getkirby/panel": "<2.5.14", "getkirby/starterkit": "<=3.7.0.2", @@ -6939,7 +8189,7 @@ "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", "october/october": "<3.7.5", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<3.7.5", + "october/system": "<=3.7.12|>=4,<=4.0.11", "oliverklee/phpunit": "<3.5.15", "omeka/omeka-s": "<4.0.3", "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", @@ -7003,14 +8253,15 @@ "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.7.6", + "pimcore/admin-ui-classic-bundle": "<=1.7.15|>=2.0.0.0-RC1-dev,<=2.2.2", "pimcore/customer-management-framework-bundle": "<4.2.1", "pimcore/data-hub": "<1.2.4", "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", "pimcore/demo": "<10.3", "pimcore/ecommerce-framework-bundle": "<1.0.10", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.5.4", + "pimcore/pimcore": "<=11.5.13|>=12.0.0.0-RC1-dev,<12.3.1", + "pimcore/web2print-tools-bundle": "<=5.2.1|>=6.0.0.0-RC1-dev,<=6.1", "piwik/piwik": "<1.11", "pixelfed/pixelfed": "<0.12.5", "plotly/plotly.js": "<2.25.2", @@ -7052,7 +8303,7 @@ "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<5.20.1", + "redaxo/source": "<=5.20.1", "remdex/livehelperchat": "<4.29", "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", "reportico-web/reportico": "<=8.1", @@ -7074,10 +8325,10 @@ "setasign/fpdi": "<2.6.4", "sfroemken/url_redirect": "<=1.2.1", "sheng/yiicms": "<1.2.1", - "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.4.1-dev", + "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.6.1-dev", "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", + "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.6.1-dev", "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", "shopxo/shopxo": "<=6.4", "showdoc/showdoc": "<2.10.4", @@ -7122,7 +8373,7 @@ "snipe/snipe-it": "<=8.3.4", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", - "solspace/craft-freeform": ">=5,<5.10.16", + "solspace/craft-freeform": "<4.1.29|>=5,<5.10.16", "soosyze/soosyze": "<=2", "spatie/browsershot": "<5.0.5", "spatie/image-optimizer": "<1.7.3", @@ -7230,10 +8481,10 @@ "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", - "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", @@ -7245,7 +8496,8 @@ "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", "typo3/cms-lowlevel": ">=11,<=11.5.41", "typo3/cms-recordlist": ">=11,<11.5.48", - "typo3/cms-recycler": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-redirects": ">=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", "typo3/cms-scheduler": ">=11,<=11.5.41", "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", @@ -7405,7 +8657,7 @@ "type": "tidelift" } ], - "time": "2025-12-30T23:05:26+00:00" + "time": "2026-01-16T21:05:58+00:00" }, { "name": "sebastian/cli-parser", @@ -8866,72 +10118,6 @@ ], "time": "2024-11-14T22:24:57+00:00" }, - { - "name": "symfony/stopwatch", - "version": "v8.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/service-contracts": "^2.5|^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/v8.0.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-08-04T07:36:47+00:00" - }, { "name": "symfony/web-profiler-bundle", "version": "v8.0.3", @@ -9066,6 +10252,188 @@ } ], "time": "2025-12-08T11:19:18+00:00" + }, + { + "name": "zenstruck/assert", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/zenstruck/assert.git", + "reference": "1e32d48847d4e82c345112ca226b21a1a792af0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zenstruck/assert/zipball/1e32d48847d4e82c345112ca226b21a1a792af0a", + "reference": "1e32d48847d4e82c345112ca226b21a1a792af0a", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-php81": "^1.23", + "symfony/var-exporter": "^5.4|^6.0|^7.0|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9.5.21", + "symfony/phpunit-bridge": "^6.3|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Zenstruck\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Bond", + "email": "kevinbond@gmail.com" + } + ], + "description": "Standalone, lightweight, framework agnostic, test assertion library.", + "homepage": "https://github.com/zenstruck/assert", + "keywords": [ + "assertion", + "phpunit", + "test" + ], + "support": { + "issues": "https://github.com/zenstruck/assert/issues", + "source": "https://github.com/zenstruck/assert/tree/v1.7.0" + }, + "funding": [ + { + "url": "https://github.com/kbond", + "type": "github" + }, + { + "url": "https://github.com/nikophil", + "type": "github" + } + ], + "time": "2025-12-07T01:59:12+00:00" + }, + { + "name": "zenstruck/foundry", + "version": "v2.8.4", + "source": { + "type": "git", + "url": "https://github.com/zenstruck/foundry.git", + "reference": "f76b711ec83a4c7a1ff2bd7d3abc4a6ed8f2e44e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zenstruck/foundry/zipball/f76b711ec83a4c7a1ff2bd7d3abc4a6ed8f2e44e", + "reference": "f76b711ec83a4c7a1ff2bd7d3abc4a6ed8f2e44e", + "shasum": "" + }, + "require": { + "fakerphp/faker": "^1.23", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.2|^3.0", + "symfony/polyfill-php84": "^1.32", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.9|~7.0.9|^7.1.2|^8.0", + "zenstruck/assert": "^1.4" + }, + "conflict": { + "doctrine/cache": "<1.12.1", + "doctrine/persistence": "<2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8", + "dama/doctrine-test-bundle": "^8.0", + "doctrine/collections": "^1.7|^2.0", + "doctrine/common": "^3.2.2", + "doctrine/doctrine-bundle": "^2.10|^3.0", + "doctrine/doctrine-migrations-bundle": "^2.2|^3.0", + "doctrine/mongodb-odm": "^2.4", + "doctrine/mongodb-odm-bundle": "^4.6|^5.0", + "doctrine/orm": "^2.16|^3.0", + "doctrine/persistence": "^2.0|^3.0|^4.0", + "phpunit/phpunit": "^9.5.0 || ^10.0 || ^11.0 || ^12.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dotenv": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/maker-bundle": "^1.55", + "symfony/phpunit-bridge": "^6.4.26|^7.0|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/runtime": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^3.4", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", + "webmozart/assert": "^1.11" + }, + "type": "library", + "extra": { + "psalm": { + "pluginClass": "Zenstruck\\Foundry\\Psalm\\FoundryPlugin" + }, + "bamarni-bin": { + "bin-links": true, + "forward-command": false, + "target-directory": "bin/tools" + } + }, + "autoload": { + "files": [ + "src/functions.php", + "src/Persistence/functions.php", + "src/symfony_console.php" + ], + "psr-4": { + "Zenstruck\\Foundry\\": "src/", + "Zenstruck\\Foundry\\Psalm\\": "utils/psalm", + "Zenstruck\\Foundry\\Utils\\Rector\\": "utils/rector/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Bond", + "email": "kevinbond@gmail.com" + }, + { + "name": "Nicolas PHILIPPE", + "email": "nikophil@gmail.com" + } + ], + "description": "A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.", + "homepage": "https://github.com/zenstruck/foundry", + "keywords": [ + "Fixture", + "dev", + "doctrine", + "factory", + "faker", + "symfony", + "test" + ], + "support": { + "issues": "https://github.com/zenstruck/foundry/issues", + "source": "https://github.com/zenstruck/foundry/tree/v2.8.4" + }, + "funding": [ + { + "url": "https://github.com/kbond", + "type": "github" + }, + { + "url": "https://github.com/nikophil", + "type": "github" + } + ], + "time": "2025-12-23T14:33:33+00:00" } ], "aliases": [], @@ -9086,5 +10454,5 @@ "ext-xml": "*" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/config/bundles.php b/config/bundles.php index 475fcaf..fa94225 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -13,4 +13,7 @@ Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], Kocal\BiomeJsBundle\KocalBiomeJsBundle::class => ['dev' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Zenstruck\Foundry\ZenstruckFoundryBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/config/packages/doctrine.php b/config/packages/doctrine.php new file mode 100644 index 0000000..fbbd722 --- /dev/null +++ b/config/packages/doctrine.php @@ -0,0 +1,28 @@ + [ + 'dbal' => [ + 'url' => '%env(resolve:DATABASE_URL)%', + 'profiling_collect_backtrace' => '%kernel.debug%', + ], + 'orm' => [ + 'validate_xml_mapping' => true, + 'naming_strategy' => 'doctrine.orm.naming_strategy.underscore_number_aware', + 'auto_mapping' => true, + 'mappings' => [ + 'App' => [ + 'type' => 'attribute', + 'is_bundle' => false, + 'dir' => '%kernel.project_dir%/src/Entity', + 'prefix' => 'App\Entity', + 'alias' => 'App', + ], + ], + ], + ], +]); diff --git a/config/packages/doctrine_migrations.php b/config/packages/doctrine_migrations.php new file mode 100644 index 0000000..7895858 --- /dev/null +++ b/config/packages/doctrine_migrations.php @@ -0,0 +1,14 @@ + [ + 'migrations_paths' => [ + 'DoctrineMigrations' => '%kernel.project_dir%/migrations', + ], + 'enable_profiler' => false, + ], +]); diff --git a/config/packages/zenstruck_foundry.php b/config/packages/zenstruck_foundry.php new file mode 100644 index 0000000..91a0f32 --- /dev/null +++ b/config/packages/zenstruck_foundry.php @@ -0,0 +1,24 @@ + [ + 'enable_auto_refresh_with_lazy_objects' => true, + 'persistence' => [ + // Flush only once per call of `PersistentObjectFactory::create()` + 'flush_once' => true, + ], + + // If you use the `make:factory --test` command, you may need to uncomment the following. + // See https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#generate + // services: + // App\Tests\Factory\: + // resource: '%kernel.project_dir%/tests/Factory/' + // autowire: true + // autoconfigure: true + ], +]); diff --git a/migrations/.gitignore b/migrations/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/migrations/Version20260117053612.php b/migrations/Version20260117053612.php new file mode 100644 index 0000000..601f9df --- /dev/null +++ b/migrations/Version20260117053612.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649E7927C74 ON user (email)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D64986CC499D ON user (username)'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP TABLE user'); + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8208cf5..6bc7884 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -46,6 +46,7 @@ diff --git a/public/index.php b/public/index.php index ee85cc1..2641a98 100644 --- a/public/index.php +++ b/public/index.php @@ -7,6 +7,6 @@ require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return static function (array $context) { - /** @var array{APP_ENV: string, APP_DEBUG: string, APP_SECRET: string} $context */ + /** @var array{APP_ENV: string, APP_DEBUG: string} $context */ return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); }; diff --git a/src/Controller/ListUsersAction.php b/src/Controller/ListUsersAction.php new file mode 100644 index 0000000..c334a70 --- /dev/null +++ b/src/Controller/ListUsersAction.php @@ -0,0 +1,25 @@ +render(self::class.'.html.twig', [ + 'users_dbal' => $conn->fetchAllAssociative('SELECT * FROM user'), + 'users_orm' => $userRepository->findAll(), + ]); + } +} diff --git a/src/Entity/.gitignore b/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 0000000..132bc2b --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,169 @@ +email = $email; + $this->password = $password; + $this->username = $username; + } + + public function setId(int $id): self + { + $this->id = $id; + + return $this; + } + + public function getId(): int + { + return $this->id; + } + + public function __toString(): string + { + return $this->getUserIdentifier().' ('.$this->getId().')'; + } + + /** + * @return array{int, string, string, string} + */ + public function __serialize(): array + { + return [$this->id, $this->username, $this->password, $this->email]; + } + + /** + * @param array{int, string, string, string} $data + */ + public function __unserialize(array $data): void + { + [$this->id, $this->username, $this->password, $this->email] = $data; + } + + public function getUserIdentifier(): string + { + if ($this->username === '') { + throw new \LogicException('User username cannot be empty.'); + } + + return $this->username; + } + + /** + * Returns the roles or permissions granted to the user for security. + */ + public function getRoles(): array + { + return [self::ROLE_USER]; + } + + public function getEmail(): string + { + return $this->email; + } + + /** + * Be careful with your users' emails, they should be normalized. + */ + public function setEmail(string $email): self + { + $this->email = $email; + + return $this; + } + + public function getPassword(): string + { + return $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + public function getUsername(): string + { + return $this->username; + } + + public function setUsername(string $username): self + { + $this->username = $username; + + return $this; + } + + public function getCreatedAt(): \DateTimeInterface + { + return $this->createdAt; + } + + public function getUpdatedAt(): \DateTimeInterface + { + return $this->updatedAt; + } + + /** + * Auto set updatedAt and createdAt on persist. + */ + #[ORM\PrePersist] + public function onPrePersist(): void + { + $this->createdAt = new \DateTimeImmutable(); + $this->updatedAt = new \DateTimeImmutable(); + } + + /** + * Auto set updatedAt on update. + */ + #[ORM\PreUpdate] + public function onPreUpdate(): void + { + $this->updatedAt = new \DateTimeImmutable(); + } +} diff --git a/src/Factory/UserFactory.php b/src/Factory/UserFactory.php new file mode 100644 index 0000000..bd65778 --- /dev/null +++ b/src/Factory/UserFactory.php @@ -0,0 +1,33 @@ + + * + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories + */ +final class UserFactory extends PersistentObjectFactory +{ + public static function class(): string + { + return User::class; + } + + /** + * @return array + */ + protected function defaults(): array + { + return [ + 'email' => self::faker()->email(), + 'username' => self::faker()->userName(), + 'password' => self::faker()->password(), + ]; + } +} diff --git a/src/Repository/.gitignore b/src/Repository/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php new file mode 100644 index 0000000..5d5cce2 --- /dev/null +++ b/src/Repository/UserRepository.php @@ -0,0 +1,31 @@ + + * + * @see https://github.com/symfony/demo/blob/main/src/Repository/UserRepository.php + */ +class UserRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, User::class); + } +} diff --git a/src/Story/AppStory.php b/src/Story/AppStory.php new file mode 100644 index 0000000..94aab68 --- /dev/null +++ b/src/Story/AppStory.php @@ -0,0 +1,21 @@ +Doctrine demo + +

The page displays the user table rows coming from the var/data.db SQLite database.

+ +

Doctrine DBAL

+ + + 'users_dbal' => $conn->fetchAllAssociative('SELECT * FROM user'), + + + + + + + + + + + + + + {% for user in users_dbal %} + + + + + + + + {% endfor %} + + + + + + +
IdEmailPseudoCreated atUpdated at
{{ user.id }}{{ user.email }}{{ user.username }}{{ user.created_at|date(constant('DateTime::RSS')) }}{{ user.updated_at|date(constant('DateTime::RSS')) }}
+ There are {{ users_dbal|length }} user(s). +
+ +
+ +

Doctrine ORM

+ + + 'users_orm' => $userRepository->findAll(), + + + + + + + + + + + + + + {% for user in users_orm %} + + + + + + + + {% endfor %} + + + + + + +
IdEmailPseudoCreated atUpdated at
{{ user.id }}{{ user.email }}{{ user.username }}{{ user.createdAt|date(constant('DateTime::RSS')) }}{{ user.updatedAt|date(constant('DateTime::RSS')) }}
+ There are {{ users_orm|length }} user(s). +
+{% endblock %} diff --git a/templates/base.html.twig b/templates/base.html.twig index 572dadc..9fcc05a 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -52,6 +52,7 @@
  • JavaScript with Stimulus
  • The composer.json file
  • 📝 Form example
  • +
  • 👥 Users list
  • ❌ Custom error page
  • ✨ Pico CSS documentation ⤴️
  • diff --git a/tests/Functional/Controller/ListUsersActionTest.php b/tests/Functional/Controller/ListUsersActionTest.php new file mode 100644 index 0000000..f3a78f3 --- /dev/null +++ b/tests/Functional/Controller/ListUsersActionTest.php @@ -0,0 +1,27 @@ +request('GET', '/users'); + self::assertResponseIsSuccessful(); + } +} diff --git a/tests/Integration/Entity/UserTest.php b/tests/Integration/Entity/UserTest.php new file mode 100644 index 0000000..62cd8dd --- /dev/null +++ b/tests/Integration/Entity/UserTest.php @@ -0,0 +1,35 @@ +get(EntityManagerInterface::class); + $user = new User( + email: 'test@example.com', + password: 'hashed_password', + username: 'testuser' + ); + + // persist (@see User::PrePersist()) + $em->persist($user); + $em->flush(); + self::assertSame(1, $user->getId()); + + // update (@see User::onPreUpdate()) + $user->setEmail('new_email'); + $em->flush(); + self::assertSame('new_email', $user->getEmail()); + } +} diff --git a/tests/Unit/Entity/UserTest.php b/tests/Unit/Entity/UserTest.php new file mode 100644 index 0000000..323250e --- /dev/null +++ b/tests/Unit/Entity/UserTest.php @@ -0,0 +1,43 @@ +setId(1)->getId()); + self::assertSame('test@example.com', $user->setEmail('test@example.com')->getEmail()); + self::assertSame('COil', $user->setUsername('COil')->getUsername()); + self::assertSame('COil', $user->getUserIdentifier()); + self::assertSame('123456', $user->setPassword('123456')->getPassword()); + self::assertSame('COil (1)', (string) $user); + self::assertSame($roles, $user->getRoles()); + } + + public function testUserGetUserIdentifier(): void + { + $user = new User('email', 'password', 'username'); + $user->setUsername(''); + $this->expectException(\LogicException::class); + $user->getUserIdentifier(); + } + + public function testUserSerialize(): void + { + $user = new User('email', 'password', 'serialized')->setId(1); + $serializedUser = 'O:15:"App\Entity\User":4:{i:0;i:1;i:1;s:10:"serialized";i:2;s:8:"password";i:3;s:5:"email";}'; + self::assertSame($serializedUser, serialize($user)); + unserialize($serializedUser); + } +} diff --git a/vendor-bin/php-cs-fixer/composer.lock b/vendor-bin/php-cs-fixer/composer.lock index 870c990..560b644 100644 --- a/vendor-bin/php-cs-fixer/composer.lock +++ b/vendor-bin/php-cs-fixer/composer.lock @@ -403,16 +403,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.92.3", + "version": "v3.92.5", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8" + "reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8", - "reference": "2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58", + "reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58", "shasum": "" }, "require": { @@ -444,17 +444,17 @@ }, "require-dev": { "facile-it/paraunit": "^1.3.1 || ^2.7", - "infection/infection": "^0.31.0", - "justinrainbow/json-schema": "^6.5", - "keradus/cli-executor": "^2.2", + "infection/infection": "^0.31", + "justinrainbow/json-schema": "^6.6", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", "php-coveralls/php-coveralls": "^2.9", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", + "phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.46", "symfony/polyfill-php85": "^1.33", - "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0", - "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0" + "symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -495,7 +495,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.3" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.5" }, "funding": [ { @@ -503,7 +503,7 @@ "type": "github" } ], - "time": "2025-12-18T10:45:02+00:00" + "time": "2026-01-08T21:57:37+00:00" }, { "name": "psr/container", @@ -2685,5 +2685,5 @@ "platform-overrides": { "php": "8.2" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" }