diff --git a/composer.json b/composer.json index 24af29a..640f537 100644 --- a/composer.json +++ b/composer.json @@ -10,15 +10,15 @@ } ], "require": { - "php": ">=8.2", + "php": ">=8.4", "ext-ctype": "*", "ext-iconv": "*", "ext-simplexml": "*", "ext-sockets": "*", "beberlei/doctrineextensions": "^1.5", - "doctrine/doctrine-bundle": "^2.10", + "doctrine/doctrine-bundle": "^2.15", "doctrine/doctrine-migrations-bundle": "^3.2", - "doctrine/orm": "^2.15", + "doctrine/orm": "^3.6", "flagception/flagception-bundle": "^6.0", "knplabs/knp-menu-bundle": "^3.2", "knplabs/knp-paginator-bundle": "^6.2", diff --git a/composer.lock b/composer.lock index 7d76a5b..f41894a 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": "2f83a821022fcd019f4192cff19af85e", + "content-hash": "e4ae4ad86c4c01e26d770c2ab3e0fda4", "packages": [ { "name": "beberlei/doctrineextensions", @@ -360,100 +360,6 @@ }, "time": "2024-07-08T12:26:09+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" - } - ], - "abandoned": true, - "time": "2022-05-20T20:07:39+00:00" - }, { "name": "doctrine/collections", "version": "2.6.0", @@ -540,97 +446,6 @@ ], "time": "2026-01-15T10:01:58+00:00" }, - { - "name": "doctrine/common", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5", - "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5", - "shasum": "" - }, - "require": { - "doctrine/persistence": "^2.0 || ^3.0 || ^4.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.5.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%2Fcommon", - "type": "tidelift" - } - ], - "time": "2025-01-01T22:12:03+00:00" - }, { "name": "doctrine/dbal", "version": "3.10.6", @@ -1442,61 +1257,49 @@ }, { "name": "doctrine/orm", - "version": "2.20.13", + "version": "3.6.8", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "f525f32e11efc60a34f5eecd88093f476c90f90e" + "reference": "a4d13ed5b11e7f7b4d654b1adf95432031ae3ffc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/f525f32e11efc60a34f5eecd88093f476c90f90e", - "reference": "f525f32e11efc60a34f5eecd88093f476c90f90e", + "url": "https://api.github.com/repos/doctrine/orm/zipball/a4d13ed5b11e7f7b4d654b1adf95432031ae3ffc", + "reference": "a4d13ed5b11e7f7b4d654b1adf95432031ae3ffc", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/cache": "^1.12.1 || ^2.1.1", - "doctrine/collections": "^1.5 || ^2.1", - "doctrine/common": "^3.0.3", - "doctrine/dbal": "^2.13.1 || ^3.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": "^2 || ^3", - "doctrine/persistence": "^2.4 || ^3", + "doctrine/lexer": "^3", + "doctrine/persistence": "^3.3.1 || ^4", "ext-ctype": "*", - "php": "^7.1 || ^8.0", + "php": "^8.1", "psr/cache": "^1 || ^2 || ^3", - "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0", - "symfony/polyfill-php72": "^1.23", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "doctrine/annotations": "<1.13 || >= 3.0" + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/var-exporter": "^6.3.9 || ^7.0 || ^8.0" }, "require-dev": { - "doctrine/annotations": "^1.13 || ^2", - "doctrine/coding-standard": "^9.0.2 || ^14.0", - "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/extension-installer": "~1.1.0 || ^1.4", - "phpstan/phpstan": "~1.4.10 || 2.1.23", - "phpstan/phpstan-deprecation-rules": "^1 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "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": "^4.4 || ^5.4 || ^6.4 || ^7.0", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0" + "symfony/cache": "^5.4 || ^6.2 || ^7.0 || ^8.0" }, "suggest": { + "ext-deepclone": "Improves performance when not using native lazy objects (Symfony 8.1+)", "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" + "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0" }, - "bin": [ - "bin/doctrine" - ], "type": "library", "autoload": { "psr-4": { @@ -1537,40 +1340,38 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.20.13" + "source": "https://github.com/doctrine/orm/tree/3.6.8" }, - "time": "2026-05-25T05:46:05+00:00" + "time": "2026-08-05T19:05:32+00:00" }, { "name": "doctrine/persistence", - "version": "3.4.5", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "703a29d8597336fb75f42eeabcdf3f2863156ca8" + "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/703a29d8597336fb75f42eeabcdf3f2863156ca8", - "reference": "703a29d8597336fb75f42eeabcdf3f2863156ca8", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b", + "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b", "shasum": "" }, "require": { + "doctrine/deprecations": "^1", "doctrine/event-manager": "^1 || ^2", - "php": "^7.2 || ^8.0", + "php": "^8.1", "psr/cache": "^1.0 || ^2.0 || ^3.0" }, - "conflict": { - "doctrine/common": "<2.10" - }, "require-dev": { - "doctrine/coding-standard": "^12 || ^14", - "doctrine/common": "^3.0", - "phpstan/phpstan": "^1 || 2.1.30", - "phpstan/phpstan-phpunit": "^1 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8.5.38 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0" + "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 || ^8.0", + "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0 || ^8.0" }, "type": "library", "autoload": { @@ -1619,7 +1420,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.4.5" + "source": "https://github.com/doctrine/persistence/tree/4.2.0" }, "funding": [ { @@ -1635,7 +1436,7 @@ "type": "tidelift" } ], - "time": "2026-06-13T19:29:35+00:00" + "time": "2026-04-26T12:12:52+00:00" }, { "name": "doctrine/sql-formatter", @@ -15963,7 +15764,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=8.2", + "php": ">=8.4", "ext-ctype": "*", "ext-iconv": "*", "ext-simplexml": "*", diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index daf9bb6..1fd2e72 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -7,7 +7,7 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '15' orm: - auto_generate_proxy_classes: true + enable_native_lazy_objects: true # Keep implicit controller-argument entity resolution on (many actions type-hint # an entity against a matching {id}/{uuid} route param without #[MapEntity]). # Setting this explicitly silences the "default will flip to false" deprecation; @@ -15,7 +15,6 @@ doctrine: # migrated to #[MapEntity], which is its own task. controller_resolver: auto_mapping: true - enable_lazy_ghost_objects: true report_fields_where_declared: true validate_xml_mapping: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware @@ -42,8 +41,6 @@ when@test: when@prod: doctrine: orm: - auto_generate_proxy_classes: false - proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' query_cache_driver: type: pool pool: doctrine.system_cache_pool diff --git a/deploy.php b/deploy.php index 26005d2..e2c2cec 100644 --- a/deploy.php +++ b/deploy.php @@ -103,6 +103,7 @@ task('deploy', [ 'deploy:lock', 'deploy:release', 'deploy:assets', + 'deploy:check-platform', 'rsync', 'deploy:shared', 'deploy:writable', @@ -113,6 +114,10 @@ task('deploy', [ 'deploy:stop-workers', ]); +task('deploy:check-platform', function () { + runLocally('composer check-platform-reqs'); +}); + task('deploy:stop-workers', function () { run('{{bin/console}} messenger:stop-workers'); }); diff --git a/docs/operations.md b/docs/operations.md index 60c816a..518ae54 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -54,7 +54,12 @@ Why each part is the way it is: explicitly for both hosts, because the host's default CLI is not the right one. Cron's `PATH` is typically only `/usr/bin:/bin`. `vendor/` is rsynced from a developer machine and there is no `deploy:vendors`, so the CLI must match the PHP the dependencies were - installed against (8.3). + installed against (8.4). Deployments run `composer check-platform-reqs` locally before + rsync; because `config.platform.php` is pinned in `composer.json`, this only verifies + that the locked dependencies resolve against the PHP and extension set we target — it + does not probe the staging or production runtime. Keeping both FPM and + `/usr/local/bin/php` on staging and production at PHP 8.4 is a manual precondition of + every deploy. - **`--time-limit=300`** on the mailing worker. An 800-recipient mailing needs roughly 200–360 seconds of worker time — the fan-out renders 800 Twig bodies and inserts 800 rows, then the mails go out at about 3–5 per second over a reused SMTP connection. So a diff --git a/tests/BusProNet/UserDataHandlerTest.php b/tests/BusProNet/UserDataHandlerTest.php index fd37339..455cf4f 100644 --- a/tests/BusProNet/UserDataHandlerTest.php +++ b/tests/BusProNet/UserDataHandlerTest.php @@ -14,7 +14,7 @@ use App\Entity\Embeddable\Communication; use App\Entity\Teamer; use App\Entity\User; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ObjectRepository; +use Doctrine\ORM\EntityRepository; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -511,7 +511,7 @@ class UserDataHandlerTest extends TestCase $profileResponse = $this->createProfileResponse(); - $repository = $this->createMock(ObjectRepository::class); + $repository = $this->createMock(EntityRepository::class); $repository ->expects($this->once()) ->method('findOneBy') @@ -562,7 +562,7 @@ class UserDataHandlerTest extends TestCase $profileResponse = $this->createProfileResponse(); - $repository = $this->createMock(ObjectRepository::class); + $repository = $this->createMock(EntityRepository::class); $repository ->expects($this->once()) ->method('findOneBy') @@ -607,7 +607,7 @@ class UserDataHandlerTest extends TestCase $profileResponse = $this->createProfileResponse(null, null); - $repository = $this->createMock(ObjectRepository::class); + $repository = $this->createMock(EntityRepository::class); $repository ->expects($this->once()) ->method('findOneBy') @@ -669,7 +669,7 @@ class UserDataHandlerTest extends TestCase $profileResponse = $this->createProfileResponse(); - $repository = $this->createMock(ObjectRepository::class); + $repository = $this->createMock(EntityRepository::class); $repository ->expects($this->once()) ->method('findOneBy') diff --git a/tests/Security/MyEpAuthenticatorTest.php b/tests/Security/MyEpAuthenticatorTest.php index f6d673c..c189995 100644 --- a/tests/Security/MyEpAuthenticatorTest.php +++ b/tests/Security/MyEpAuthenticatorTest.php @@ -10,7 +10,7 @@ use App\RequiredTeamerCheck\RequiredTeamerCheckRegistry; use App\Security\MyEpAuthenticator; use App\Security\OAuth2\MyEpClient; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ObjectRepository; +use Doctrine\ORM\EntityRepository; use Flagception\Manager\FeatureManagerInterface; use GuzzleHttp\Psr7\Request as Psr7Request; use GuzzleHttp\Psr7\Response as Psr7Response; @@ -30,7 +30,7 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; class MyEpAuthenticatorTest extends TestCase { private EntityManagerInterface&MockObject $entityManager; - private ObjectRepository&MockObject $repository; + private EntityRepository&MockObject $repository; /** @var User[] */ private array $persisted = []; @@ -38,7 +38,7 @@ class MyEpAuthenticatorTest extends TestCase protected function setUp(): void { $this->persisted = []; - $this->repository = $this->createMock(ObjectRepository::class); + $this->repository = $this->createMock(EntityRepository::class); $this->entityManager = $this->createMock(EntityManagerInterface::class); $this->entityManager->method('getRepository')->willReturn($this->repository); $this->entityManager