Skip to content

Commit cdffcdf

Browse files
committed
ISSUE-345: update message endpoint
1 parent 49a8926 commit cdffcdf

22 files changed

+483
-124
lines changed

config/services/builders.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
services:
2+
_defaults:
3+
autowire: true
4+
autoconfigure: true
5+
public: false
6+
7+
PhpList\RestBundle\Service\Builder\MessageBuilder:
8+
autowire: true
9+
autoconfigure: true
10+
11+
PhpList\RestBundle\Service\Builder\MessageFormatBuilder:
12+
autowire: true
13+
autoconfigure: true
14+
15+
PhpList\RestBundle\Service\Builder\MessageScheduleBuilder:
16+
autowire: true
17+
autoconfigure: true
18+
19+
PhpList\RestBundle\Service\Builder\MessageContentBuilder:
20+
autowire: true
21+
autoconfigure: true
22+
23+
PhpList\RestBundle\Service\Builder\MessageOptionsBuilder:
24+
autowire: true
25+
autoconfigure: true

src/Controller/CampaignController.php

+83-72
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpList\Core\Security\Authentication;
1010
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
1111
use PhpList\RestBundle\Entity\Request\CreateMessageRequest;
12+
use PhpList\RestBundle\Entity\Request\UpdateMessageRequest;
1213
use PhpList\RestBundle\Serializer\MessageNormalizer;
1314
use PhpList\RestBundle\Service\Manager\MessageManager;
1415
use PhpList\RestBundle\Service\Provider\MessageProvider;
@@ -19,6 +20,7 @@
1920
use Symfony\Component\HttpFoundation\Request;
2021
use Symfony\Component\HttpFoundation\Response;
2122
use Symfony\Component\Routing\Attribute\Route;
23+
use Symfony\Component\Serializer\SerializerInterface;
2224

