diff --git a/lib/EventTypes.php b/lib/EventTypes.php new file mode 100644 index 0000000..c981980 --- /dev/null +++ b/lib/EventTypes.php @@ -0,0 +1,91 @@ +} Returns [before, after, events] where before is always null for Events API + */ + public function listEvents($params = []) + { + $eventsPath = "events"; + + // Handle events parameter - convert array to comma-separated string + if (isset($params['events']) && is_array($params['events'])) { + $params['events'] = implode(',', $params['events']); + } + + $response = Client::request(Client::METHOD_GET, $eventsPath, null, $params, true); + $events = []; + foreach ($response["data"] as $responseData) { + \array_push($events, Resource\Event::constructFromResponse($responseData)); + } + $after = $response["list_metadata"]["after"] ?? null; + return [null, $after, $events]; + } +} diff --git a/lib/Resource/Event.php b/lib/Resource/Event.php new file mode 100644 index 0000000..120bb12 --- /dev/null +++ b/lib/Resource/Event.php @@ -0,0 +1,174 @@ + "id", + "object" => "object", + "event" => "event", + "data" => "data", + "created_at" => "createdAt", + ]; + + /** + * Get the event ID. + * + * @return string + */ + public function getId() + { + return $this->values["id"]; + } + + /** + * Get the event object type. + * + * @return string + */ + public function getObject() + { + return $this->values["object"]; + } + + /** + * Get the event type. + * + * @return string + */ + public function getEvent() + { + return $this->values["event"]; + } + + /** + * Get the event data. + * + * @return array + */ + public function getData() + { + return $this->values["data"]; + } + + /** + * Get the event creation timestamp. + * + * @return string + */ + public function getCreatedAt() + { + return $this->values["createdAt"]; + } + + /** + * Get formatted creation date. + * + * @param string $format PHP date format (default: 'Y-m-d H:i:s') + * + * @return string + */ + public function getFormattedCreatedAt($format = 'Y-m-d H:i:s') + { + return date($format, strtotime($this->values["createdAt"])); + } + + /** + * Check if event is of a specific type. + * + * @param string $eventType The event type to check + * + * @return bool + */ + public function isEventType($eventType) + { + return $this->values["event"] === $eventType; + } + + /** + * Check if event is an authentication event. + * + * @return bool + */ + public function isAuthenticationEvent() + { + return strpos($this->values["event"], 'authentication.') === 0; + } + + /** + * Check if event is a user event. + * + * @return bool + */ + public function isUserEvent() + { + return strpos($this->values["event"], 'user.') === 0; + } + + /** + * Check if event is an organization event. + * + * @return bool + */ + public function isOrganizationEvent() + { + return strpos($this->values["event"], 'organization') === 0; + } + + /** + * Check if event is a DSync event. + * + * @return bool + */ + public function isDSyncEvent() + { + return strpos($this->values["event"], 'dsync.') === 0; + } + + /** + * Get a specific data field from the event data. + * + * @param string $key The data key to retrieve + * @param mixed $default Default value if key doesn't exist + * + * @return mixed + */ + public function getDataField($key, $default = null) + { + $data = $this->values["data"]; + + if (is_array($data) && array_key_exists($key, $data)) { + return $data[$key]; + } + + return $default; + } + + /** + * Get the event data as JSON string. + * + * @param int $options JSON encoding options + * + * @return string + */ + public function getDataAsJson($options = JSON_PRETTY_PRINT) + { + return json_encode($this->values["data"], $options); + } +} diff --git a/lib/WorkOS.php b/lib/WorkOS.php index 935e32e..d4a2775 100644 --- a/lib/WorkOS.php +++ b/lib/WorkOS.php @@ -162,4 +162,5 @@ private static function getEnvVariable($key) return false; } + } diff --git a/tests/WorkOS/EventsTest.php b/tests/WorkOS/EventsTest.php new file mode 100644 index 0000000..7ee3d7a --- /dev/null +++ b/tests/WorkOS/EventsTest.php @@ -0,0 +1,303 @@ +traitSetUp(); + $this->withApiKeyAndClientId(); + } + + public function testListEvents() + { + $events = new Events(); + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + ['events' => 'user.created'], + true, + json_encode([ + 'object' => 'list', + 'data' => [ + [ + 'id' => 'event_123', + 'event' => 'user.created', + 'object' => 'event', + 'data' => ['user' => ['id' => 'user_123']], + 'created_at' => '2023-01-01T00:00:00Z' + ] + ], + 'list_metadata' => ['after' => null] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents(['events' => ['user.created']]); + + $this->assertNull($before); + $this->assertNull($after); + $this->assertIsArray($eventsList); + $this->assertCount(1, $eventsList); + $this->assertInstanceOf(\WorkOS\Resource\Event::class, $eventsList[0]); + $this->assertEquals('event_123', $eventsList[0]->getId()); + $this->assertEquals('user.created', $eventsList[0]->getEvent()); + } + + public function testListEventsWithFilters() + { + $events = new Events(); + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + ['events' => 'user.created,user.updated', 'limit' => 10], + true, + json_encode([ + 'object' => 'list', + 'data' => [ + [ + 'id' => 'event_123', + 'event' => 'user.created', + 'object' => 'event', + 'data' => ['user' => ['id' => 'user_123']], + 'created_at' => '2023-01-01T00:00:00Z' + ] + ], + 'list_metadata' => ['after' => null] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents([ + 'events' => 'user.created,user.updated', + 'limit' => 10 + ]); + + $this->assertNull($before); + $this->assertNull($after); + $this->assertIsArray($eventsList); + $this->assertCount(1, $eventsList); + $this->assertInstanceOf(\WorkOS\Resource\Event::class, $eventsList[0]); + $this->assertEquals('user.created', $eventsList[0]->getEvent()); + } + + public function testListEventsWithArrayFilter() + { + $events = new Events(); + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + ['events' => 'user.created,user.updated', 'limit' => 5], + true, + json_encode([ + 'object' => 'list', + 'data' => [], + 'list_metadata' => ['after' => null] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents([ + 'events' => ['user.created', 'user.updated'], + 'limit' => 5 + ]); + + $this->assertNull($before); + $this->assertNull($after); + $this->assertIsArray($eventsList); + $this->assertCount(0, $eventsList); + } + + public function testListEventsWithAllParameters() + { + $events = new Events(); + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + [ + 'events' => 'user.created,user.updated', + 'limit' => 25, + 'order' => 'asc', + 'organization_id' => 'org_123', + 'after' => 'cursor_after', + 'before' => 'cursor_before' + ], + true, + json_encode([ + 'object' => 'list', + 'data' => [], + 'list_metadata' => ['after' => 'cursor_next'] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents([ + 'events' => ['user.created', 'user.updated'], + 'limit' => 25, + 'order' => 'asc', + 'organization_id' => 'org_123', + 'after' => 'cursor_after', + 'before' => 'cursor_before' + ]); + + $this->assertNull($before); + $this->assertEquals('cursor_next', $after); + $this->assertIsArray($eventsList); + $this->assertCount(0, $eventsList); + } + + public function testEventResourceCreation() + { + $events = new Events(); + + $eventData = [ + 'id' => 'event_123', + 'event' => 'user.created', + 'object' => 'event', + 'data' => ['user' => ['id' => 'user_123']], + 'created_at' => '2023-01-01T00:00:00Z' + ]; + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + ['events' => 'user.created', 'limit' => 1], + true, + json_encode([ + 'object' => 'list', + 'data' => [$eventData], + 'list_metadata' => ['after' => null] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents(['events' => ['user.created'], 'limit' => 1]); + + $this->assertNotEmpty($eventsList); + $this->assertCount(1, $eventsList); + $event = $eventsList[0]; + + $this->assertInstanceOf(\WorkOS\Resource\Event::class, $event); + $this->assertEquals($eventData['id'], $event->getId()); + $this->assertEquals($eventData['event'], $event->getEvent()); + $this->assertEquals($eventData['data'], $event->getData()); + + // Test helper methods + $this->assertTrue($event->isUserEvent()); + + // Test JSON formatting + $jsonData = $event->getDataAsJson(); + $this->assertIsString($jsonData); + $this->assertJson($jsonData); + } + + public function testEventResourceHelperMethods() + { + $eventData = [ + 'id' => 'event_123', + 'event' => 'authentication.sso_succeeded', + 'object' => 'event', + 'data' => ['user' => ['id' => 'user_123']], + 'created_at' => '2023-01-01T00:00:00Z' + ]; + + $event = \WorkOS\Resource\Event::constructFromResponse($eventData); + + // Test event type checks + $this->assertTrue($event->isAuthenticationEvent()); + $this->assertFalse($event->isUserEvent()); + $this->assertFalse($event->isOrganizationEvent()); + $this->assertFalse($event->isDSyncEvent()); + + // Test specific event type + $this->assertTrue($event->isEventType('authentication.sso_succeeded')); + $this->assertFalse($event->isEventType('user.created')); + } + + public function testEventResourceDataAccess() + { + $eventData = [ + 'id' => 'event_123', + 'event' => 'user.created', + 'object' => 'event', + 'data' => [ + 'user' => [ + 'id' => 'user_123', + 'email' => 'test@example.com' + ] + ], + 'created_at' => '2023-01-01T00:00:00Z' + ]; + + $event = \WorkOS\Resource\Event::constructFromResponse($eventData); + + // Test data field access + $userData = $event->getDataField('user'); + $this->assertIsArray($userData); + $this->assertEquals('user_123', $userData['id']); + $this->assertEquals('test@example.com', $userData['email']); + $this->assertNull($event->getDataField('nonexistent')); + + // Test formatted date + $formattedDate = $event->getFormattedCreatedAt('Y-m-d H:i:s'); + $this->assertIsString($formattedDate); + $this->assertStringContainsString('2023-01-01', $formattedDate); + } + + public function testEventTypesConstants() + { + // Test that EventTypes constants are accessible and have correct values + $this->assertEquals('user.created', EventTypes::USER_CREATED); + $this->assertEquals('user.updated', EventTypes::USER_UPDATED); + $this->assertEquals('user.deleted', EventTypes::USER_DELETED); + $this->assertEquals('authentication.sso_succeeded', EventTypes::AUTHENTICATION_SSO_SUCCEEDED); + $this->assertEquals('organization.created', EventTypes::ORGANIZATION_CREATED); + } + + public function testListEventsWithEventTypesConstants() + { + $events = new Events(); + + $this->mockRequest( + Client::METHOD_GET, + "events", + null, + ['events' => EventTypes::USER_CREATED . ',' . EventTypes::USER_UPDATED], + true, + json_encode([ + 'object' => 'list', + 'data' => [ + [ + 'id' => 'event_123', + 'event' => 'user.created', + 'object' => 'event', + 'data' => ['user' => ['id' => 'user_123']], + 'created_at' => '2023-01-01T00:00:00Z' + ] + ], + 'list_metadata' => ['after' => null] + ]) + ); + + list($before, $after, $eventsList) = $events->listEvents([ + 'events' => [EventTypes::USER_CREATED, EventTypes::USER_UPDATED] + ]); + + $this->assertNull($before); + $this->assertNull($after); + $this->assertIsArray($eventsList); + $this->assertCount(1, $eventsList); + $this->assertInstanceOf(\WorkOS\Resource\Event::class, $eventsList[0]); + } +}