diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 44dfad70bc..c783f0a226 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -171,8 +171,8 @@ class Hook * Use this function when you want to be able to allow a hook to manipulate * the provided data. * - * @param string $name of the hook to call - * @param string|array &$data to transmit to the callback handler + * @param string $name of the hook to call + * @param int|string|array|null $data to transmit to the callback handler * @return void * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index cc2e8be225..1567b3e20a 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -69,6 +69,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', + ArrayFilterEvent::EVENT_CREATED => 'event_created', + ArrayFilterEvent::EVENT_UPDATED => 'event_updated', ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', @@ -123,6 +125,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', + ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', @@ -211,6 +215,32 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the EVENT_CREATED event to `event_created` hook + */ + public static function onEventCreatedEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $id = (int) $data['event']['id'] ?? 0; + + // one-way-event: we don't care about the returned value + static::callHook($event->getName(), $id); + } + + /** + * Map the EVENT_UPDATED event to `event_updated` hook + */ + public static function onEventUpdatedEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $id = (int) $data['event']['id'] ?? 0; + + // one-way-event: we don't care about the returned value + static::callHook($event->getName(), $id); + } + public static function onArrayFilterEvent(ArrayFilterEvent $event): void { $event->setArray( @@ -226,9 +256,9 @@ final class HookEventBridge } /** - * @param string|array|object $data + * @param int|string|array|object $data * - * @return string|array|object + * @return int|string|array|object */ private static function callHook(string $name, $data) { diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index ac72f3d29a..b3be9f70fa 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -76,6 +76,10 @@ final class ArrayFilterEvent extends Event public const AVATAR_LOOKUP = 'friendica.data.avatar_lookup'; + public const EVENT_CREATED = 'friendica.data.event_created'; + + public const EVENT_UPDATED = 'friendica.data.event_updated'; + public const ADD_WORKER_TASK = 'friendica.data.add_worker_task'; public const STORAGE_CONFIG = 'friendica.data.storage_config'; diff --git a/src/Model/Event.php b/src/Model/Event.php index 6cb73f4c37..debeb74d45 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -14,6 +14,7 @@ use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\UnauthorizedException; @@ -255,6 +256,7 @@ class Event 'finish' => DateTimeFormat::utc(($arr['finish'] ?? '') ?: DBA::NULL_DATETIME), ]; + $eventDispatcher = DI::eventDispatcher(); if ($event['finish'] < DBA::NULL_DATETIME) { $event['finish'] = DBA::NULL_DATETIME; @@ -295,14 +297,18 @@ class Event Item::update($fields, ['id' => $item['id']]); } - Hook::callAll('event_updated', $event['id']); + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => $event]), + ); } else { // New event. Store it. DBA::insert('event', $event); $event['id'] = DBA::lastInsertId(); - Hook::callAll("event_created", $event['id']); + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EVENT_CREATED, ['event' => $event]), + ); } return $event['id']; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 77e0b1ecfc..1852248ebb 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -58,6 +58,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', + ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', @@ -267,6 +269,40 @@ class HookEventBridgeTest extends TestCase ); } + public function testOnEventCreatedEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_CREATED, ['event' => ['id' => 123]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('event_created', $name); + $this->assertSame(123, $data); + + return 123; + }); + + HookEventBridge::onEventCreatedEvent($event); + } + + public function testOnEventUpdatedEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => ['id' => 123]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('event_updated', $name); + $this->assertSame(123, $data); + + return 123; + }); + + HookEventBridge::onEventUpdatedEvent($event); + } + public static function getArrayFilterEventData(): array { return [ @@ -297,6 +333,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], + [ArrayFilterEvent::EVENT_CREATED, 'event_created'], + [ArrayFilterEvent::EVENT_UPDATED, 'event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 0e0c147216..0e4467c1ed 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -55,6 +55,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], + [ArrayFilterEvent::EVENT_CREATED, 'friendica.data.event_created'], + [ArrayFilterEvent::EVENT_UPDATED, 'friendica.data.event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'],