Skip to content

Commit fcde98c

Browse files
committed
Add BounceRegexController
1 parent 3b839be commit fcde98c

File tree

13 files changed

+546
-7
lines changed

13 files changed

+546
-7
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
},
3737
"require": {
3838
"php": "^8.1",
39-
"phplist/core": "dev-subscribepage",
39+
"phplist/core": "dev-bounceregex",
4040
"friendsofsymfony/rest-bundle": "*",
4141
"symfony/test-pack": "^1.0",
4242
"symfony/process": "^6.4",

config/services/managers.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,19 @@ services:
2020
autowire: true
2121
autoconfigure: true
2222

23-
PhpList\Core\Domain\Messaging\Service\MessageManager:
23+
PhpList\Core\Domain\Messaging\Service\Manager\MessageManager:
2424
autowire: true
2525
autoconfigure: true
2626

27-
PhpList\Core\Domain\Messaging\Service\TemplateManager:
27+
PhpList\Core\Domain\Messaging\Service\Manager\TemplateManager:
2828
autowire: true
2929
autoconfigure: true
3030

31-
PhpList\Core\Domain\Messaging\Service\TemplateImageManager:
31+
PhpList\Core\Domain\Messaging\Service\Manager\TemplateImageManager:
32+
autowire: true
33+
autoconfigure: true
34+
35+
PhpList\Core\Domain\Messaging\Service\Manager\BounceRegexManager:
3236
autowire: true
3337
autoconfigure: true
3438

config/services/normalizers.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,7 @@ services:
101101
PhpList\RestBundle\Subscription\Serializer\SubscribePageNormalizer:
102102
tags: [ 'serializer.normalizer' ]
103103
autowire: true
104+
105+
PhpList\RestBundle\Messaging\Serializer\BounceRegexNormalizer:
106+
tags: [ 'serializer.normalizer' ]
107+
autowire: true
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Messaging\Controller;
6+
7+
use OpenApi\Attributes as OA;
8+
use PhpList\Core\Domain\Messaging\Service\Manager\BounceRegexManager;
9+
use PhpList\Core\Security\Authentication;
10+
use PhpList\RestBundle\Common\Controller\BaseController;
11+
use PhpList\RestBundle\Common\Validator\RequestValidator;
12+
use PhpList\RestBundle\Messaging\Request\CreateBounceRegexRequest;
13+
use PhpList\RestBundle\Messaging\Serializer\BounceRegexNormalizer;
14+
use Symfony\Component\HttpFoundation\JsonResponse;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\Routing\Attribute\Route;
18+
19+
/**
20+
* Manage bounce regular expressions.
21+
*/
22+
#[Route('/bounces/regex', name: 'bounce_regex_')]
23+
class BounceRegexController extends BaseController
24+
{
25+
public function __construct(
26+
Authentication $authentication,
27+
RequestValidator $validator,
28+
private readonly BounceRegexManager $manager,
29+
private readonly BounceRegexNormalizer $normalizer,
30+
) {
31+
parent::__construct($authentication, $validator);
32+
}
33+
34+
#[Route('', name: 'get_list', methods: ['GET'])]
35+
#[OA\Get(
36+
path: '/api/v2/bounces/regex',
37+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production. ' .
38+
'Returns a JSON list of all bounce regex rules.',
39+
summary: 'Gets a list of all bounce regex rules.',
40+
tags: ['bounces'],
41+
parameters: [
42+
new OA\Parameter(
43+
name: 'php-auth-pw',
44+
description: 'Session key obtained from login',
45+
in: 'header',
46+
required: true,
47+
schema: new OA\Schema(type: 'string')
48+
),
49+
],
50+
responses: [
51+
new OA\Response(
52+
response: 200,
53+
description: 'Success',
54+
content: new OA\JsonContent(
55+
type: 'array',
56+
items: new OA\Items(ref: '#/components/schemas/BounceRegex')
57+
)
58+
),
59+
new OA\Response(
60+
response: 403,
61+
description: 'Failure',
62+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
63+
)
64+
]
65+
)]
66+
public function list(Request $request): JsonResponse
67+
{
68+
$this->requireAuthentication($request);
69+
$items = $this->manager->getAll();
70+
$normalized = array_map(fn($bounceRegex) => $this->normalizer->normalize($bounceRegex), $items);
71+
72+
return $this->json($normalized, Response::HTTP_OK);
73+
}
74+
75+
#[Route('/{regexHash}', name: 'get_one', methods: ['GET'])]
76+
#[OA\Get(
77+
path: '/api/v2/bounces/regex/{regexHash}',
78+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production. ' .
79+
'Returns a bounce regex by its hash.',
80+
summary: 'Get a bounce regex by its hash',
81+
tags: ['bounces'],
82+
parameters: [
83+
new OA\Parameter(
84+
name: 'php-auth-pw',
85+
description: 'Session key obtained from login',
86+
in: 'header',
87+
required: true,
88+
schema: new OA\Schema(type: 'string')
89+
),
90+
new OA\Parameter(
91+
name: 'regexHash',
92+
description: 'Regex hash',
93+
in: 'path',
94+
required: true,
95+
schema: new OA\Schema(type: 'string')
96+
),
97+
],
98+
responses: [
99+
new OA\Response(
100+
response: 200,
101+
description: 'Success',
102+
content: new OA\JsonContent(ref: '#/components/schemas/BounceRegex')
103+
),
104+
new OA\Response(
105+
response: 403,
106+
description: 'Failure',
107+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
108+
),
109+
new OA\Response(
110+
response: 404,
111+
description: 'Failure',
112+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
113+
)
114+
]
115+
)]
116+
public function getOne(Request $request, string $regexHash): JsonResponse
117+
{
118+
$this->requireAuthentication($request);
119+
$entity = $this->manager->getByHash($regexHash);
120+
if (!$entity) {
121+
throw $this->createNotFoundException('Bounce regex not found.');
122+
}
123+
124+
return $this->json($this->normalizer->normalize($entity), Response::HTTP_OK);
125+
}
126+
127+
#[Route('', name: 'create_or_update', methods: ['POST'])]
128+
#[OA\Post(
129+
path: '/api/v2/bounces/regex',
130+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production. ' .
131+
'Creates a new bounce regex or updates an existing one (matched by regex hash).',
132+
summary: 'Create or update a bounce regex',
133+
requestBody: new OA\RequestBody(
134+
description: 'Create or update a bounce regex rule.',
135+
required: true,
136+
content: new OA\JsonContent(
137+
required: ['regex'],
138+
properties: [
139+
new OA\Property(property: 'regex', type: 'string', example: '/mailbox is full/i'),
140+
new OA\Property(property: 'action', type: 'string', example: 'delete', nullable: true),
141+
new OA\Property(property: 'list_order', type: 'integer', example: 0, nullable: true),
142+
new OA\Property(property: 'admin', type: 'integer', example: 1, nullable: true),
143+
new OA\Property(property: 'comment', type: 'string', example: 'Auto-generated', nullable: true),
144+
new OA\Property(property: 'status', type: 'string', example: 'active', nullable: true),
145+
],
146+
type: 'object'
147+
)
148+
),
149+
tags: ['bounces'],
150+
parameters: [
151+
new OA\Parameter(
152+
name: 'php-auth-pw',
153+
description: 'Session key obtained from login',
154+
in: 'header',
155+
required: true,
156+
schema: new OA\Schema(type: 'string')
157+
),
158+
],
159+
responses: [
160+
new OA\Response(
161+
response: 201,
162+
description: 'Success',
163+
content: new OA\JsonContent(ref: '#/components/schemas/BounceRegex')
164+
),
165+
new OA\Response(
166+
response: 403,
167+
description: 'Failure',
168+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
169+
),
170+
new OA\Response(
171+
response: 422,
172+
description: 'Failure',
173+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
174+
),
175+
]
176+
)]
177+
public function createOrUpdate(Request $request): JsonResponse
178+
{
179+
$this->requireAuthentication($request);
180+
/** @var CreateBounceRegexRequest $dto */
181+
$dto = $this->validator->validate($request, CreateBounceRegexRequest::class);
182+
183+
$entity = $this->manager->createOrUpdateFromPattern(
184+
regex: $dto->regex,
185+
action: $dto->action,
186+
listOrder: $dto->listOrder,
187+
adminId: $dto->admin,
188+
comment: $dto->comment,
189+
status: $dto->status
190+
);
191+
192+
return $this->json($this->normalizer->normalize($entity), Response::HTTP_CREATED);
193+
}
194+
195+
#[Route('/{regexHash}', name: 'delete', methods: ['DELETE'])]
196+
#[OA\Delete(
197+
path: '/api/v2/bounces/regex/{regexHash}',
198+
description: '🚧 **Status: Beta** – This method is under development. Avoid using in production. ' .
199+
'Delete a bounce regex by its hash.',
200+
summary: 'Delete a bounce regex by its hash',
201+
tags: ['bounces'],
202+
parameters: [
203+
new OA\Parameter(
204+
name: 'php-auth-pw',
205+
description: 'Session key obtained from login',
206+
in: 'header',
207+
required: true,
208+
schema: new OA\Schema(type: 'string')
209+
),
210+
new OA\Parameter(
211+
name: 'regexHash',
212+
description: 'Regex hash',
213+
in: 'path',
214+
required: true,
215+
schema: new OA\Schema(type: 'string')
216+
),
217+
],
218+
responses: [
219+
new OA\Response(
220+
response: Response::HTTP_NO_CONTENT,
221+
description: 'Success'
222+
),
223+
new OA\Response(
224+
response: 403,
225+
description: 'Failure',
226+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
227+
),
228+
new OA\Response(
229+
response: 404,
230+
description: 'Failure',
231+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundErrorResponse')
232+
)
233+
]
234+
)]
235+
public function delete(Request $request, string $regexHash): JsonResponse
236+
{
237+
$this->requireAuthentication($request);
238+
$entity = $this->manager->getByHash($regexHash);
239+
if (!$entity) {
240+
throw $this->createNotFoundException('Bounce regex not found.');
241+
}
242+
$this->manager->delete($entity);
243+
244+
return $this->json(null, Response::HTTP_NO_CONTENT);
245+
}
246+
}

