Skip to content

Commit 529d3e7

Browse files
committed
Add support for subscribe page data management and validation
1 parent 112abce commit 529d3e7

6 files changed

Lines changed: 178 additions & 167 deletions

File tree

src/Subscription/Controller/SubscribePageController.php

Lines changed: 33 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PhpList\RestBundle\Common\Controller\BaseController;
1515
use PhpList\RestBundle\Common\Service\Provider\PaginatedDataProvider;
1616
use PhpList\RestBundle\Common\Validator\RequestValidator;
17-
use PhpList\RestBundle\Subscription\Request\SubscribePageDataRequest;
1817
use PhpList\RestBundle\Subscription\Request\SubscribePageRequest;
1918
use PhpList\RestBundle\Subscription\Serializer\SubscribePageNormalizer;
2019
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
@@ -152,14 +151,12 @@ className: SubscribePage::class,
152151
),
153152
]
154153
)]
155-
public function getPage(
156-
Request $request,
157-
#[MapEntity(mapping: ['id' => 'id'])] ?SubscribePage $page = null
158-
): JsonResponse {
154+
public function getPage(Request $request): JsonResponse {
159155
$admin = $this->requireAuthentication($request);
160156
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
161157
throw $this->createAccessDeniedException('You are not allowed to view subscribe pages.');
162158
}
159+
$page = $this->subscribePageManager->findPage(id: (int) $request->get('id'));
163160

164161
if (!$page) {
165162
throw $this->createNotFoundException('Subscribe page not found');
@@ -179,6 +176,18 @@ public function getPage(
179176
properties: [
180177
new OA\Property(property: 'title', type: 'string'),
181178
new OA\Property(property: 'active', type: 'boolean', nullable: true),
179+
new OA\Property(
180+
property: 'data',
181+
type: 'array',
182+
items: new OA\Items(
183+
properties: [
184+
new OA\Property(property: 'key', type: 'string'),
185+
new OA\Property(property: 'value', type: 'string'),
186+
],
187+
type: 'object'
188+
),
189+
nullable: true
190+
),
182191
]
183192
)
184193
),
@@ -221,6 +230,10 @@ public function createPage(Request $request): JsonResponse
221230
$createRequest = $this->validator->validate($request, SubscribePageRequest::class);
222231

223232
$page = $this->subscribePageManager->createPage($createRequest->title, $createRequest->active, $admin);
233+
if ($createRequest->hasData()) {
234+
$this->entityManager->flush();
235+
$this->subscribePageManager->syncPageData($createRequest->getDataMap(), $page);
236+
}
224237
$this->entityManager->flush();
225238

226239
return $this->json($this->normalizer->normalize($page), Response::HTTP_CREATED);
@@ -237,6 +250,18 @@ public function createPage(Request $request): JsonResponse
237250
properties: [
238251
new OA\Property(property: 'title', type: 'string', nullable: true),
239252
new OA\Property(property: 'active', type: 'boolean', nullable: true),
253+
new OA\Property(
254+
property: 'data',
255+
type: 'array',
256+
items: new OA\Items(
257+
properties: [
258+
new OA\Property(property: 'key', type: 'string'),
259+
new OA\Property(property: 'value', type: 'string'),
260+
],
261+
type: 'object'
262+
),
263+
nullable: true
264+
),
240265
]
241266
)
242267
),
@@ -297,6 +322,9 @@ public function updatePage(
297322
active: $updateRequest->active,
298323
owner: $admin,
299324
);
325+
if ($updateRequest->hasData()) {
326+
$this->subscribePageManager->syncPageData(data: $updateRequest->getDataMap(), page: $page);
327+
}
300328
$this->entityManager->flush();
301329