2325
/**
2426
* This controller provides REST API to manage campaigns.
@@ -151,78 +153,11 @@ public function getMessage(
151153
content: new OA\JsonContent(
152154
properties: [
153155
new OA\Property(property: 'template_id', type: 'integer', example: 1),
154-
new OA\Property(
155-
property: 'message_content',
156-
properties: [
157-
new OA\Property(property: 'subject', type: 'string', example: 'Campaign Subject'),
158-
new OA\Property(property: 'text', type: 'string', example: 'Full text content'),
159-
new OA\Property(property: 'text_message', type: 'string', example: 'Short text message'),
160-
new OA\Property(property: 'footer', type: 'string', example: 'Unsubscribe link here'),
161-
],
162-
type: 'object'
163-
),
164-
new OA\Property(
165-
property: 'message_format',
166-
properties: [
167-
new OA\Property(property: 'html_formated', type: 'boolean', example: true),
168-
new OA\Property(
169-
property: 'send_format',
170-
type: 'string',
171-
enum: ['html', 'text', 'invite'],
172-
example: 'html'
173-
),
174-
new OA\Property(
175-
property: 'format_options',
176-
type: 'array',
177-
items: new OA\Items(type: 'string', enum: ['text', 'html', 'pdf']),
178-
example: ['html']
179-
),
180-
],
181-
type: 'object'
182-
),
183-
new OA\Property(
184-
property: 'message_metadata',
185-
properties: [
186-
new OA\Property(property: 'status', type: 'string', example: 'draft'),
187-
],
188-
type: 'object'
189-
),
190-
new OA\Property(
191-
property: 'message_schedule',
192-
properties: [
193-
new OA\Property(
194-
property: 'embargo',
195-
type: 'string',
196-
format: 'date-time',
197-
example: '2025-04-17 09:00:00'
198-
),
199-
new OA\Property(property: 'repeat_interval', type: 'string', example: '24 hours'),
200-
new OA\Property(
201-
property: 'repeat_until',
202-
type: 'string',
203-
format: 'date-time',
204-
example: '2025-04-30T00:00:00+04:00'
205-
),
206-
new OA\Property(property: 'requeue_interval', type: 'string', example: '12 hours'),
207-
new OA\Property(
208-
property: 'requeue_until',
209-
type: 'string',
210-
format: 'date-time',
211-
example: '2025-04-20T00:00:00+04:00'
212-
),
213-
],
214-
type: 'object'
215-
),
216-
new OA\Property(
217-
property: 'message_options',
218-
properties: [
219-
new OA\Property(property: 'from_field', type: 'string', example: '[email protected]'),
220-
new OA\Property(property: 'to_field', type: 'string', example: '[email protected]'),
221-
new OA\Property(property: 'reply_to', type: 'string', example: '[email protected]'),
222-
new OA\Property(property: 'user_selection', type: 'string', example: 'all-active-users'),
223-
],
224-
type: 'object'
225-
),
156+
new OA\Property(property: 'message_content', ref: '#/components/schemas/MessageContentRequest'),
157+
new OA\Property(property: 'message_format', ref: '#/components/schemas/MessageFormatRequest'),
158+
new OA\Property(property: 'message_metadata', ref: '#/components/schemas/MessageMetadataRequest'),
159+
new OA\Property(property: 'message_schedule', ref: '#/components/schemas/MessageScheduleRequest'),
160+
new OA\Property(property: 'message_options', ref: '#/components/schemas/MessageOptionsRequest'),
226161
],
227162
type: 'object'
228163
)
@@ -267,4 +202,80 @@ public function createMessage(Request $request, MessageNormalizer $normalizer):
267202

268203
return new JsonResponse($normalizer->normalize($data), Response::HTTP_CREATED);
269204
}
205+
206+
#[Route('/{messageId}', name: 'update_campaign', methods: ['PUT'])]
207+
#[OA\Put(
208+
path: '/campaigns/{messageId}',
209+
description: 'Updates campaign/message by id.',
210+
summary: 'Update campaign by id.',
211+
requestBody: new OA\RequestBody(
212+
description: 'Update message.',
213+
required: true,
214+
content: new OA\JsonContent(
215+
properties: [
216+
new OA\Property(property: 'template_id', type: 'integer', example: 1),
217+
new OA\Property(property: 'message_content', ref: '#/components/schemas/MessageContentRequest'),
218+
new OA\Property(property: 'message_format', ref: '#/components/schemas/MessageFormatRequest'),
219+
new OA\Property(property: 'message_schedule', ref: '#/components/schemas/MessageScheduleRequest'),
220+
new OA\Property(property: 'message_options', ref: '#/components/schemas/MessageOptionsRequest'),
221+
],
222+
type: 'object'
223+
)
224+
),
225+
tags: ['campaigns'],
226+
parameters: [
227+
new OA\Parameter(
228+
name: 'session',
229+
description: 'Session ID obtained from authentication',
230+
in: 'header',
231+
required: true,
232+
schema: new OA\Schema(
233+
type: 'string'
234+
)
235+
),
236+
new OA\Parameter(
237+
name: 'messageId',
238+
description: 'message ID',
239+
in: 'path',
240+
required: true,
241+
schema: new OA\Schema(type: 'string')
242+
)
243+
],
244+
responses: [
245+
new OA\Response(
246+
response: 200,
247+
description: 'Success',
248+
content: new OA\JsonContent(ref: '#/components/schemas/Message')
249+
),
250+
new OA\Response(
251+
response: 403,
252+
description: 'Failure',
253+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
254+
),
255+
new OA\Response(
256+
response: 422,
257+
description: 'Failure',
258+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
259+
),
260+
]
261+
)]
262+
public function updateMessage(
263+
Request $request,
264+
#[MapEntity(mapping: ['messageId' => 'id'])] Message $message,
265+
SerializerInterface $serializer,
266+
): JsonResponse {
267+
$authUser = $this->requireAuthentication($request);
268+
269+
/** @return UpdateMessageRequest $updateMessageRequest */
270+
$updateMessageRequest = $serializer->deserialize($request->getContent(), UpdateMessageRequest::class, 'json');
271+
$updateMessageRequest->subscriberId = $message->getId();
272+
$this->validator->validateDto($updateMessageRequest);
273+
274+
return new JsonResponse(
275+
$this->normalizer->normalize(
276+
$this->messageManager->updateMessage($updateMessageRequest, $message, $authUser)
277+
),
278+
Response::HTTP_OK
279+
);
280+
}
270281
}