src/Messaging/Controller/TemplateController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use OpenApi\Attributes as OA;
88
use PhpList\Core\Domain\Messaging\Model\Template;
9-
use PhpList\Core\Domain\Messaging\Service\TemplateManager;
9+
use PhpList\Core\Domain\Messaging\Service\Manager\TemplateManager;
1010
use PhpList\Core\Security\Authentication;
1111
use PhpList\RestBundle\Common\Controller\BaseController;
1212
use PhpList\RestBundle\Common\Service\Provider\PaginatedDataProvider;

src/Messaging/OpenApi/SwaggerSchemasResponse.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,21 @@
120120
],
121121
type: 'object'
122122
)]
123+
#[OA\Schema(
124+
schema: 'BounceRegex',
125+
properties: [
126+
new OA\Property(property: 'id', type: 'integer', example: 10),
127+
new OA\Property(property: 'regex', type: 'string', example: '/mailbox is full/i'),
128+
new OA\Property(property: 'regex_hash', type: 'string', example: 'd41d8cd98f00b204e9800998ecf8427e'),
129+
new OA\Property(property: 'action', type: 'string', example: 'delete', nullable: true),
130+
new OA\Property(property: 'list_order', type: 'integer', example: 0, nullable: true),
131+
new OA\Property(property: 'admin_id', type: 'integer', example: 1, nullable: true),
132+
new OA\Property(property: 'comment', type: 'string', example: 'Auto-generated rule', nullable: true),
133+
new OA\Property(property: 'status', type: 'string', example: 'active', nullable: true),
134+
new OA\Property(property: 'count', type: 'integer', example: 5, nullable: true),
135+
],
136+
type: 'object'
137+
)]
123138
class SwaggerSchemasResponse
124139
{
125140
}
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\Messaging\Request;
6+
7+
use PhpList\RestBundle\Common\Request\RequestInterface;
8+
use Symfony\Component\Validator\Constraints as Assert;
9+
10+
class CreateBounceRegexRequest implements RequestInterface
11+
{
12+
#[Assert\NotBlank]
13+
#[Assert\Type('string')]
14+
public string $regex;
15+
16+
#[Assert\Type('string')]
17+
public ?string $action = null;
18+
19+
#[Assert\Type('integer')]
20+
public ?int $listOrder = 0;
21+
22+
#[Assert\Type('integer')]
23+
public ?int $admin = null;
24+
25+
#[Assert\Type('string')]
26+
public ?string $comment = null;
27+
28+
#[Assert\Type('string')]
29+
public ?string $status = null;
30+
31+
public function getDto(): array
32+
{
33+
return [
34+
'regex' => $this->regex,
35+
'action' => $this->action,
36+
'listOrder' => $this->listOrder,
37+
'admin' => $this->admin,
38+
'comment' => $this->comment,
39+
'status' => $this->status,
40+
];
41+
}
42+
}

0 commit comments

Comments
 (0)