Skip to content

Commit 9780fc8

Browse files
committed
ISSUE-345: delete subscription endpoint
1 parent 6068d25 commit 9780fc8

File tree

7 files changed

+93
-6
lines changed

7 files changed

+93
-6
lines changed

config/services/normalizers.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ services:
22
_defaults:
33
autowire: true
44
autoconfigure: true
5+
public: false
56

67
Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter: ~
78

config/services/validators.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ services:
22
PhpList\RestBundle\Validator\RequestValidator:
33
autowire: true
44
autoconfigure: true
5+
public: false
56

67
PhpList\RestBundle\Validator\UniqueEmailValidator:
78
autowire: true

src/Controller/SubscriptionController.php

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
use OpenApi\Attributes as OA;
88
use PhpList\Core\Security\Authentication;
99
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
10-
use PhpList\RestBundle\Entity\Request\CreateSubscriptionRequest;
10+
use PhpList\RestBundle\Entity\Request\SubscriptionRequest;
11+
use PhpList\RestBundle\Entity\Request\DeleteSubscriptionRequest;
1112
use PhpList\RestBundle\Serializer\SubscriptionNormalizer;
1213
use PhpList\RestBundle\Service\Manager\SubscriptionManager;
1314
use PhpList\RestBundle\Validator\RequestValidator;
@@ -98,13 +99,68 @@ public function createSubscription(Request $request, SubscriptionNormalizer $ser
9899
{
99100
$this->requireAuthentication($request);
100101

101-
/** @var CreateSubscriptionRequest $subscriptionRequest */
102-
$subscriptionRequest = $this->validator->validate($request, CreateSubscriptionRequest::class);
102+
/** @var SubscriptionRequest $subscriptionRequest */
103+
$subscriptionRequest = $this->validator->validate($request, SubscriptionRequest::class);
103104
$subscription = $this->subscriptionManager->createSubscription(
104105
$subscriptionRequest->email,
105106
$subscriptionRequest->listId
106107
);
107108

108109
return new JsonResponse($serializer->normalize($subscription, 'json'), Response::HTTP_CREATED);
109110
}
111+
112+
#[Route('', name: 'delete_subscription', methods: ['DELETE'])]
113+
#[OA\Delete(
114+
path: '/subscriptions',
115+
description: 'Delete subscription.',
116+
summary: 'Delete subscription',
117+
requestBody: new OA\RequestBody(
118+
description: 'Pass session credentials',
119+
required: true,
120+
content: new OA\JsonContent(
121+
required: ['email', 'list_id'],
122+
properties: [
123+
new OA\Property(property: 'email', type: 'string', example: '[email protected]'),
124+
new OA\Property(property: 'list_id', type: 'integer', example: 2),
125+
]
126+
)
127+
),
128+
tags: ['subscriptions'],
129+
parameters: [
130+
new OA\Parameter(
131+
name: 'session',
132+
description: 'Session ID obtained from authentication',
133+
in: 'header',
134+
required: true,
135+
schema: new OA\Schema(type: 'string')
136+
),
137+
],
138+
responses: [
139+
new OA\Response(
140+
response: 204,
141+
description: 'Success',
142+
),
143+
new OA\Response(
144+
response: 403,
145+
description: 'Failure',
146+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
147+
),
148+
new OA\Response(
149+
response: 404,
150+
description: 'Not Found',
151+
)
152+
]
153+
)]
154+
public function deleteSubscriber(
155+
Request $request,
156+
): JsonResponse {
157+
$this->requireAuthentication($request);
158+
159+
/** @var SubscriptionRequest $subscriptionRequest */
160+
$subscriptionRequest = $this->validator->validate($request, SubscriptionRequest::class);
161+
162+
$this->subscriptionManager->deleteSubscription($subscriptionRequest->email, $subscriptionRequest->listId);
163+
164+
return new JsonResponse(null, Response::HTTP_NO_CONTENT);
165+
}
110166
}

src/Entity/Request/CreateSubscriptionRequest.php renamed to src/Entity/Request/SubscriptionRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use PhpList\RestBundle\Validator as CustomAssert;
88
use Symfony\Component\Validator\Constraints as Assert;
99

10-
class CreateSubscriptionRequest implements RequestInterface
10+
class SubscriptionRequest implements RequestInterface
1111
{
1212
#[Assert\NotBlank]
1313
#[Assert\Email]

src/EventListener/ExceptionListener.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpList\RestBundle\EventListener;
66

77
use Exception;
8+
use PhpList\RestBundle\Exception\SubscriptionCreationException;
89
use Symfony\Component\HttpFoundation\JsonResponse;
910
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
1011
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -27,6 +28,11 @@ public function onKernelException(ExceptionEvent $event): void
2728
'message' => $exception->getMessage(),
2829
], $exception->getStatusCode());
2930

31+
$event->setResponse($response);
32+
} elseif ($exception instanceof SubscriptionCreationException) {
33+
$response = new JsonResponse([
34+
'message' => $exception->getMessage(),
35+
], $exception->getStatusCode());
3036
$event->setResponse($response);
3137
} elseif ($exception instanceof Exception) {
3238
$response = new JsonResponse([

src/Exception/SubscriptionCreationException.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,16 @@
88

99
class SubscriptionCreationException extends RuntimeException
1010
{
11+
private int $statusCode;
12+
13+
public function __construct(string $message, int $statusCode)
14+
{
15+
parent::__construct($message);
16+
$this->statusCode = $statusCode;
17+
}
18+
19+
public function getStatusCode(): int
20+
{
21+
return $this->statusCode;
22+
}
1123
}

src/Service/Manager/SubscriptionManager.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ public function createSubscription(string $email, int $listId): Subscription
3232
$subscriberList = $this->subscriberListRepository->find($listId);
3333

3434
if (!$subscriber || !$subscriberList) {
35-
throw new SubscriptionCreationException('Subscriber or list does not exists.');
35+
throw new SubscriptionCreationException('Subscriber or list does not exists.', 404);
3636
}
3737

3838
$existingSubscription = $this->subscriptionRepository
3939
->findOneBySubscriberListAndSubscriber($subscriberList, $subscriber);
4040

4141
if ($existingSubscription) {
42-
throw new SubscriptionCreationException('Subscriber is already subscribed to this list.');
42+
throw new SubscriptionCreationException('Subscriber is already subscribed to this list.', 409);
4343
}
4444
$subscription = new Subscription();
4545
$subscription->setSubscriber($subscriber);
@@ -49,4 +49,15 @@ public function createSubscription(string $email, int $listId): Subscription
4949

5050
return $subscription;
5151
}
52+
53+
public function deleteSubscription(string $email, int $listId): void
54+
{
55+
$subscription = $this->subscriptionRepository->findOneBySubscriberEmailAndListId($listId, $email);
56+
57+
if (!$subscription) {
58+
throw new SubscriptionCreationException('Subscription not found for this subscriber and list.', 404);
59+
}
60+
61+
$this->subscriptionRepository->remove($subscription);
62+
}
5263
}

0 commit comments

Comments
 (0)