src/Entity/Dto/MessageContext.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Entity\Dto;
6+
7+
use PhpList\Core\Domain\Model\Identity\Administrator;
8+
use PhpList\Core\Domain\Model\Messaging\Message;
9+
10+
class MessageContext
11+
{
12+
public function __construct(public Administrator $user, public ?Message $existing = null)
13+
{
14+
}
15+
16+
public function getOwner(): Administrator
17+
{
18+
return $this->user;
19+
}
20+
21+
public function getExisting(): ?Message
22+
{
23+
return $this->existing;
24+
}
25+
}

src/Entity/Request/Message/MessageContentRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Validator\Constraints as Assert;
88

9-
class MessageContentRequest
9+
class MessageContentRequest implements RequestDtoInterface
1010
{
1111
#[Assert\NotBlank]
1212
public string $subject;

src/Entity/Request/Message/MessageFormatRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Validator\Constraints as Assert;
88

9-
class MessageFormatRequest
9+
class MessageFormatRequest implements RequestDtoInterface
1010
{
1111
#[Assert\Type('bool')]
1212
public bool $htmlFormated;

src/Entity/Request/Message/MessageMetadataRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Validator\Constraints as Assert;
88

9-
class MessageMetadataRequest
9+
class MessageMetadataRequest implements RequestDtoInterface
1010
{
1111
#[Assert\NotBlank]
1212
public string $status;

src/Entity/Request/Message/MessageOptionsRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Validator\Constraints as Assert;
88

9-
class MessageOptionsRequest
9+
class MessageOptionsRequest implements RequestDtoInterface
1010
{
1111
#[Assert\Email]
1212
public string $fromField;

src/Entity/Request/Message/MessageScheduleRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Validator\Constraints as Assert;
88

9-
class MessageScheduleRequest
9+
class MessageScheduleRequest implements RequestDtoInterface
1010
{
1111
#[Assert\NotBlank]
1212
public int $repeatInterval;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace PhpList\RestBundle\Entity\Request\Message;
4+
5+
interface RequestDtoInterface
6+
{
7+
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Entity\Request;
6+
7+
use PhpList\RestBundle\Entity\Request\Message\MessageContentRequest;
8+
use PhpList\RestBundle\Entity\Request\Message\MessageFormatRequest;
9+
use PhpList\RestBundle\Entity\Request\Message\MessageOptionsRequest;
10+
use PhpList\RestBundle\Entity\Request\Message\MessageScheduleRequest;
11+
use Symfony\Component\Validator\Constraints as Assert;
12+
use PhpList\RestBundle\Validator as CustomAssert;
13+
14+
class UpdateMessageRequest extends CreateMessageRequest
15+
{
16+
public int $messageId;
17+
18+
#[Assert\Valid]
19+
#[Assert\NotNull]
20+
public MessageContentRequest $content;
21+
22+
#[Assert\Valid]
23+
#[Assert\NotNull]
24+
public MessageFormatRequest $format;
25+
26+
#[Assert\Valid]
27+
#[Assert\NotNull]
28+
public MessageScheduleRequest $schedule;
29+
30+
#[Assert\Valid]
31+
#[Assert\NotNull]
32+
public MessageOptionsRequest $options;
33+
34+
#[CustomAssert\TemplateExists]
35+
public ?int $templateId;
36+
}

0 commit comments

Comments
 (0)