diff --git a/backend/src/Api/Console/Controller/SubscriberController.php b/backend/src/Api/Console/Controller/SubscriberController.php index d73affc8..bb1c6f4b 100644 --- a/backend/src/Api/Console/Controller/SubscriberController.php +++ b/backend/src/Api/Console/Controller/SubscriberController.php @@ -261,6 +261,19 @@ private function skipLists(Subscriber $subscriber, array $lists, array $reasonsT ); } + #[Route('/subscribers/email/{email}', methods: 'GET')] + #[ScopeRequired(Scope::SUBSCRIBERS_READ)] + public function getSubscriberByEmail(string $email, Newsletter $newsletter): JsonResponse + { + $subscriber = $this->subscriberService->getSubscriberByEmail($newsletter, $email); + + if ($subscriber === null) { + return $this->json(['message' => 'Subscriber not found'], 404); + } + + return $this->json(new SubscriberObject($subscriber)); + } + #[Route('/subscribers/{id}', methods: 'DELETE')] #[ScopeRequired(Scope::SUBSCRIBERS_WRITE)] public function deleteSubscriber(Subscriber $subscriber): JsonResponse diff --git a/backend/src/Api/Console/Object/SubscriberObject.php b/backend/src/Api/Console/Object/SubscriberObject.php index 4a8ed305..cc4253bd 100644 --- a/backend/src/Api/Console/Object/SubscriberObject.php +++ b/backend/src/Api/Console/Object/SubscriberObject.php @@ -17,6 +17,10 @@ class SubscriberObject * @var array */ public array $list_ids; + /** + * @var array + */ + public array $lists; public ?string $subscribe_ip; public ?int $subscribed_at; @@ -31,7 +35,9 @@ public function __construct(Subscriber $subscriber) $this->email = $subscriber->getEmail(); $this->source = $subscriber->getSource(); $this->status = $subscriber->getStatus(); - $this->list_ids = array_values($subscriber->getLists()->map(fn($list) => $list->getId())->toArray()); + $subscriberLists = $subscriber->getLists(); + $this->list_ids = array_values($subscriberLists->map(fn($list) => $list->getId())->toArray()); + $this->lists = array_values($subscriberLists->map(fn($list) => $list->getName())->toArray()); $this->subscribe_ip = $subscriber->getSubscribeIp(); $this->subscribed_at = $subscriber->getSubscribedAt()?->getTimestamp(); $this->metadata = $subscriber->getMetadata(); diff --git a/backend/tests/Api/Console/Subscriber/GetSubscriberByEmailTest.php b/backend/tests/Api/Console/Subscriber/GetSubscriberByEmailTest.php new file mode 100644 index 00000000..a40532ff --- /dev/null +++ b/backend/tests/Api/Console/Subscriber/GetSubscriberByEmailTest.php @@ -0,0 +1,85 @@ + $newsletter, 'name' => 'list-one']); + $list2 = NewsletterListFactory::createOne(['newsletter' => $newsletter, 'name' => 'list-two']); + + $subscriber = SubscriberFactory::createOne([ + 'newsletter' => $newsletter, + 'email' => 'test@example.com', + 'lists' => [$list1, $list2], + ]); + + $response = $this->consoleApi( + $newsletter, + 'GET', + '/subscribers/email/test@example.com', + ); + + $this->assertSame(200, $response->getStatusCode()); + $json = $this->getJson(); + $this->assertSame($subscriber->getId(), $json['id']); + $this->assertSame('test@example.com', $json['email']); + $this->assertIsArray($json['list_ids']); + $this->assertIsArray($json['lists']); + $this->assertContains($list1->getId(), $json['list_ids']); + $this->assertContains($list2->getId(), $json['list_ids']); + $this->assertContains('list-one', $json['lists']); + $this->assertContains('list-two', $json['lists']); + } + + public function test_get_subscriber_by_email_not_found(): void + { + $newsletter = NewsletterFactory::createOne(); + + $response = $this->consoleApi( + $newsletter, + 'GET', + '/subscribers/email/nonexistent@example.com', + ); + + $this->assertSame(404, $response->getStatusCode()); + } + + public function test_get_subscriber_by_email_other_newsletter(): void + { + $newsletter = NewsletterFactory::createOne(); + $otherNewsletter = NewsletterFactory::createOne(); + + SubscriberFactory::createOne([ + 'newsletter' => $newsletter, + 'email' => 'test@example.com', + ]); + + $response = $this->consoleApi( + $otherNewsletter, + 'GET', + '/subscribers/email/test@example.com', + ); + + $this->assertSame(404, $response->getStatusCode()); + } +} diff --git a/frontend/src/routes/(marketing)/docs/[...slug]/content/ConsoleApi.svelte b/frontend/src/routes/(marketing)/docs/[...slug]/content/ConsoleApi.svelte index 9660d9fc..bd26c6b2 100644 --- a/frontend/src/routes/(marketing)/docs/[...slug]/content/ConsoleApi.svelte +++ b/frontend/src/routes/(marketing)/docs/[...slug]/content/ConsoleApi.svelte @@ -284,6 +284,10 @@