diff --git a/.gitattributes b/.gitattributes index d41c778..d9f4a3b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,4 @@ .gitignore export-ignore /test export-ignore /phpunit.xml.dist export-ignore +/phpcs.xml.dist export-ignore diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index b7896e1..19d3d82 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -15,7 +15,7 @@ jobs: php-versions: ['8.3', '8.4'] name: PHP ${{ matrix.php-versions }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} diff --git a/README.md b/README.md index c2b71c9..6b74eb7 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ This component lets you automatically update entities by implementing `setUpdate Requirements ------------ -The blamable component requires a minimum of php 5.4 and runs on Doctrine2. For specific requirements, please check [composer.json](../master/composer.json). +The blamable component requires a minimum of php 8.3 and runs on Doctrine2. For specific requirements, please check [composer.json](../master/composer.json). Installation ------------ @@ -32,7 +32,7 @@ Installing is pretty easy, this package is available on [packagist](https://pack ```javascript "require" : { - "hostnet/entity-blamable-component" : "1.*" + "hostnet/entity-blamable-component" : "2.*" } ``` @@ -45,14 +45,14 @@ Documentation How does it work? ----------------- -It works by putting the `@Blamable` annotation and BlamableInterface on your Entity and registering the listener on the entityChanged event, assuming you have already configured the [Entity Tracker Component](https://github.com/hostnet/entity-tracker-component/#setup). +It works by putting the `#[Blamable]` attribute and BlamableInterface on your Entity and registering the listener on the entityChanged event, assuming you have already configured the [Entity Tracker Component](https://github.com/hostnet/entity-tracker-component/#setup). For a usage example, follow the setup below. Setup ----- - - You have to add `@Blamable` to your entity + - You have to add `#[Blamable]` to your entity - You have to add the BlamableInterface to your entity - You have to implement the BlamableProviderInterface on an object and pass it to the listener @@ -72,27 +72,24 @@ use Acme\Bundle\AcmeBundle\Service\AcmeBlamableProvider; use Hostnet\Component\EntityBlamable\Listener\BlamableListener; use Hostnet\Component\EntityBlamable\Resolver\BlamableResolver; use Hostnet\Component\EntityTracker\Listener\EntityChangedListener; -use Hostnet\Component\EntityTracker\Provider\EntityAnnotationMetadataProvider; +use Hostnet\Component\EntityTracker\Provider\EntityMetadataProvider; use Hostnet\Component\EntityTracker\Provider\EntityMutationMetadataProvider; /* @var $em \Doctrine\ORM\EntityManager */ $event_manager = $em->getEventManager(); -// default doctrine annotation reader -$annotation_reader = new AnnotationReader(); - // setup required providers -$mutation_metadata_provider = new EntityMutationMetadataProvider($annotation_reader); -$annotation_metadata_provider = new EntityAnnotationMetadataProvider($annotation_reader); +$mutation_metadata_provider = new EntityMutationMetadataProvider(); +$metadata_provider = new EntityMetadataProvider(); -// pre flush event listener that uses the @Tracked/@Blamable annotation +// pre flush event listener that uses the #[Tracked]/#[Blamable] attribute $entity_changed_listener = new EntityChangedListener( - $mutation_metadata_provider, - $annotation_metadata_provider + $metadata_provider, + $mutation_metadata_provider ); -// the resolver is used to find the correct annotation -$blamable_resolver = new BlamableResolver($annotation_metadata_provider); +// the resolver is used to find the correct attribute +$blamable_resolver = new BlamableResolver($metadata_provider); // the object that will provide the username and date time. This is an // application specific implementation of the BlamableProviderInterface @@ -120,21 +117,18 @@ use Hostnet\Component\EntityBlamable\Provider\BlamableProviderInterface; class AcmeBlamableProvider implements BlamableProviderInterface { - private $username; - - public function __construct($username) + public function __construct(private string $username) { - $this->username = $username; } - public function getUpdatedBy() + public function getUpdatedBy(): string { return $this->username; } - - public function getChangedAt() + + public function getChangedAt(): \DateTimeInterface { - return new \DateTime(); + return new \DateTimeImmutable(); } } @@ -142,48 +136,46 @@ class AcmeBlamableProvider implements BlamableProviderInterface ``` #### Configuring the Entity -All we have to do now is put the `@Blamable` annotation and BlamableInterface on our Entity. +All we have to do now is put the `#[Blamable]` attribute and BlamableInterface on our Entity. ```php use Doctrine\ORM\Mapping as ORM; -use Hostnet\Component\EntityBlamable\Blamable; +use Hostnet\Component\EntityBlamable\Attributes\Blamable; use Hostnet\Component\EntityBlamable\BlamableInterface; -/** - * @ORM\Entity - * @Blamable - */ +#[ORM\Entity] +#[Blamable] class MyEntity implements BlamableInterface { - /** - * @ORM\... - */ - private $updated_by; - - /** - * @ORM\... - */ - private $updated_at; - - /** - * @ORM\... - */ - private $created_at; - - public function setUpdatedBy($by) + #[ORM\Column(nullable: true)] + private ?string $updated_by = null; + + #[ORM\Column(type: 'datetime_immutable', nullable: true)] + private ?\DateTimeInterface $updated_at = null; + + #[ORM\Column(type: 'datetime_immutable', nullable: true)] + private ?\DateTimeInterface $created_at = null; + + public function setUpdatedBy(string $by): static { $this->updated_by = $by; + + return $this; } - public function setUpdatedAt(\DateTime $at) + public function setUpdatedAt(\DateTimeInterface $at): static { - $this->changed_at = $at; + $this->updated_at = $at; + + return $this; } - - public function setCreatedAt(\DateTime $at) + + public function setCreatedAt(\DateTimeInterface $at): static { - $this->created_at = $at + $this->created_at = $at; + + return $this; } } diff --git a/composer.json b/composer.json index aaf4e30..b567133 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "php": "^8.3", "doctrine/orm": "^2.4.0", - "hostnet/entity-tracker-component": "^2.3.0", + "hostnet/entity-tracker-component": "^3.0.0", "symfony/cache": "^6.4|^7.4" }, "require-dev": { diff --git a/src/Blamable.php b/src/Blamable.php deleted file mode 100644 index 7fdc1a1..0000000 --- a/src/Blamable.php +++ /dev/null @@ -1,19 +0,0 @@ -getCurrentEntity(); @@ -53,9 +50,9 @@ public function entityChanged(EntityChangedEvent $event): void } } - private function isBlamable(ObjectManager $em, mixed $entity): bool + private function isBlamable(EntityManagerInterface $em, object $entity): bool { - $cache_key = base64_encode('BLAMABLE-' . get_class($entity)); + $cache_key = base64_encode('BLAMABLE-' . $entity::class); $cached_item = $this->is_blamable_cache->getItem($cache_key); if ($cached_item->isHit()) { @@ -66,10 +63,6 @@ private function isBlamable(ObjectManager $em, mixed $entity): bool return $this->save($cached_item, false); } - if (null !== $this->resolver->getBlamableAnnotation($em, $entity)) { - return $this->save($cached_item, true); - } - if (null !== $this->resolver->getBlamableAttribute($em, $entity)) { return $this->save($cached_item, true); } diff --git a/src/Provider/BlamableProviderInterface.php b/src/Provider/BlamableProviderInterface.php index 987c486..9392880 100644 --- a/src/Provider/BlamableProviderInterface.php +++ b/src/Provider/BlamableProviderInterface.php @@ -6,18 +6,9 @@ namespace Hostnet\Component\EntityBlamable\Provider; -/** - * @TODO: add (return)typehints on next BC break, when removing doctrine/annotations - */ interface BlamableProviderInterface { - /** - * @return string - */ - public function getUpdatedBy(); + public function getUpdatedBy(): string; - /** - * @return \DateTime - */ - public function getChangedAt(); + public function getChangedAt(): \DateTimeInterface; } diff --git a/src/Resolver/BlamableResolver.php b/src/Resolver/BlamableResolver.php index ca3a7c2..2f10c80 100644 --- a/src/Resolver/BlamableResolver.php +++ b/src/Resolver/BlamableResolver.php @@ -8,7 +8,6 @@ use Doctrine\ORM\EntityManagerInterface; use Hostnet\Component\EntityBlamable\Attributes\Blamable; -use Hostnet\Component\EntityBlamable\Blamable as BlamabeAnnotation; use Hostnet\Component\EntityTracker\Provider\EntityMetadataProvider; class BlamableResolver implements BlamableResolverInterface @@ -17,17 +16,7 @@ public function __construct(private EntityMetadataProvider $provider) { } - /** - * @see \Hostnet\Component\EntityBlamable\Resolver\BlamableResolverInterface::getBlamableAnnotation() - * - * @deprecated Please use the attribute instead. - */ - public function getBlamableAnnotation(EntityManagerInterface $em, $entity) - { - return $this->provider->getAnnotationFromEntity($em, $entity, BlamabeAnnotation::class); - } - - public function getBlamableAttribute(EntityManagerInterface $em, $entity): ?Blamable + public function getBlamableAttribute(EntityManagerInterface $em, object $entity): ?Blamable { return $this->provider->getAttributeFromEntity(Blamable::class, $em, $entity); } diff --git a/src/Resolver/BlamableResolverInterface.php b/src/Resolver/BlamableResolverInterface.php index 97898ff..90c1cdf 100644 --- a/src/Resolver/BlamableResolverInterface.php +++ b/src/Resolver/BlamableResolverInterface.php @@ -11,15 +11,5 @@ interface BlamableResolverInterface { - /** - * Return the blamable annotation - * - * @param EntityManagerInterface $em - * @param mixed $entity - * - * @deprecated Please use the attribute instead. - */ - public function getBlamableAnnotation(EntityManagerInterface $em, $entity); - - public function getBlamableAttribute(EntityManagerInterface $em, $entity): ?Blamable; + public function getBlamableAttribute(EntityManagerInterface $em, object $entity): ?Blamable; } diff --git a/test/Listener/BlamableListenerTest.php b/test/Listener/BlamableListenerTest.php index 0ab4afa..1d6b9f2 100644 --- a/test/Listener/BlamableListenerTest.php +++ b/test/Listener/BlamableListenerTest.php @@ -7,7 +7,6 @@ namespace Hostnet\Component\EntityBlamable\Listener; use Hostnet\Component\EntityBlamable\Attributes\Blamable; -use Hostnet\Component\EntityBlamable\Blamable as BlamableAnnotation; use Hostnet\Component\EntityTracker\Event\EntityChangedEvent; use PHPUnit\Framework\TestCase; @@ -20,7 +19,6 @@ class BlamableListenerTest extends TestCase private $resolver; private $provider; private $entity; - private $uow; public function setUp(): void { @@ -68,8 +66,8 @@ public function testOnEntityChangedExistingEntity(): void $this->resolver ->expects($this->once()) - ->method('getBlamableAnnotation') - ->willReturn(new BlamableAnnotation()); + ->method('getBlamableAttribute') + ->willReturn(new Blamable()); $event = new EntityChangedEvent($this->em, $this->entity, new \stdClass(), []); $listener = new BlamableListener($this->resolver, $this->provider); @@ -108,8 +106,8 @@ public function testOnEntityChangedNewEntity(): void $this->resolver ->expects($this->once()) - ->method('getBlamableAnnotation') - ->willReturn(new BlamableAnnotation()); + ->method('getBlamableAttribute') + ->willReturn(new Blamable()); $event = new EntityChangedEvent($this->em, $this->entity, null, []); $listener = new BlamableListener($this->resolver, $this->provider); @@ -131,11 +129,6 @@ public function testOnEntityChangedNewEntityWithAttribute(): void ->method('getUpdatedBy') ->willReturn($by); - $this->resolver - ->expects($this->once()) - ->method('getBlamableAnnotation') - ->willReturn(null); - $this->resolver ->expects($this->once()) ->method('getBlamableAttribute') @@ -166,11 +159,6 @@ public function testOnEntityChangedNewEntityWithInterfaceOnly(): void ->expects($this->never()) ->method('getUpdatedBy'); - $this->resolver - ->expects($this->once()) - ->method('getBlamableAnnotation') - ->willReturn(null); - $this->resolver ->expects($this->once()) ->method('getBlamableAttribute') diff --git a/test/Listener/EntityWithAttribute.php b/test/Listener/EntityWithAttribute.php index a14aa75..c7138ab 100644 --- a/test/Listener/EntityWithAttribute.php +++ b/test/Listener/EntityWithAttribute.php @@ -12,14 +12,16 @@ #[Blamable] class EntityWithAttribute implements BlamableInterface { - private ?\DateTime $created_at = null; + private ?\DateTimeInterface $created_at = null; - private ?string $updated_by = null; - private ?\DateTime $updated_at = null; + private ?string $updated_by = null; + private ?\DateTimeInterface $updated_at = null; - public function setUpdatedBy($by): void + public function setUpdatedBy(string $by): static { $this->updated_by = $by; + + return $this; } public function getUpdatedBy(): ?string @@ -27,22 +29,26 @@ public function getUpdatedBy(): ?string return $this->updated_by; } - public function setUpdatedAt(\DateTime $at): void + public function setUpdatedAt(\DateTimeInterface $at): static { $this->updated_at = $at; + + return $this; } - public function getUpdatedAt(): ?\DateTime + public function getUpdatedAt(): ?\DateTimeInterface { return $this->updated_at; } - public function setCreatedAt(\DateTime $at): void + public function setCreatedAt(\DateTimeInterface $at): static { $this->created_at = $at; + + return $this; } - public function getCreatedAt(): ?\DateTime + public function getCreatedAt(): ?\DateTimeInterface { return $this->created_at; } diff --git a/test/Listener/EntityWithInterfaceOnly.php b/test/Listener/EntityWithInterfaceOnly.php index 5fc50cd..6dc9e5b 100644 --- a/test/Listener/EntityWithInterfaceOnly.php +++ b/test/Listener/EntityWithInterfaceOnly.php @@ -10,14 +10,16 @@ class EntityWithInterfaceOnly implements BlamableInterface { - private ?\DateTime $created_at = null; + private ?\DateTimeInterface $created_at = null; - private ?string $updated_by = null; - private ?\DateTime $updated_at = null; + private ?string $updated_by = null; + private ?\DateTimeInterface $updated_at = null; - public function setUpdatedBy($by): void + public function setUpdatedBy(string $by): static { $this->updated_by = $by; + + return $this; } public function getUpdatedBy(): ?string @@ -25,22 +27,26 @@ public function getUpdatedBy(): ?string return $this->updated_by; } - public function setUpdatedAt(\DateTime $at): void + public function setUpdatedAt(\DateTimeInterface $at): static { $this->updated_at = $at; + + return $this; } - public function getUpdatedAt(): ?\DateTime + public function getUpdatedAt(): ?\DateTimeInterface { return $this->updated_at; } - public function setCreatedAt(\DateTime $at): void + public function setCreatedAt(\DateTimeInterface $at): static { $this->created_at = $at; + + return $this; } - public function getCreatedAt(): ?\DateTime + public function getCreatedAt(): ?\DateTimeInterface { return $this->created_at; } diff --git a/test/Resolver/BlamableResolverTest.php b/test/Resolver/BlamableResolverTest.php index cb03318..08c3f73 100644 --- a/test/Resolver/BlamableResolverTest.php +++ b/test/Resolver/BlamableResolverTest.php @@ -6,8 +6,9 @@ namespace Hostnet\Component\EntityBlamable\Resolver; +use Doctrine\ORM\EntityManagerInterface; use Hostnet\Component\EntityBlamable\Attributes\Blamable; -use Hostnet\Component\EntityBlamable\Blamable as BlamableAnnotation; +use Hostnet\Component\EntityTracker\Provider\EntityMetadataProvider; use PHPUnit\Framework\TestCase; /** @@ -22,30 +23,18 @@ class BlamableResolverTest extends TestCase public function setUp(): void { $this->provider = $this - ->getMockBuilder('Hostnet\Component\EntityTracker\Provider\EntityAnnotationMetadataProvider') + ->getMockBuilder(EntityMetadataProvider::class) ->disableOriginalConstructor() ->getMock(); $this->em = $this - ->getMockBuilder('Doctrine\ORM\EntityManagerInterface') + ->getMockBuilder(EntityManagerInterface::class) ->disableOriginalConstructor() ->getMock(); $this->resolver = new BlamableResolver($this->provider); } - public function testGetBlamableAnnotation(): void - { - $entity = new \stdClass(); - - $this->provider - ->expects($this->once()) - ->method('getAnnotationFromEntity') - ->with($this->em, $entity, BlamableAnnotation::class); - - $this->resolver->getBlamableAnnotation($this->em, $entity); - } - public function testGetRevisionAttribute(): void { $entity = new \stdClass();