From 9fdadd7b5aa40c03f0f287e787db103272186796 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 11:09:25 +0200 Subject: [PATCH 1/6] Update components to remove annotation support --- composer.json | 10 +++++----- .../HostnetEntityTrackerExtension.php | 6 +++--- src/Resources/config/blamable.yaml | 4 ++-- src/Resources/config/mutation.yaml | 2 +- src/Resources/config/revision.yaml | 2 +- src/Resources/config/services.yaml | 10 +++------- .../HostnetEntityTrackerExtensionTest.php | 4 ++-- 7 files changed, 17 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index d0b40e7..316d4c1 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "minimum-stability": "stable", "require": { "php": "^8.3", - "hostnet/entity-tracker-component": "^2.3.0", + "hostnet/entity-tracker-component": "^3.0.0", "psr/log": "^1.1.0||^2.0.0||^3.0.0", "symfony/config": "^5.4||^6.0", "symfony/dependency-injection": "^5.4||^6.0", @@ -13,7 +13,7 @@ "symfony/yaml": "^5.4||^6.0" }, "require-dev": { - "hostnet/entity-blamable-component": "^1.1.0", + "hostnet/entity-blamable-component": "^2.0.0", "hostnet/phpcs-tool": "^9.1.0", "phpspec/prophecy": "^1.19", "phpspec/prophecy-phpunit": "^2.2", @@ -27,9 +27,9 @@ "hostnet/entity-revision-component": "Provides the @Revision annotation/attribute and listeners" }, "conflict": { - "hostnet/entity-blamable-component": "<1.1.0", - "hostnet/entity-mutation-component": "<1.1.0", - "hostnet/entity-revision-component": "<1.2.0" + "hostnet/entity-blamable-component": "<2.0.0", + "hostnet/entity-mutation-component": "<2.0.0", + "hostnet/entity-revision-component": "<2.0.0" }, "autoload": { "psr-4": { diff --git a/src/DependencyInjection/HostnetEntityTrackerExtension.php b/src/DependencyInjection/HostnetEntityTrackerExtension.php index e42b3df..672f724 100644 --- a/src/DependencyInjection/HostnetEntityTrackerExtension.php +++ b/src/DependencyInjection/HostnetEntityTrackerExtension.php @@ -14,9 +14,9 @@ class HostnetEntityTrackerExtension extends Extension { - private const string BLAMABLE = 'Hostnet\Component\EntityBlamable\Blamable'; - private const string MUTATION = 'Hostnet\Component\EntityMutation\Mutation'; - private const string REVISION = 'Hostnet\Component\EntityRevision\Revision'; + private const string BLAMABLE = 'Hostnet\Component\EntityBlamable\Attributes\Blamable'; + private const string MUTATION = 'Hostnet\Component\EntityMutation\Attributes\Mutation'; + private const string REVISION = 'Hostnet\Component\EntityRevision\Attributes\Revision'; public function load(array $configs, ContainerBuilder $container): void { diff --git a/src/Resources/config/blamable.yaml b/src/Resources/config/blamable.yaml index aa7a494..99296f5 100644 --- a/src/Resources/config/blamable.yaml +++ b/src/Resources/config/blamable.yaml @@ -2,7 +2,7 @@ services: entity_tracker.resolver.blamable: class: Hostnet\Component\EntityBlamable\Resolver\BlamableResolver arguments: - - "@entity_tracker.provider.annotation_metadata" + - "@entity_tracker.provider.entity_metadata" entity_tracker.listener.blamable: class: Hostnet\Component\EntityBlamable\Listener\BlamableListener @@ -11,6 +11,6 @@ services: - "" # provider id, (configurable) - "" # cacheadapter id (configurable, entity_tracker.cache by default) tags: - - { name: doctrine.event_listener, event: entityChanged, priority: 32, method: onEntityChanged } + - { name: doctrine.event_listener, event: entityChanged, priority: 32 } diff --git a/src/Resources/config/mutation.yaml b/src/Resources/config/mutation.yaml index cbe462f..0d19226 100644 --- a/src/Resources/config/mutation.yaml +++ b/src/Resources/config/mutation.yaml @@ -2,7 +2,7 @@ services: entity_tracker.resolver.mutation: class: Hostnet\Component\EntityMutation\Resolver\MutationResolver arguments: - - "@entity_tracker.provider.annotation_metadata" + - "@entity_tracker.provider.entity_metadata" entity_tracker.listener.mutation: class: Hostnet\Component\EntityMutation\Listener\MutationListener diff --git a/src/Resources/config/revision.yaml b/src/Resources/config/revision.yaml index ec3dfa9..7a63e0f 100644 --- a/src/Resources/config/revision.yaml +++ b/src/Resources/config/revision.yaml @@ -2,7 +2,7 @@ services: entity_tracker.resolver.revision: class: Hostnet\Component\EntityRevision\Resolver\RevisionResolver arguments: - - "@entity_tracker.provider.annotation_metadata" + - "@entity_tracker.provider.entity_metadata" entity_tracker.listener.revision: class: Hostnet\Component\EntityRevision\Listener\RevisionListener diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index 2ca9432..c28f62f 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -2,24 +2,20 @@ services: entity_tracker.cache: class: Symfony\Component\Cache\Adapter\ArrayAdapter - entity_tracker.provider.annotation_metadata: - class: Hostnet\Component\EntityTracker\Provider\EntityAnnotationMetadataProvider - arguments: - - "@annotation_reader" + entity_tracker.provider.entity_metadata: + class: Hostnet\Component\EntityTracker\Provider\EntityMetadataProvider entity_tracker.provider.mutation_metadata: class: Hostnet\Component\EntityTracker\Provider\EntityMutationMetadataProvider arguments: - - "@annotation_reader" - "@?logger" entity_tracker.listener.entity_changed: class: Hostnet\Component\EntityTracker\Listener\EntityChangedListener arguments: - - "@entity_tracker.provider.annotation_metadata" + - "@entity_tracker.provider.entity_metadata" - "@entity_tracker.provider.mutation_metadata" - "@?logger" - "" # cacheadapter id (configurable, entity_tracker.cache by default) tags: - { name: doctrine.event_listener, event: preFlush, priority: 15 } - - { name: doctrine.event_listener, event: prePersist, priority: 15 } diff --git a/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php b/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php index f1d9113..fc88e5e 100644 --- a/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php +++ b/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php @@ -6,7 +6,7 @@ namespace Hostnet\Bundle\EntityTrackerBundle\DependencyInjection; -use Hostnet\Component\EntityBlamable\Blamable; +use Hostnet\Component\EntityBlamable\Attributes\Blamable; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -60,7 +60,7 @@ public function testLoadMutation(): void $this->extension->expects(self::once()) ->method('validateComponent') - ->with('Hostnet\Component\EntityMutation\Mutation', 'mutation'); + ->with('Hostnet\Component\EntityMutation\Attributes\Mutation', 'mutation'); $this->extension->load($configs, $this->container); } From 16398ee333606c4b039788e7f4ff83fcde1a8657 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 11:36:08 +0200 Subject: [PATCH 2/6] Modernize code to PHP 8.3 conventions - Add #[\Override] on interface/parent-overriding methods. - Use constructor property promotion in DefaultBlamableProvider and type the previously-untyped properties in the test suite. - Replace PHPUnit's deprecated setMethods() mock builder call with onlyMethods(). - Remove PHPDoc that only restated a typed signature. Co-Authored-By: Claude Sonnet 5 --- src/DependencyInjection/Configuration.php | 1 + .../HostnetEntityTrackerExtension.php | 7 +------ .../Blamable/DefaultBlamableProvider.php | 20 ++++++------------- .../HostnetEntityTrackerExtensionTest.php | 14 ++++++------- tests/Functional/Fixtures/TestKernel.php | 7 ++++--- tests/Functional/FunctionalTest.php | 2 ++ .../Blamable/DefaultBlamableProviderTest.php | 3 ++- 7 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index da1424d..16fa292 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -22,6 +22,7 @@ class Configuration implements ConfigurationInterface private const string CONFIG_ROOT = 'hostnet_entity_tracker'; + #[\Override] public function getConfigTreeBuilder(): TreeBuilder { $tree_builder = new TreeBuilder(self::CONFIG_ROOT); diff --git a/src/DependencyInjection/HostnetEntityTrackerExtension.php b/src/DependencyInjection/HostnetEntityTrackerExtension.php index 672f724..2a8dd55 100644 --- a/src/DependencyInjection/HostnetEntityTrackerExtension.php +++ b/src/DependencyInjection/HostnetEntityTrackerExtension.php @@ -18,6 +18,7 @@ class HostnetEntityTrackerExtension extends Extension private const string MUTATION = 'Hostnet\Component\EntityMutation\Attributes\Mutation'; private const string REVISION = 'Hostnet\Component\EntityRevision\Attributes\Revision'; + #[\Override] public function load(array $configs, ContainerBuilder $container): void { $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); @@ -78,9 +79,6 @@ public function load(array $configs, ContainerBuilder $container): void } /** - * @param string $annotation_class - * @param string $config_name - * * @throws \RuntimeException */ protected function validateComponent(string $annotation_class, string $config_name): void @@ -97,9 +95,6 @@ protected function validateComponent(string $annotation_class, string $config_na } /** - * @param string $annotation_class - * @param string $config_name - * * @throws \RuntimeException */ protected function validateClass(string $annotation_class, string $config_name): void diff --git a/src/Services/Blamable/DefaultBlamableProvider.php b/src/Services/Blamable/DefaultBlamableProvider.php index 36a162d..8c3e3b0 100644 --- a/src/Services/Blamable/DefaultBlamableProvider.php +++ b/src/Services/Blamable/DefaultBlamableProvider.php @@ -15,22 +15,13 @@ */ class DefaultBlamableProvider implements BlamableProviderInterface { - /** - * @var TokenStorageInterface - */ - private $token_storage; - - /** - * @var string - */ - private $username; - - public function __construct(TokenStorageInterface $token_storage, string $username) - { - $this->token_storage = $token_storage; - $this->username = $username; + public function __construct( + private TokenStorageInterface $token_storage, + private string $username + ) { } + #[\Override] public function getUpdatedBy(): string { if (($token = $this->token_storage->getToken()) instanceof TokenInterface) { @@ -40,6 +31,7 @@ public function getUpdatedBy(): string return $this->username; } + #[\Override] public function getChangedAt(): \DateTime { return new \DateTime(); diff --git a/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php b/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php index fc88e5e..19ee10d 100644 --- a/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php +++ b/tests/DependencyInjection/HostnetEntityTrackerExtensionTest.php @@ -7,6 +7,7 @@ namespace Hostnet\Bundle\EntityTrackerBundle\DependencyInjection; use Hostnet\Component\EntityBlamable\Attributes\Blamable; +use Hostnet\Component\EntityMutation\Attributes\Mutation; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -15,19 +16,16 @@ */ class HostnetEntityTrackerExtensionTest extends TestCase { - private $container; - - /** - * @var HostnetEntityTrackerExtension - */ - private $extension; + private ContainerBuilder $container; + private HostnetEntityTrackerExtension $extension; + #[\Override] public function setUp(): void { $this->container = new ContainerBuilder(); $this->extension = $this->getMockBuilder(HostnetEntityTrackerExtension::class) - ->setMethods(['validateComponent', 'validateClass']) + ->onlyMethods(['validateComponent', 'validateClass']) ->getMock(); } @@ -60,7 +58,7 @@ public function testLoadMutation(): void $this->extension->expects(self::once()) ->method('validateComponent') - ->with('Hostnet\Component\EntityMutation\Attributes\Mutation', 'mutation'); + ->with(Mutation::class, 'mutation'); $this->extension->load($configs, $this->container); } diff --git a/tests/Functional/Fixtures/TestKernel.php b/tests/Functional/Fixtures/TestKernel.php index e1fc0a1..8db63c2 100644 --- a/tests/Functional/Fixtures/TestKernel.php +++ b/tests/Functional/Fixtures/TestKernel.php @@ -11,9 +11,7 @@ class TestKernel extends Kernel { - /** - * {@inheritdoc} - */ + #[\Override] public function registerBundles(): array { return [ @@ -22,16 +20,19 @@ public function registerBundles(): array ]; } + #[\Override] public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load(__DIR__ . '/config/config.yaml'); } + #[\Override] public function getCacheDir(): string { return __DIR__ . '/../../../var/cache/' . $this->getEnvironment(); } + #[\Override] public function getLogDir(): string { return __DIR__ . '/../../../var/logs'; diff --git a/tests/Functional/FunctionalTest.php b/tests/Functional/FunctionalTest.php index fae4d53..4c95945 100644 --- a/tests/Functional/FunctionalTest.php +++ b/tests/Functional/FunctionalTest.php @@ -14,11 +14,13 @@ */ class FunctionalTest extends KernelTestCase { + #[\Override] protected function setUp(): void { static::bootKernel(); } + #[\Override] protected static function getKernelClass(): string { return TestKernel::class; diff --git a/tests/Services/Blamable/DefaultBlamableProviderTest.php b/tests/Services/Blamable/DefaultBlamableProviderTest.php index f0e4580..9cf39ae 100644 --- a/tests/Services/Blamable/DefaultBlamableProviderTest.php +++ b/tests/Services/Blamable/DefaultBlamableProviderTest.php @@ -19,8 +19,9 @@ class DefaultBlamableProviderTest extends TestCase { use ProphecyTrait; - private $token_storage; + private TokenStorageInterface $token_storage; + #[\Override] protected function setUp(): void { $this->token_storage = $this->createMock(TokenStorageInterface::class); From 23e795c4116b9ad6de1223da1eab8e0bd321e876 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 11:38:24 +0200 Subject: [PATCH 3/6] Update CI workflow to match sibling hostnet components - Bump actions/checkout v2 -> v7 (v2 runs on the deprecated Node 16 runtime). - Bump actions/cache v4 -> v6. - Add PHP 8.4 to the test matrix alongside 8.3, matching entity-blamable/mutation/revision-component's own workflows. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/main.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index e59bb7e..23d8935 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -8,10 +8,10 @@ jobs: strategy: matrix: - php-versions: ['8.3'] + php-versions: ['8.3', '8.4'] name: PHP ${{ matrix.php-versions }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} @@ -19,7 +19,7 @@ jobs: id: composer-cache run: | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - uses: actions/cache@v4 + - uses: actions/cache@v6 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} From 5c4f1b5d332a29dfa65e65f3034e6308189f4ca6 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 11:48:22 +0200 Subject: [PATCH 4/6] Drop symfony <6.4 support --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 316d4c1..b64829e 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,10 @@ "php": "^8.3", "hostnet/entity-tracker-component": "^3.0.0", "psr/log": "^1.1.0||^2.0.0||^3.0.0", - "symfony/config": "^5.4||^6.0", - "symfony/dependency-injection": "^5.4||^6.0", - "symfony/http-kernel": "^5.4||^6.0", - "symfony/yaml": "^5.4||^6.0" + "symfony/config": "^6.4", + "symfony/dependency-injection": "^6.4", + "symfony/http-kernel": "^6.4", + "symfony/yaml": "^6.4" }, "require-dev": { "hostnet/entity-blamable-component": "^2.0.0", @@ -18,8 +18,8 @@ "phpspec/prophecy": "^1.19", "phpspec/prophecy-phpunit": "^2.2", "phpunit/phpunit": "^9.5.6", - "symfony/framework-bundle": "^5.4||^6.0", - "symfony/security-bundle": "^5.4||^6.0" + "symfony/framework-bundle": "^6.4", + "symfony/security-bundle": "^6.4" }, "suggest": { "hostnet/entity-blamable-component": "Provides the @Blamable annotation/attribute and listeners", From 30861f7515ce86de1b5d66ced40c836c0c51ee79 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 15:46:10 +0200 Subject: [PATCH 5/6] Update requirements and conflicts --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b64829e..83186f3 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "symfony/yaml": "^6.4" }, "require-dev": { - "hostnet/entity-blamable-component": "^2.0.0", + "hostnet/entity-blamable-component": "^2.0.1", "hostnet/phpcs-tool": "^9.1.0", "phpspec/prophecy": "^1.19", "phpspec/prophecy-phpunit": "^2.2", @@ -22,12 +22,12 @@ "symfony/security-bundle": "^6.4" }, "suggest": { - "hostnet/entity-blamable-component": "Provides the @Blamable annotation/attribute and listeners", - "hostnet/entity-mutation-component": "Provides the @Mutation annotation/attribute and listeners", - "hostnet/entity-revision-component": "Provides the @Revision annotation/attribute and listeners" + "hostnet/entity-blamable-component": "Provides the #[Blamable] attribute and listeners", + "hostnet/entity-mutation-component": "Provides the #[Mutation] attribute and listeners", + "hostnet/entity-revision-component": "Provides the #[Revision] attribute and listeners" }, "conflict": { - "hostnet/entity-blamable-component": "<2.0.0", + "hostnet/entity-blamable-component": "<2.0.1", "hostnet/entity-mutation-component": "<2.0.0", "hostnet/entity-revision-component": "<2.0.0" }, From 28929d85bbfbb019b8cb67a7325d2339f7748331 Mon Sep 17 00:00:00 2001 From: Jan Lam Date: Mon, 14 Sep 2026 15:58:15 +0200 Subject: [PATCH 6/6] Conflict against symfony/console >=8.0 to fix PHP 8.4 CI fatal symfony/console is only ever a transitive dependency here (pulled in loosely by doctrine/orm and by conflict guards in framework-bundle/ http-kernel/security-bundle/symfony/yaml), and nothing capped its upper bound. On PHP 8.4, Composer's solver was free to pick symfony/console 8.0.x (itself requiring php >=8.4), whose abstract Command::configure() now declares a ": void" return type that symfony/yaml 6.4's LintCommand::configure() (still untyped) doesn't satisfy - a fatal "Declaration ... must be compatible with ..." the moment framework-bundle's console/command wiring loads that class. On PHP 8.3 the same console 8.0.x is filtered out by its own php requirement during resolution, so the break was invisible until the 8.4 matrix leg was added. A conflict entry (rather than a fake require-dev on a package this bundle never actually uses) keeps composer.json honest about what's really a dependency here. Co-Authored-By: Claude Sonnet 5 --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 83186f3..cc9ff87 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "conflict": { "hostnet/entity-blamable-component": "<2.0.1", "hostnet/entity-mutation-component": "<2.0.0", - "hostnet/entity-revision-component": "<2.0.0" + "hostnet/entity-revision-component": "<2.0.0", + "symfony/console": ">=8.0" }, "autoload": { "psr-4": {