diff --git a/src/Event/DataObjectEvent.php b/src/Event/DataObjectEvent.php index b0878d0..4e20bea 100644 --- a/src/Event/DataObjectEvent.php +++ b/src/Event/DataObjectEvent.php @@ -24,13 +24,15 @@ * Example usage: * ```php * $event = DataObjectEvent::create( - * $dataObject->ID, * get_class($dataObject), + * $dataObject->ID, * Operation::UPDATE, * $dataObject->Version, * Security::getCurrentUser()?->ID * ); * ``` + * + * @template T of DataObject */ class DataObjectEvent { @@ -42,15 +44,15 @@ class DataObjectEvent private readonly int $timestamp; /** + * @param class-string $objectClass The class name of the affected DataObject * @param int $objectID The ID of the affected DataObject - * @param string $objectClass The class name of the affected DataObject * @param Operation $operation The type of operation performed * @param int|null $version The version number (for versioned objects) * @param int|null $memberID The ID of the member who performed the operation */ public function __construct( - private readonly int $objectID, private readonly string $objectClass, + private readonly int $objectID, private readonly Operation $operation, private readonly ?int $version = null, private readonly ?int $memberID = null @@ -109,6 +111,8 @@ public function getTimestamp(): int /** * Get the DataObject associated with this event * + * @phpstan-return T|null + * * @param bool $useVersion If true and the object is versioned, retrieves the specific version that was affected * Note: This may return null if the object has been deleted since the event was created */ diff --git a/src/Extension/EventDispatchExtension.php b/src/Extension/EventDispatchExtension.php index 6c35325..e23b1eb 100644 --- a/src/Extension/EventDispatchExtension.php +++ b/src/Extension/EventDispatchExtension.php @@ -27,8 +27,8 @@ public function onAfterWrite(): void { $owner = $this->getOwner(); $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, // By this point isInDB() will return true even for new records since the ID is already set // Instead check if the ID field was changed which indicates this is a new record $owner->isChanged('ID') ? Operation::CREATE : Operation::UPDATE, @@ -46,8 +46,8 @@ public function onBeforeDelete(): void { $owner = $this->getOwner(); $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, Operation::DELETE, $owner->hasExtension(Versioned::class) ? $owner->Version : null, Security::getCurrentUser()?->ID @@ -67,8 +67,8 @@ public function onAfterPublish(): void } $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, Operation::PUBLISH, $owner->Version, Security::getCurrentUser()?->ID @@ -88,8 +88,8 @@ public function onAfterUnpublish(): void } $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, Operation::UNPUBLISH, $owner->Version, Security::getCurrentUser()?->ID @@ -109,8 +109,8 @@ public function onAfterArchive(): void } $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, Operation::ARCHIVE, $owner->Version, Security::getCurrentUser()?->ID @@ -130,8 +130,8 @@ public function onAfterRestore(): void } $event = DataObjectEvent::create( - $owner->ID, get_class($owner), + $owner->ID, Operation::RESTORE, $owner->Version, Security::getCurrentUser()?->ID diff --git a/src/Listener/DataObjectEventListener.php b/src/Listener/DataObjectEventListener.php index e377647..9157bc6 100644 --- a/src/Listener/DataObjectEventListener.php +++ b/src/Listener/DataObjectEventListener.php @@ -17,6 +17,8 @@ * This listener can be configured to only handle specific operations (create, update, delete etc) * and specific DataObject classes. When an event matches the configured criteria, the callback * is executed with the event. + * + * @template T of DataObject */ class DataObjectEventListener { @@ -25,8 +27,9 @@ class DataObjectEventListener /** * Creates a new DataObject event listener. * - * @param Closure(DataObjectEvent): void $callback Callback to execute when an event matches - * @param class-string[] $classes Array of DataObject class names to listen for + * @template T of DataObject + * @param Closure(DataObjectEvent): void $callback Callback to execute when an event matches + * @param class-string[] $classes Array of DataObject class names to listen for * @param Operation[]|null $operations Array of operations to listen for. If null, listens for all operations. */ public function __construct( @@ -56,7 +59,7 @@ public function selfRegister(ListenerProvider|EventService $provider = null): vo * Checks if the event matches the configured operations and classes, * and executes the callback if it does. * - * @param DataObjectEvent $event The event to handle + * @param DataObjectEvent $event The event to handle */ public function __invoke(DataObjectEvent $event): void { diff --git a/tests/php/Event/DataObjectEventTest.php b/tests/php/Event/DataObjectEventTest.php index 31e47ed..7fef75a 100644 --- a/tests/php/Event/DataObjectEventTest.php +++ b/tests/php/Event/DataObjectEventTest.php @@ -20,7 +20,7 @@ class DataObjectEventTest extends SapphireTest public function testEventCreation(): void { - $event = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE, null, 1); + $event = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE, null, 1); $this->assertEquals(1, $event->getObjectID()); $this->assertEquals(SimpleDataObject::class, $event->getObjectClass()); @@ -35,7 +35,7 @@ public function testGetObject(): void /** @var SimpleDataObject $object */ $object = $this->objFromFixture(SimpleDataObject::class, 'object1'); - $event = DataObjectEvent::create($object->ID, SimpleDataObject::class, Operation::UPDATE); + $event = DataObjectEvent::create(SimpleDataObject::class, $object->ID, Operation::UPDATE); $this->assertNotNull($event->getObject()); $this->assertEquals($object->ID, $event->getObject()->ID); @@ -50,7 +50,7 @@ public function testGetVersionedObject(): void $object->Title = 'Updated Title'; $object->write(); - $event = DataObjectEvent::create($object->ID, VersionedDataObject::class, Operation::UPDATE, $object->Version); + $event = DataObjectEvent::create(VersionedDataObject::class, $object->ID, Operation::UPDATE, $object->Version); // Get current version $currentObject = $event->getObject(false); @@ -61,7 +61,7 @@ public function testGetVersionedObject(): void $this->assertEquals('Updated Title', $versionedObject->Title); // Get previous version - $previousEvent = DataObjectEvent::create($object->ID, VersionedDataObject::class, Operation::UPDATE, $object->Version - 1); + $previousEvent = DataObjectEvent::create(VersionedDataObject::class, $object->ID, Operation::UPDATE, $object->Version - 1); $previousVersion = $previousEvent->getObject(true); $this->assertEquals('Original Title', $previousVersion->Title); } @@ -71,7 +71,7 @@ public function testGetMember(): void /** @var Member $member */ $member = $this->objFromFixture(Member::class, 'member1'); - $event = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE, null, $member->ID); + $event = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE, null, $member->ID); $this->assertNotNull($event->getMember()); $this->assertEquals($member->ID, $event->getMember()->ID); @@ -79,7 +79,7 @@ public function testGetMember(): void public function testSerialization(): void { - $event = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE, 2, 3); + $event = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE, 2, 3); $serialized = serialize($event); /** @var DataObjectEvent $unserialized */ diff --git a/tests/php/Listener/DataObjectEventListenerTest.php b/tests/php/Listener/DataObjectEventListenerTest.php index 6563ce0..84431a5 100644 --- a/tests/php/Listener/DataObjectEventListenerTest.php +++ b/tests/php/Listener/DataObjectEventListenerTest.php @@ -44,12 +44,12 @@ function (DataObjectEvent $event) { ); // Should handle SimpleDataObject event - $simpleEvent = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE); + $simpleEvent = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE); $listener($simpleEvent); $this->assertCount(1, $this->receivedEvents, 'Listener should handle SimpleDataObject events'); // Should not handle VersionedDataObject event - $versionedEvent = DataObjectEvent::create(1, VersionedDataObject::class, Operation::CREATE); + $versionedEvent = DataObjectEvent::create(VersionedDataObject::class, 1, Operation::CREATE); $listener($versionedEvent); $this->assertCount(1, $this->receivedEvents, 'Listener should not handle VersionedDataObject events'); } @@ -65,8 +65,8 @@ function (DataObjectEvent $event) { ); // Should handle both SimpleDataObject and VersionedDataObject events - $simpleEvent = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE); - $versionedEvent = DataObjectEvent::create(1, VersionedDataObject::class, Operation::CREATE); + $simpleEvent = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE); + $versionedEvent = DataObjectEvent::create(VersionedDataObject::class, 1, Operation::CREATE); $listener($simpleEvent); $listener($versionedEvent); @@ -86,17 +86,17 @@ function (DataObjectEvent $event) { ); // Should handle CREATE event - $createEvent = DataObjectEvent::create(1, SimpleDataObject::class, Operation::CREATE); + $createEvent = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE); $listener($createEvent); $this->assertCount(1, $this->receivedEvents, 'Listener should handle CREATE events'); // Should handle UPDATE event - $updateEvent = DataObjectEvent::create(1, SimpleDataObject::class, Operation::UPDATE); + $updateEvent = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::UPDATE); $listener($updateEvent); $this->assertCount(2, $this->receivedEvents, 'Listener should handle UPDATE events'); // Should not handle DELETE event - $deleteEvent = DataObjectEvent::create(1, SimpleDataObject::class, Operation::DELETE); + $deleteEvent = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::DELETE); $listener($deleteEvent); $this->assertCount(2, $this->receivedEvents, 'Listener should not handle DELETE events'); } @@ -113,7 +113,7 @@ function (DataObjectEvent $event) { // Should handle all operations foreach (Operation::cases() as $operation) { - $event = DataObjectEvent::create(1, SimpleDataObject::class, $operation); + $event = DataObjectEvent::create(SimpleDataObject::class, 1, $operation); $listener($event); }