Skip to content

Commit 9377cb5

Browse files
committed
ISSUE-345: subscriber attribute relation
1 parent 425a35b commit 9377cb5

File tree

4 files changed

+355
-14
lines changed

4 files changed

+355
-14
lines changed

src/Subscription/Controller/ListMembersController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function __construct(
5555
description: 'List ID',
5656
in: 'path',
5757
required: true,
58-
schema: new OA\Schema(type: 'string')
58+
schema: new OA\Schema(type: 'integer')
5959
),
6060
new OA\Parameter(
6161
name: 'after_id',
Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Subscription\Controller;
6+
7+
use OpenApi\Attributes as OA;
8+
use PhpList\Core\Domain\Subscription\Model\Filter\SubscriberAttributeValueFilter;
9+
use PhpList\Core\Domain\Subscription\Model\Subscriber;
10+
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeDefinition;
11+
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeValue;
12+
use PhpList\Core\Domain\Subscription\Service\SubscriberAttributeManager;
13+
use PhpList\Core\Security\Authentication;
14+
use PhpList\RestBundle\Common\Controller\BaseController;
15+
use PhpList\RestBundle\Common\Service\Provider\PaginatedDataProvider;
16+
use PhpList\RestBundle\Common\Validator\RequestValidator;
17+
use PhpList\RestBundle\Subscription\Serializer\SubscriberAttributeValueNormalizer;
18+
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
19+
use Symfony\Component\HttpFoundation\JsonResponse;
20+
use Symfony\Component\HttpFoundation\Request;
21+
use Symfony\Component\HttpFoundation\Response;
22+
use Symfony\Component\Routing\Attribute\Route;
23+
24+
#[Route('/subscriber/attribute-values')]
25+
class SubscriberAttributeController extends BaseController
26+
{
27+
private SubscriberAttributeManager $attributeManager;
28+
private SubscriberAttributeValueNormalizer $normalizer;
29+
private PaginatedDataProvider $paginatedDataProvider;
30+
31+
public function __construct(
32+
Authentication $authentication,
33+
RequestValidator $validator,
34+
SubscriberAttributeManager $attributeManager,
35+
SubscriberAttributeValueNormalizer $normalizer,
36+
PaginatedDataProvider $paginatedDataProvider
37+
) {
38+
parent::__construct($authentication, $validator);
39+
$this->attributeManager = $attributeManager;
40+
$this->normalizer = $normalizer;
41+
$this->paginatedDataProvider = $paginatedDataProvider;
42+
}
43+
44+
#[Route('/{subscriberId}/{definitionId}', name: 'create_subscriber_attribute_value', methods: ['POST', 'PUT'])]
45+
#[OA\Post(
46+
path: '/subscriber/attribute-values/{subscriberId}/{definitionId}',
47+
description: 'Returns created/updated subscriber attribute.',
48+
summary: 'Create/update a subscriber attribute.',
49+
requestBody: new OA\RequestBody(
50+
description: 'Pass parameters to create subscriber attribute.',
51+
required: true,
52+
content: new OA\JsonContent(
53+
properties: [
54+
new OA\Property(property: 'value', type: 'string', example: 'United States'),
55+
]
56+
)
57+
),
58+
tags: ['subscriber-attributes'],
59+
parameters: [
60+
new OA\Parameter(
61+
name: 'session',
62+
description: 'Session ID obtained from authentication',
63+
in: 'header',
64+
required: true,
65+
schema: new OA\Schema(type: 'string')
66+
),
67+
new OA\Parameter(
68+
name: 'definitionId',
69+
description: 'attribute definition id',
70+
in: 'path',
71+
required: true,
72+
schema: new OA\Schema(type: 'integer')
73+
),
74+
new OA\Parameter(
75+
name: 'subscriberId',
76+
description: 'Subscriber id',
77+
in: 'path',
78+
required: true,
79+
schema: new OA\Schema(type: 'integer')
80+
),
81+
],
82+
responses: [
83+
new OA\Response(
84+
response: 201,
85+
description: 'Success',
86+
content: new OA\JsonContent(ref: '#/components/schemas/SubscriberAttributeValue')
87+
),
88+
new OA\Response(
89+
response: 403,
90+
description: 'Failure',
91+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
92+
),
93+
new OA\Response(
94+
response: 422,
95+
description: 'Failure',
96+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
97+
),
98+
]
99+
)]
100+
public function createOrUpdate(
101+
Request $request,
102+
#[MapEntity(mapping: ['definitionId' => 'id'])] ?SubscriberAttributeDefinition $definition = null,
103+
#[MapEntity(mapping: ['subscriberId' => 'id'])] ?Subscriber $subscriber = null,
104+
): JsonResponse {
105+
$this->requireAuthentication($request);
106+
107+
if (!$definition) {
108+
throw $this->createNotFoundException('Attribute definition not found.');
109+
}
110+
if (!$subscriber) {
111+
throw $this->createNotFoundException('Subscriber not found.');
112+
}
113+
114+
$attributeDefinition = $this->attributeManager->createOrUpdate(
115+
subscriber:$subscriber,
116+
definition: $definition,
117+
value: $request->get('value')
118+
);
119+
$json = $this->normalizer->normalize($attributeDefinition, 'json');
120+
121+
return $this->json($json, Response::HTTP_CREATED);
122+
}
123+
124+
#[Route('/{subscriberId}/{definitionId}', name: 'delete_subscriber_attribute', methods: ['DELETE'])]
125+
#[OA\Delete(
126+
path: '/subscriber/attribute-values/{subscriberId}/{definitionId}',
127+
description: 'Deletes a single subscriber attribute.',
128+
summary: 'Deletes an attribute.',
129+
tags: ['subscriber-attributes'],
130+
parameters: [
131+
new OA\Parameter(
132+
name: 'session',
133+
description: 'Session ID',
134+
in: 'header',
135+
required: true,
136+
schema: new OA\Schema(type: 'string')
137+
),
138+
new OA\Parameter(
139+
name: 'definitionId',
140+
description: 'attribute definition id',
141+
in: 'path',
142+
required: true,
143+
schema: new OA\Schema(type: 'integer')
144+
),
145+
new OA\Parameter(
146+
name: 'subscriberId',
147+
description: 'Subscriber id',
148+
in: 'path',
149+
required: true,
150+
schema: new OA\Schema(type: 'integer')
151+
),
152+
],
153+
responses: [
154+
new OA\Response(
155+
response: 200,
156+
description: 'Success'
157+
),
158+
new OA\Response(
159+
response: 403,
160+
description: 'Failure',
161+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
162+
),
163+
new OA\Response(
164+
response: 404,
165+
description: 'Failure',
166+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
167+
)
168+
]
169+
)]
170+
public function delete(
171+
Request $request,
172+
#[MapEntity(mapping: ['definitionId' => 'id'])] ?SubscriberAttributeDefinition $definition = null,
173+
#[MapEntity(mapping: ['subscriberId' => 'id'])] ?Subscriber $subscriber = null,
174+
): JsonResponse {
175+
$this->requireAuthentication($request);
176+
if (!$definition || !$subscriber) {
177+
throw $this->createNotFoundException('Subscriber attribute not found.');
178+
}
179+
$attribute = $this->attributeManager->getSubscriberAttribute($definition->getId(), $subscriber->getId());
180+
$this->attributeManager->delete($attribute);
181+
182+
return $this->json(null, Response::HTTP_NO_CONTENT);
183+
}
184+
185+
#[Route('/{subscriberId}', name: 'get_subscriber_attributes', methods: ['GET'])]
186+
#[OA\Get(
187+
path: '/subscriber/attribute-values/{subscriberId}',
188+
description: 'Returns a JSON list of all subscriber attributes.',
189+
summary: 'Gets a list of all subscriber attributes.',
190+
tags: ['subscriber-attributes'],
191+
parameters: [
192+
new OA\Parameter(
193+
name: 'session',
194+
description: 'Session ID obtained from authentication',
195+
in: 'header',
196+
required: true,
197+
schema: new OA\Schema(type: 'string')
198+
),
199+
new OA\Parameter(
200+
name: 'subscriberId',
201+
description: 'Subscriber id',
202+
in: 'path',
203+
required: true,
204+
schema: new OA\Schema(type: 'integer')
205+
),
206+
new OA\Parameter(
207+
name: 'after_id',
208+
description: 'Last id (starting from 0)',
209+
in: 'query',
210+
required: false,
211+
schema: new OA\Schema(type: 'integer', default: 1, minimum: 1)
212+
),
213+
new OA\Parameter(
214+
name: 'limit',
215+
description: 'Number of results per page',
216+
in: 'query',
217+
required: false,
218+
schema: new OA\Schema(type: 'integer', default: 25, maximum: 100, minimum: 1)
219+
)
220+
],
221+
responses: [
222+
new OA\Response(
223+
response: 200,
224+
description: 'Success',
225+
content: new OA\JsonContent(
226+
properties: [
227+
new OA\Property(
228+
property: 'items',
229+
type: 'array',
230+
items: new OA\Items(ref: '#/components/schemas/SubscriberAttributeValue')
231+
),
232+
new OA\Property(property: 'pagination', ref: '#/components/schemas/CursorPagination')
233+
],
234+
type: 'object'
235+
)
236+
),
237+
new OA\Response(
238+
response: 403,
239+
description: 'Failure',
240+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
241+
)
242+
]
243+
)]
244+
public function getPaginated(Request $request): JsonResponse
245+
{
246+
$this->requireAuthentication($request);
247+
$filter = (new SubscriberAttributeValueFilter())->setSubscriberId($request->query->getInt('subscriberId'));
248+
249+
return $this->json(
250+
$this->paginatedDataProvider->getPaginatedList(
251+
$request,
252+
$this->normalizer,
253+
SubscriberAttributeValue::class,
254+
$filter
255+
),
256+
Response::HTTP_OK
257+
);
258+
}
259+
260+
#[Route('/{subscriberId}/{definitionId}', name: 'get_subscriber_attribute', methods: ['GET'])]
261+
#[OA\Get(
262+
path: '/subscriber/attribute-values/{subscriberId}/{definitionId}',
263+
description: 'Returns a single attribute.',
264+
summary: 'Gets subscriber attribute.',
265+
tags: ['subscriber-attributes'],
266+
parameters: [
267+
new OA\Parameter(
268+
name: 'definitionId',
269+
description: 'attribute definition id',
270+
in: 'path',
271+
required: true,
272+
schema: new OA\Schema(type: 'integer')
273+
),
274+
new OA\Parameter(
275+
name: 'subscriberId',
276+
description: 'Subscriber id',
277+
in: 'path',
278+
required: true,
279+
schema: new OA\Schema(type: 'integer')
280+
),
281+
new OA\Parameter(
282+
name: 'session',
283+
description: 'Session ID obtained from authentication',
284+
in: 'header',
285+
required: true,
286+
schema: new OA\Schema(type: 'string')
287+
)
288+
],
289+
responses: [
290+
new OA\Response(
291+
response: 200,
292+
description: 'Success',
293+
content: new OA\JsonContent(ref: '#/components/schemas/SubscriberAttributeValue')
294+
),
295+
new OA\Response(
296+
response: 403,
297+
description: 'Failure',
298+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
299+
),
300+
new OA\Response(
301+
response: 404,
302+
description: 'Failure',
303+
content: new OA\JsonContent(
304+
properties: [
305+
new OA\Property(
306+
property: 'message',
307+
type: 'string',
308+
example: 'There is no attribute with that ID.'
309+
)
310+
],
311+
type: 'object'
312+
)
313+
)
314+
]
315+
)]
316+
public function getAttributeDefinition(
317+
Request $request,
318+
#[MapEntity(mapping: ['subscriberId' => 'id'])] ?SubscriberAttributeDefinition $subscriber,
319+
#[MapEntity(mapping: ['definitionId' => 'id'])] ?SubscriberAttributeDefinition $definition,
320+
): JsonResponse {
321+
$this->requireAuthentication($request);
322+
if (!$definition || !$subscriber) {
323+
throw $this->createNotFoundException('Subscriber attribute not found.');
324+
}
325+
$attribute = $this->attributeManager->getSubscriberAttribute($definition->getId(), $subscriber->getId());
326+
$this->attributeManager->delete($attribute);
327+
328+
return $this->json(
329+
$this->normalizer->normalize($attribute),
330+
Response::HTTP_OK
331+
);
332+
}
333+
}

0 commit comments

Comments
 (0)