Skip to content

Commit a61147e

Browse files
committed
ISSUE-345: create subscription endpoint
1 parent c501c0e commit a61147e

16 files changed

+450
-58
lines changed

config/services/managers.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ services:
1515
PhpList\RestBundle\Service\Manager\SubscriberListManager:
1616
autowire: true
1717
autoconfigure: true
18+
19+
PhpList\RestBundle\Service\Manager\SubscriptionManager:
20+
autowire: true
21+
autoconfigure: true

config/services/normalizers.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ services:
22
_defaults:
33
autowire: true
44
autoconfigure: true
5-
public: false
65

76
Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter: ~
87

@@ -22,3 +21,7 @@ services:
2221
PhpList\RestBundle\Serializer\SubscriberListNormalizer:
2322
tags: [ 'serializer.normalizer' ]
2423
autowire: true
24+
25+
PhpList\RestBundle\Serializer\SubscriptionNormalizer:
26+
tags: [ 'serializer.normalizer' ]
27+
autowire: true

config/services/validators.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ services:
77
autowire: true
88
autoconfigure: true
99
tags: [ 'validator.constraint_validator' ]
10+
11+
PhpList\RestBundle\Validator\EmailExistsValidator:
12+
autowire: true
13+
autoconfigure: true
14+
tags: [ 'validator.constraint_validator' ]
15+
16+
PhpList\RestBundle\Validator\ListExistsValidator:
17+
autowire: true
18+
autoconfigure: true
19+
tags: [ 'validator.constraint_validator' ]

