Skip to content

Commit 3b95468

Browse files
committed
Add: getPublicPage endpoint
1 parent 66ecaa9 commit 3b95468

4 files changed

Lines changed: 160 additions & 5 deletions

File tree

src/Subscription/Controller/SubscribePageController.php

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PhpList\RestBundle\Common\Validator\RequestValidator;
1717
use PhpList\RestBundle\Subscription\Request\SubscribePageRequest;
1818
use PhpList\RestBundle\Subscription\Serializer\SubscribePageNormalizer;
19+
use PhpList\RestBundle\Subscription\Serializer\SubscribePagePublicNormalizer;
1920
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
2021
use Symfony\Component\HttpFoundation\JsonResponse;
2122
use Symfony\Component\HttpFoundation\Request;
@@ -153,16 +154,58 @@ className: SubscribePage::class,
153154
)]
154155
public function getPage(Request $request): JsonResponse
155156
{
156-
$admin = $this->authentication->authenticateByApiKey($request);
157-
$page = $this->subscribePageManager->findPage(id: (int) $request->get('id'));
157+
$admin = $this->requireAuthentication($request);
158+
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
159+
throw $this->createAccessDeniedException('You are not allowed to view subscribe pages.');
160+
}
158161

159-
if (!$page || ($page->isActive() === false && $admin === null)) {
162+
$page = $this->subscribePageManager->findPage(id: (int) $request->get('id'));
163+
if (!$page) {
160164
throw $this->createNotFoundException('Subscribe page not found');
161165
}
162166

163167
return $this->json($this->normalizer->normalize($page), Response::HTTP_OK);
164168
}
165169

170+
#[Route('/{id}/public', name: 'get_public', requirements: ['id' => '\\d+'], methods: ['GET'])]
171+
#[OA\Get(
172+
path: '/api/v2/subscribe-pages/{id}/public',
173+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production.',
174+
summary: 'Get public subscribe page (placeholders replaced with actual values)',
175+
tags: ['subscriptions'],
176+
parameters: [
177+
new OA\Parameter(
178+
name: 'id',
179+
description: 'Subscribe page ID',
180+
in: 'path',
181+
required: true,
182+
schema: new OA\Schema(type: 'integer')
183+
)
184+
],
185+
responses: [
186+
new OA\Response(
187+
response: 200,
188+
description: 'Success',
189+
content: new OA\JsonContent(ref: '#/components/schemas/SubscribePagePublic'),
190+
),
191+
new OA\Response(
192+
response: 404,
193+
description: 'Not Found',
194+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
195+
),
196+
]
197+
)]
198+
public function getPublicPage(Request $request, SubscribePagePublicNormalizer $normalizer): JsonResponse
199+
{
200+
$page = $this->subscribePageManager->findPublicPage(id: (int) $request->get('id'));
201+
202+
if (!$page || $page->isActive() === false) {
203+
throw $this->createNotFoundException('Subscribe page not found');
204+
}
205+
206+
return $this->json($normalizer->normalize($page), Response::HTTP_OK);
207+
}
208+
166209
#[Route('', name: 'create', methods: ['POST'])]
167210
#[OA\Post(
168211
path: '/api/v2/subscribe-pages',
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\SubscribePage;
9+
use PhpList\Core\Domain\Subscription\Model\SubscribePageData;
10+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
11+
12+
#[OA\Schema(
13+
schema: 'SubscribePagePublic',
14+
properties: [
15+
new OA\Property(property: 'id', type: 'integer', example: 1),
16+
new OA\Property(property: 'title', type: 'string', example: 'Subscribe to our newsletter'),
17+
new OA\Property(
18+
property: 'data',
19+
type: 'array',
20+
items: new OA\Items(
21+
type: 'object',
22+
additionalProperties: new OA\AdditionalProperties(
23+
type: 'string'
24+
)
25+
)
26+
),
27+
],
28+
)]
29+
class SubscribePagePublicNormalizer implements NormalizerInterface
30+
{
31+
/**
32+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
33+
*/
34+
public function normalize($object, string $format = null, array $context = []): array
35+
{
36+
if (!$object instanceof SubscribePage) {
37+
return [];
38+
}
39+
40+
return [
41+
'id' => $object->getId(),
42+
'title' => $object->getTitle(),
43+
'data' => array_reduce(
44+
$object->getData(),
45+
function (array $carry, SubscribePageData $data) {
46+
$carry[$data->getName()] = $data->getData();
47+
return $carry;
48+
},
49+
[]
50+
),
51+
];
52+
}
53+
54+
/**
55+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
56+
*/
57+
public function supportsNormalization($data, string $format = null): bool
58+
{
59+
return $data instanceof SubscribePage;
60+
}
61+
}

tests/Integration/Subscription/Controller/SubscribePageControllerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ public function testControllerIsAvailableViaContainer(): void
2020
);
2121
}
2222

23-
public function testGetSubscribePageWithoutSessionReturnsPageIfItIsActive(): void
23+
public function testGetSubscribePageWithoutSessionReturnsForbidden(): void
2424
{
2525
$this->loadFixtures([AdministratorFixture::class, SubscribePageFixture::class]);
2626

2727
self::getClient()->request('GET', '/api/v2/subscribe-pages/1');
28-
$this->assertHttpOkay();
28+
$this->assertHttpForbidden();
2929
}
3030

3131
public function testGetSubscribePageWithSessionReturnsPage(): void
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Unit\Subscription\Serializer;
6+
7+
use PhpList\Core\Domain\Identity\Model\Administrator;
8+
use PhpList\Core\Domain\Subscription\Model\SubscribePage;
9+
use PhpList\RestBundle\Subscription\Serializer\SubscribePagePublicNormalizer;
10+
use PHPUnit\Framework\TestCase;
11+
use stdClass;
12+
13+
class SubscribePagePublicNormalizerTest extends TestCase
14+
{
15+
public function testSupportsNormalization(): void
16+
{
17+
$normalizer = new SubscribePagePublicNormalizer();
18+
19+
$page = $this->createMock(SubscribePage::class);
20+
21+
$this->assertTrue($normalizer->supportsNormalization($page));
22+
$this->assertFalse($normalizer->supportsNormalization(new stdClass()));
23+
}
24+
25+
public function testNormalizeReturnsExpectedArray(): void
26+
{
27+
$owner = $this->createMock(Administrator::class);
28+
29+
$page = $this->createMock(SubscribePage::class);
30+
$page->method('getId')->willReturn(42);
31+
$page->method('getTitle')->willReturn('welcome@example.org');
32+
$page->method('isActive')->willReturn(true);
33+
$page->method('getOwner')->willReturn($owner);
34+
35+
$normalizer = new SubscribePagePublicNormalizer();
36+
37+
$expected = [
38+
'id' => 42,
39+
'title' => 'welcome@example.org',
40+
'data' => [],
41+
];
42+
43+
$this->assertSame($expected, $normalizer->normalize($page));
44+
}
45+
46+
public function testNormalizeWithInvalidObjectReturnsEmptyArray(): void
47+
{
48+
$normalizer = new SubscribePagePublicNormalizer();
49+
$this->assertSame([], $normalizer->normalize(new stdClass()));
50+
}
51+
}

0 commit comments

Comments
 (0)