From 18687d478ba1cfca1b5b8d45b39968d3effcfe2e Mon Sep 17 00:00:00 2001 From: Tatevik Date: Tue, 22 Jul 2025 12:32:36 +0400 Subject: [PATCH] Mark subscriber as confirmed by UniqueId --- .../Controller/SubscriberController.php | 50 +++++++++++++++++++ .../Controller/SubscriberImportController.php | 2 +- .../Controller/SubscriberControllerTest.php | 41 +++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/Subscription/Controller/SubscriberController.php b/src/Subscription/Controller/SubscriberController.php index a281b659..9d3aecb4 100644 --- a/src/Subscription/Controller/SubscriberController.php +++ b/src/Subscription/Controller/SubscriberController.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Attribute\Route; /** @@ -281,4 +282,53 @@ public function deleteSubscriber( return $this->json(null, Response::HTTP_NO_CONTENT); } + + #[Route('/confirm', name: 'confirm', methods: ['GET'])] + #[OA\Get( + path: '/api/v2/subscribers/confirm', + description: '🚧 **Status: Beta** – This method is under development. Avoid using in production.', + summary: 'Confirm a subscriber by uniqueId.', + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent( + properties: [ + new OA\Property(property: 'uniqueId', type: 'string', example: 'e9d8c9b2e6') + ] + ) + ), + tags: ['subscribers'], + responses: [ + new OA\Response( + response: 200, + description: 'Subscriber confirmed', + content: new OA\MediaType( + mediaType: 'text/html' + ) + ), + new OA\Response( + response: 400, + description: 'Missing or invalid uniqueId' + ), + new OA\Response( + response: 404, + description: 'Subscriber not found' + ) + ] + )] + public function setSubscriberAsConfirmed(Request $request): Response + { + $uniqueId = $request->query->get('uniqueId'); + + if (!$uniqueId) { + return new Response('

Missing confirmation code.

', 400); + } + + try { + $this->subscriberManager->markAsConfirmedByUniqueId($uniqueId); + } catch (NotFoundHttpException) { + return new Response('

Subscriber isn\'t found or already confirmed.

', 404); + } + + return new Response('

Thank you, your subscription is confirmed!

'); + } } diff --git a/src/Subscription/Controller/SubscriberImportController.php b/src/Subscription/Controller/SubscriberImportController.php index 57e546d5..683140b8 100644 --- a/src/Subscription/Controller/SubscriberImportController.php +++ b/src/Subscription/Controller/SubscriberImportController.php @@ -55,7 +55,7 @@ public function __construct( description: 'List id to add imported subscribers to', type: 'string', default: null, - pattern: "^\\d+$" + pattern: '^\\d+$' ), new OA\Property( property: 'update_existing', diff --git a/tests/Integration/Subscription/Controller/SubscriberControllerTest.php b/tests/Integration/Subscription/Controller/SubscriberControllerTest.php index 2ee4c226..3ffb4dd2 100644 --- a/tests/Integration/Subscription/Controller/SubscriberControllerTest.php +++ b/tests/Integration/Subscription/Controller/SubscriberControllerTest.php @@ -9,6 +9,7 @@ use PhpList\RestBundle\Subscription\Controller\SubscriberController; use PhpList\RestBundle\Tests\Integration\Common\AbstractTestController; use PhpList\RestBundle\Tests\Integration\Subscription\Fixtures\SubscriberFixture; +use Symfony\Component\HttpFoundation\Response; /** * Testcase. @@ -165,4 +166,44 @@ public function testPostSubscribersWithValidSessionKeyAssignsProvidedSubscriberD static::assertTrue($responseContent['html_email']); static::assertFalse($responseContent['disabled']); } + public function testSetSubscriberAsConfirmedWithMissingUniqueIdReturnsBadRequestStatus() + { + self::getClient()->request('get', '/api/v2/subscribers/confirm'); + + $response = self::getClient()->getResponse(); + self::assertSame(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); + self::assertStringContainsString('Missing confirmation code', $response->getContent()); + } + + public function testSetSubscriberAsConfirmedWithInvalidUniqueIdReturnsNotFoundStatus() + { + self::getClient()->request('get', '/api/v2/subscribers/confirm', ['uniqueId' => 'invalid-unique-id']); + + $response = self::getClient()->getResponse(); + self::assertSame(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + self::assertStringContainsString('Subscriber isn\'t found', $response->getContent()); + } + + public function testSetSubscriberAsConfirmedWithValidUniqueIdConfirmsSubscriber() + { + $email = 'unconfirmed1@example.com'; + $jsonData = ['email' => $email, 'requestConfirmation' => true]; + + $this->authenticatedJsonRequest('post', '/api/v2/subscribers', [], [], [], json_encode($jsonData)); + $responseContent = $this->getDecodedJsonResponseContent(); + $uniqueId = $responseContent['unique_id']; + + $subscriberId = $responseContent['id']; + $subscriber = $this->subscriberRepository->find($subscriberId); + self::assertFalse($subscriber->isConfirmed()); + + self::getClient()->request('get', '/api/v2/subscribers/confirm', ['uniqueId' => $uniqueId]); + + $response = self::getClient()->getResponse(); + self::assertSame(Response::HTTP_OK, $response->getStatusCode()); + self::assertStringContainsString('Thank you, your subscription is confirmed', $response->getContent()); + + $subscriber = $this->subscriberRepository->findOneByUniqueId($uniqueId); + self::assertTrue($subscriber->isConfirmed()); + } }