302330
return $this->json($this->normalizer->normalize($updated), Response::HTTP_OK);
@@ -356,162 +384,4 @@ public function deletePage(
356384

357385
return $this->json(null, Response::HTTP_NO_CONTENT);
358386
}
359-
360-
#[Route('/{id}/data', name: 'get_data', requirements: ['id' => '\\d+'], methods: ['GET'])]
361-
#[OA\Get(
362-
path: '/api/v2/subscribe-pages/{id}/data',
363-
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production.',
364-
summary: 'Get subscribe page data',
365-
tags: ['subscriptions'],
366-
parameters: [
367-
new OA\Parameter(
368-
name: 'php-auth-pw',
369-
description: 'Session key obtained from login',
370-
in: 'header',
371-
required: true,
372-
schema: new OA\Schema(type: 'string')
373-
),
374-
new OA\Parameter(
375-
name: 'id',
376-
description: 'Subscribe page ID',
377-
in: 'path',
378-
required: true,
379-
schema: new OA\Schema(type: 'integer')
380-
)
381-
],
382-
responses: [
383-
new OA\Response(
384-
response: 200,
385-
description: 'Success',
386-
content: new OA\JsonContent(
387-
type: 'array',
388-
items: new OA\Items(
389-
properties: [
390-
new OA\Property(property: 'id', type: 'integer'),
391-
new OA\Property(property: 'name', type: 'string'),
392-
new OA\Property(property: 'data', type: 'string', nullable: true),
393-
],
394-
type: 'object'
395-
)
396-
)
397-
),
398-
new OA\Response(
399-
response: 403,
400-
description: 'Failure',
401-
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
402-
),
403-
new OA\Response(
404-
response: 404,
405-
description: 'Not Found',
406-
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
407-
)
408-
]
409-
)]
410-
public function getPageData(
411-
Request $request,
412-
#[MapEntity(mapping: ['id' => 'id'])] ?SubscribePage $page = null
413-
): JsonResponse {
414-
$admin = $this->requireAuthentication($request);
415-
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
416-
throw $this->createAccessDeniedException('You are not allowed to view subscribe page data.');
417-
}
418-
419-
if (!$page) {
420-
throw $this->createNotFoundException('Subscribe page not found');
421-
}
422-
423-
$data = $this->subscribePageManager->getPageData($page);
424-
425-
$json = array_map(static function ($item) {
426-
return [
427-
'id' => $item->getId(),
428-
'name' => $item->getName(),
429-
'data' => $item->getData(),
430-
];
431-
}, $data);
432-
433-
return $this->json($json, Response::HTTP_OK);
434-
}
435-
436-
#[Route('/{id}/data', name: 'set_data', requirements: ['id' => '\\d+'], methods: ['PUT'])]
437-
#[OA\Put(
438-
path: '/api/v2/subscribe-pages/{id}/data',
439-
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production.',
440-
summary: 'Set subscribe page data item',
441-
requestBody: new OA\RequestBody(
442-
required: true,
443-
content: new OA\JsonContent(
444-
properties: [
445-
new OA\Property(property: 'name', type: 'string'),
446-
new OA\Property(property: 'value', type: 'string', nullable: true),
447-
]
448-
)
449-
),
450-
tags: ['subscriptions'],
451-
parameters: [
452-
new OA\Parameter(
453-
name: 'php-auth-pw',
454-
description: 'Session key obtained from login',
455-
in: 'header',
456-
required: true,
457-
schema: new OA\Schema(type: 'string')
458-
),
459-
new OA\Parameter(
460-
name: 'id',
461-
description: 'Subscribe page ID',
462-
in: 'path',
463-
required: true,
464-
schema: new OA\Schema(type: 'integer')
465-
)
466-
],
467-
responses: [
468-
new OA\Response(
469-
response: 200,
470-
description: 'Success',
471-
content: new OA\JsonContent(
472-
properties: [
473-
new OA\Property(property: 'id', type: 'integer'),
474-
new OA\Property(property: 'name', type: 'string'),
475-
new OA\Property(property: 'data', type: 'string', nullable: true),
476-
],
477-
type: 'object'
478-
)
479-
),
480-
new OA\Response(
481-
response: 403,
482-
description: 'Failure',
483-
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
484-
),
485-
new OA\Response(
486-
response: 404,
487-
description: 'Not Found',
488-
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
489-
)
490-
]
491-
)]
492-
public function setPageData(
493-
Request $request,
494-
#[MapEntity(mapping: ['id' => 'id'])] ?SubscribePage $page = null
495-
): JsonResponse {
496-
$admin = $this->requireAuthentication($request);
497-
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
498-
throw $this->createAccessDeniedException('You are not allowed to update subscribe page data.');
499-
}
500-
501-
if (!$page) {
502-
throw $this->createNotFoundException('Subscribe page not found');
503-
}
504-
505-
/** @var SubscribePageDataRequest $createRequest */
506-
$createRequest = $this->validator->validate($request, SubscribePageDataRequest::class);
507-
508-
$item = $this->subscribePageManager->setPageData($page, $createRequest->name, $createRequest->value);
509-
$this->entityManager->flush();
510-
511-
return $this->json([
512-
'id' => $item->getId(),
513-
'name' => $item->getName(),
514-
'data' => $item->getData(),
515-
], Response::HTTP_OK);
516-
}
517387
}