src/Controller/SessionController.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,7 @@ public function __construct(Authentication $authentication, SessionManager $sess
7171
new OA\Response(
7272
response: 400,
7373
description: 'Failure',
74-
content: new OA\JsonContent(
75-
properties: [
76-
new OA\Property(
77-
property: 'message',
78-
type: 'string',
79-
example: 'Empty json, invalid data and or incomplete data'
80-
)
81-
]
82-
)
74+
content: new OA\JsonContent(ref: '#/components/schemas/BadRequestResponse')
8375
),
8476
new OA\Response(
8577
response: 401,
@@ -103,7 +95,7 @@ public function createSession(
10395

10496
$json = $normalizer->normalize($token, 'json');
10597

106-
return new JsonResponse($json, Response::HTTP_CREATED, [], false);
98+
return new JsonResponse($json, Response::HTTP_CREATED);
10799
}
108100

109101
/**
@@ -164,6 +156,6 @@ public function deleteSession(
164156

165157
$this->sessionManager->deleteSession($token);
166158

167-
return new JsonResponse(null, Response::HTTP_NO_CONTENT, [], false);
159+
return new JsonResponse(null, Response::HTTP_NO_CONTENT);
168160
}
169161
}

src/Controller/SubscriberController.php

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,7 @@ public function __construct(Authentication $authentication, SubscriberManager $s
8181
new OA\Response(
8282
response: 409,
8383
description: 'Failure',
84-
content: new OA\JsonContent(
85-
properties: [
86-
new OA\Property(property: 'message', type: 'string', example: 'This resource already exists.')
87-
]
88-
)
84+
content: new OA\JsonContent(ref: '#/components/schemas/AlreadyExistsResponse')
8985
),
9086
new OA\Response(
9187
response: 422,
@@ -187,12 +183,7 @@ public function updateSubscriber(
187183
$validator->validateDto($dto);
188184
$subscriber = $this->subscriberManager->updateSubscriber($dto);
189185

190-
return new JsonResponse(
191-
$subscriberNormalizer->normalize($subscriber, 'json'),
192-
Response::HTTP_OK,
193-
[],
194-
false
195-
);
186+
return new JsonResponse($subscriberNormalizer->normalize($subscriber, 'json'), Response::HTTP_OK);
196187
}
197188

198189
#[Route('/{subscriberId}', name: 'get_subscriber_by_id', methods: ['GET'])]
@@ -240,12 +231,7 @@ public function getSubscriber(Request $request, int $subscriberId, SubscriberNor
240231

241232
$subscriber = $this->subscriberManager->getSubscriber($subscriberId);
242233

243-
return new JsonResponse(
244-
$serializer->normalize($subscriber, 'json'),
245-
Response::HTTP_OK,
246-
[],
247-
false
248-
);
234+
return new JsonResponse($serializer->normalize($subscriber), Response::HTTP_OK);
249235
}
250236

251237
#[Route('/{subscriberId}', name: 'delete_subscriber', requirements: ['subscriberId' => '\d+'], methods: ['DELETE'])]
@@ -294,11 +280,6 @@ public function deleteSubscriber(
294280

295281
$this->subscriberManager->deleteSubscriber($subscriber);
296282

297-
return new JsonResponse(
298-
null,
299-
Response::HTTP_NO_CONTENT,
300-
[],
301-
false
302-
);
283+
return new JsonResponse(null, Response::HTTP_NO_CONTENT);
303284
}
304285
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Controller;
6+
7+
use OpenApi\Attributes as OA;
8+
use PhpList\Core\Security\Authentication;
9+
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
10+
use PhpList\RestBundle\Entity\Request\CreateSubscriptionRequest;
11+
use PhpList\RestBundle\Serializer\SubscriptionNormalizer;
12+
use PhpList\RestBundle\Service\Manager\SubscriptionManager;
13+
use PhpList\RestBundle\Validator\RequestValidator;
14+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
15+
use Symfony\Component\HttpFoundation\JsonResponse;
16+
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\Response;
18+
use Symfony\Component\Routing\Attribute\Route;
19+
20+
/**
21+
* This controller provides REST API access to subscriptions.
22+
*
23+
* @author Tatevik Grigoryan <[email protected]>
24+
*/
25+
#[Route('/subscriptions')]
26+
class SubscriptionController extends AbstractController
27+
{
28+
use AuthenticationTrait;
29+
30+
private SubscriptionManager $subscriptionManager;
31+
private RequestValidator $validator;
32+
33+
public function __construct(
34+
Authentication $authentication,
35+
SubscriptionManager $subscriptionManager,
36+
RequestValidator $validator
37+
) {
38+
$this->authentication = $authentication;
39+
$this->subscriptionManager = $subscriptionManager;
40+
$this->validator = $validator;
41+
}
42+
43+
#[Route('', name: 'create_subscription', methods: ['POST'])]
44+
#[OA\Post(
45+
path: '/subscriptions',
46+
description: 'Subscribe subscriber to a list.',
47+
summary: 'Create subscription',
48+
requestBody: new OA\RequestBody(
49+
description: 'Pass session credentials',
50+
required: true,
51+
content: new OA\JsonContent(
52+
required: ['email', 'list_id'],
53+
properties: [
54+
new OA\Property(property: 'email', type: 'string', example: '[email protected]'),
55+
new OA\Property(property: 'list_id', type: 'integer', example: 2),
56+
]
57+
)
58+
),
59+
tags: ['subscriptions'],
60+
parameters: [
61+
new OA\Parameter(
62+
name: 'session',
63+
description: 'Session ID obtained from authentication',
64+
in: 'header',
65+
required: true,
66+
schema: new OA\Schema(type: 'string')
67+
)
68+
],
69+
responses: [
70+
new OA\Response(
71+
response: 201,
72+
description: 'Success',
73+
content: new OA\JsonContent(ref: '#/components/schemas/Subscription'),
74+
),
75+
new OA\Response(
76+
response: 403,
77+
description: 'Failure',
78+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
79+
),
80+
new OA\Response(
81+
response: 400,
82+
description: 'Failure',
83+
content: new OA\JsonContent(ref: '#/components/schemas/BadRequestResponse')
84+
),
85+
new OA\Response(
86+
response: 409,
87+
description: 'Failure',
88+
content: new OA\JsonContent(ref: '#/components/schemas/AlreadyExistsResponse')
89+
),
90+
new OA\Response(
91+
response: 422,
92+
description: 'Failure',
93+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
94+
),
95+
]
96+
)]
97+
public function createSubscription(Request $request, SubscriptionNormalizer $serializer): JsonResponse
98+
{
99+
$this->requireAuthentication($request);
100+
101+
/** @var CreateSubscriptionRequest $subscriptionRequest */
102+
$subscriptionRequest = $this->validator->validate($request, CreateSubscriptionRequest::class);
103+
$subscription = $this->subscriptionManager->createSubscription(
104+
$subscriptionRequest->email,
105+
$subscriptionRequest->listId
106+
);
107+
108+
return new JsonResponse($serializer->normalize($subscription, 'json'), Response::HTTP_CREATED);
109+
}
110+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Entity\Request;
6+
7+
use PhpList\RestBundle\Validator as CustomAssert;
8+
use Symfony\Component\Validator\Constraints as Assert;
9+
10+
class CreateSubscriptionRequest implements RequestInterface
11+
{
12+
#[Assert\NotBlank]
13+
#[Assert\Email]
14+
#[CustomAssert\EmailExists]
15+
public string $email;
16+
17+
#[Assert\NotBlank]
18+
#[Assert\NotNull]
19+
#[CustomAssert\ListExists]
20+
public int $listId;
21+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Exception;
6+
7+
use RuntimeException;
8+
9+
class SubscriptionCreationException extends RuntimeException
10+
{
11+
}
Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,6 @@
4747
],
4848
type: 'object'
4949
)]
50-
#[OA\Schema(
51-
schema: 'UnauthorizedResponse',
52-
properties: [
53-
new OA\Property(
54-
property: 'message',
55-
type: 'string',
56-
example: 'No valid session key was provided as basic auth password.'
57-
)
58-
],
59-
type: 'object'
60-
)]
61-
#[OA\Schema(
62-
schema: 'ValidationErrorResponse',
63-
properties: [
64-
new OA\Property(
65-
property: 'message',
66-
type: 'string',
67-
example: 'Some fields invalid: email, confirmed, html_email'
68-
)
69-
],
70-
type: 'object'
71-
)]
72-
class SwaggerSchemas
50+
class SwaggerSchemasEntity
7351
{
7452
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\OpenApi;
6+
7+
use OpenApi\Attributes as OA;
8+
9+
#[OA\Schema(
10+
schema: 'UnauthorizedResponse',
11+
properties: [
12+
new OA\Property(
13+
property: 'message',
14+
type: 'string',
15+
example: 'No valid session key was provided as basic auth password.'
16+
)
17+
],
18+
type: 'object'
19+
)]
20+
#[OA\Schema(
21+
schema: 'ValidationErrorResponse',
22+
properties: [
23+
new OA\Property(
24+
property: 'message',
25+
type: 'string',
26+
example: 'Some fields invalid: email, confirmed, html_email'
27+
)
28+
],
29+
type: 'object'
30+
)]
31+
#[OA\Schema(
32+
schema: 'BadRequestResponse',
33+
properties: [
34+
new OA\Property(
35+
property: 'message',
36+
type: 'string',
37+
example: 'Invalid json format'
38+
)
39+
],
40+
type: 'object'
41+
)]
42+
#[OA\Schema(
43+
schema: 'AlreadyExistsResponse',
44+
properties: [
45+
new OA\Property(
46+
property: 'message',
47+
type: 'string',
48+
example: 'This resource already exists.'
49+
)
50+
],
51+
type: 'object'
52+
)]
53+
class SwaggerSchemasResponse
54+
{
55+
}

0 commit comments

Comments
 (0)