Skip to content

Commit fec65e4

Browse files
committed
Add unsubscribe endpoint
1 parent e7404f4 commit fec65e4

3 files changed

Lines changed: 85 additions & 15 deletions

File tree

src/Subscription/Controller/SubscribePagePublicController.php

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Doctrine\ORM\EntityManagerInterface;
88
use OpenApi\Attributes as OA;
9+
use PhpList\Core\Domain\Subscription\Model\SubscribePageData;
910
use PhpList\Core\Domain\Subscription\Repository\SubscriberListRepository;
1011
use PhpList\Core\Domain\Subscription\Service\Manager\SubscribePageManager;
1112
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberAttributeManager;
@@ -15,7 +16,6 @@
1516
use PhpList\RestBundle\Common\Validator\RequestValidator;
1617
use PhpList\RestBundle\Subscription\Request\PublicSubscriptionRequest;
1718
use PhpList\RestBundle\Subscription\Serializer\SubscribePagePublicNormalizer;
18-
use PhpList\RestBundle\Subscription\Serializer\SubscriptionNormalizer;
1919
use Symfony\Component\HttpFoundation\JsonResponse;
2020
use Symfony\Component\HttpFoundation\Request;
2121
use Symfony\Component\HttpFoundation\Response;
@@ -30,7 +30,6 @@ public function __construct(
3030
private readonly SubscribePageManager $subscribePageManager,
3131
private readonly EntityManagerInterface $entityManager,
3232
private readonly SubscriptionManager $subscriptionManager,
33-
private readonly SubscriptionNormalizer $subscriptionNormalizer,
3433
private readonly SubscriberAttributeManager $subscriberAttributeManager,
3534
private readonly SubscriberListRepository $subscriberListRepository,
3635
) {
@@ -99,12 +98,8 @@ public function getPublicPage(Request $request, SubscribePagePublicNormalizer $n
9998
],
10099
responses: [
101100
new OA\Response(
102-
response: 201,
103-
description: 'Success',
104-
content: new OA\JsonContent(
105-
type: 'array',
106-
items: new OA\Items(ref: '#/components/schemas/Subscription')
107-
)
101+
response: 204,
102+
description: 'Success'
108103
),
109104
new OA\Response(
110105
response: 400,
@@ -127,7 +122,7 @@ public function subscribe(Request $request, int $pageId): JsonResponse
127122
{
128123
$page = $this->subscribePageManager->findPublicPage(id: $pageId);
129124
if (!$page) {
130-
throw $this->createNotFoundException('Subscriber subscribe page not found.');
125+
throw $this->createNotFoundException('Subscribe page not found.');
131126
}
132127

133128
/** @var PublicSubscriptionRequest $subscriptionRequest */
@@ -158,8 +153,85 @@ public function subscribe(Request $request, int $pageId): JsonResponse
158153
}
159154
$this->entityManager->flush();
160155

161-
$normalized = array_map(fn($item) => $this->subscriptionNormalizer->normalize($item), $subscriptions);
156+
return $this->json(null, Response::HTTP_NO_CONTENT);
157+
}
158+
159+
#[Route('/{pageId}', name: 'unsubscribe', methods: ['DELETE'])]
160+
#[OA\Delete(
161+
path: '/api/v2/public/subscribe-pages/{pageId}',
162+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production.' .
163+
'Unsubscribe subscriber from a list from subscribe page.',
164+
summary: 'Delete subscription',
165+
tags: ['subscribe-pages'],
166+
parameters: [
167+
new OA\Parameter(
168+
name: 'pageId',
169+
description: 'Subscribe page ID',
170+
in: 'path',
171+
required: true,
172+
schema: new OA\Schema(type: 'integer')
173+
),
174+
new OA\Parameter(
175+
name: 'email',
176+
description: 'Subscriber email',
177+
in: 'query',
178+
required: true,
179+
schema: new OA\Schema(type: 'string')
180+
),
181+
],
182+
responses: [
183+
new OA\Response(
184+
response: 204,
185+
description: 'Success'
186+
),
187+
new OA\Response(
188+
response: 400,
189+
description: 'Failure',
190+
content: new OA\JsonContent(ref: '#/components/schemas/BadRequestResponse')
191+
),
192+
new OA\Response(
193+
response: 404,
194+
description: 'Failure',
195+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
196+
),
197+
new OA\Response(
198+
response: 422,
199+
description: 'Failure',
200+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
201+
),
202+
]
203+
)]
204+
public function unsubscribe(Request $request, int $pageId): JsonResponse
205+
{
206+
$page = $this->subscribePageManager->findPage(id: $pageId);
207+
if (!$page) {
208+
throw $this->createNotFoundException('Subscribe page not found.');
209+
}
210+
211+
/** @var SubscribePageData|null $listsField */
212+
$listsField = array_find(
213+
$page->getData(),
214+
fn (SubscribePageData $data) => $data->getName() === 'lists'
215+
);
216+
217+
if ($listsField === null) {
218+
return $this->json(null, Response::HTTP_NO_CONTENT);
219+
}
220+
221+
$listsIds = explode(',', $listsField->getData() ?? '');
222+
if ($listsIds == []) {
223+
return $this->json(null, Response::HTTP_NO_CONTENT);
224+
}
225+
226+
$lists = $this->subscriberListRepository->findBy(['id' => $listsIds]);
227+
foreach ($lists as $list) {
228+
$this->subscriptionManager->deleteSubscriptions(
229+
subscriberList: $list,
230+
emails: [$request->query->get('email')]
231+
);
232+
}
233+
$this->entityManager->flush();
162234

163-
return $this->json($normalized, Response::HTTP_CREATED);
235+
return $this->json(null, Response::HTTP_NO_CONTENT);
164236
}
165237
}

src/Subscription/Request/PublicSubscriptionRequest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#[OA\Schema(
1616
schema: 'PublicSubscriptionRequest',
17+
required: ['email', 'list_id'],
1718
properties: [
1819
new OA\Property(
1920
property: 'email',

tests/Integration/Subscription/Controller/SubscribePagePublicControllerTest.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,7 @@ public function testSubscribeCreatesSubscriptionAndAttributes(): void
8989
], JSON_THROW_ON_ERROR);
9090

9191
$this->jsonRequest('POST', '/api/v2/public/subscribe-pages/1', [], [], [], $payload);
92-
$this->assertHttpCreated();
93-
94-
$response = $this->getDecodedJsonResponseContent();
95-
self::assertSame('public@example.com', $response[0]['subscriber']['email'] ?? null);
92+
$this->assertHttpNoContent();
9693

9794
$subscriber = $this->entityManager?->getRepository(Subscriber::class)
9895
->findOneBy(['email' => 'public@example.com']);

0 commit comments

Comments
 (0)