src/Subscription/Request/SubscribePageRequest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,61 @@ class SubscribePageRequest implements RequestInterface
1616
#[Assert\Type(type: 'bool')]
1717
public bool $active = false;
1818

19+
/**
20+
* @var array<int, array{key: string, value: ?string}>|null
21+
*/
22+
#[Assert\Type(type: 'array')]
23+
#[Assert\All(constraints: [
24+
new Assert\Collection(
25+
fields: [
26+
'key' => new Assert\Required([
27+
new Assert\NotBlank(),
28+
new Assert\Type(type: 'string'),
29+
]),
30+
'value' => new Assert\Required([
31+
new Assert\Type(type: 'string'),
32+
]),
33+
],
34+
allowExtraFields: false,
35+
allowMissingFields: false
36+
),
37+
])]
38+
private ?array $data = null;
39+
40+
private bool $dataProvided = false;
41+
42+
public function setData(?array $data): void
43+
{
44+
$this->data = $data;
45+
$this->dataProvided = true;
46+
}
47+
48+
public function hasData(): bool
49+
{
50+
return $this->dataProvided;
51+
}
52+
53+
/** @return array<int, array{key: string, value: ?string}>|null */
54+
public function getData(): ?array
55+
{
56+
return $this->data;
57+
}
58+
59+
/** @return array<string, ?string> */
60+
public function getDataMap(): array
61+
{
62+
if ($this->data === null) {
63+
return [];
64+
}
65+
66+
$result = [];
67+
foreach ($this->data as $item) {
68+
$result[$item['key']] = $item['value'];
69+
}
70+
71+
return $result;
72+
}
73+
1974
public function getDto(): SubscribePageRequest
2075
{
2176
return $this;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Subscription\Serializer;
6+
7+
use OpenApi\Attributes as OA;
8+
use PhpList\Core\Domain\Subscription\Model\SubscribePageData;
9+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
10+
11+
#[OA\Schema(
12+
schema: 'SubscribePageData',
13+
properties: [
14+
new OA\Property(property: 'key', type: 'string', example: 'button'),
15+
new OA\Property(property: 'value', type: 'string', example: 'Subscribe to the selected newsletters'),
16+
],
17+
)]
18+
class SubscribePageDataNormalizer implements NormalizerInterface
19+
{
20+
/**
21+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
22+
*/
23+
public function normalize($object, string $format = null, array $context = []): array
24+
{
25+
if (!$object instanceof SubscribePageData) {
26+
return [];
27+
}
28+
29+
return [
30+
'key' => $object->getName(),
31+
'value' => $object->getData(),
32+
];
33+
}
34+
35+
/**
36+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
37+
*/
38+
public function supportsNormalization($data, string $format = null): bool
39+
{
40+
return $data instanceof SubscribePageData;
41+
}
42+
}

src/Subscription/Serializer/SubscribePageNormalizer.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
new OA\Property(property: 'title', type: 'string', example: 'Subscribe to our newsletter'),
1717
new OA\Property(property: 'active', type: 'boolean', example: true),
1818
new OA\Property(property: 'owner', ref: '#/components/schemas/Administrator'),
19+
new OA\Property(
20+
property: 'data',
21+
type: 'array',
22+
items: new OA\Items(ref: '#/components/schemas/SubscribePageData')
23+
),
1924
],
2025
)]
2126
class SubscribePageNormalizer implements NormalizerInterface
2227
{
2328
public function __construct(
2429
private readonly AdministratorNormalizer $adminNormalizer,
30+
private readonly SubscribePageDataNormalizer $dataNormalizer,
2531
) {
2632
}
2733

@@ -39,6 +45,9 @@ public function normalize($object, string $format = null, array $context = []):
3945
'title' => $object->getTitle(),
4046
'active' => $object->isActive(),
4147
'owner' => $this->adminNormalizer->normalize($object->getOwner()),
48+
'data' => array_map(function ($data) {
49+
return $this->dataNormalizer->normalize($data);
50+
}, $object->getData())
4251
];
4352
}
4453

0 commit comments

Comments
 (0)