From 6a2923dbf31550bef4a14057e2291a3fbae4f512 Mon Sep 17 00:00:00 2001 From: TomaszLach2 Date: Fri, 26 Jul 2024 15:42:44 +0200 Subject: [PATCH 1/3] Update translates, send push notification by enter user email --- .gitignore | 1 + composer.json | 2 +- .../Admin/SendPushNotificationAction.php | 61 +++++++------------ .../Model/SendPushNotificationFormModel.php | 30 +++++++++ .../Type/Admin/SendPushNotificationType.php | 46 ++++---------- .../Constraints/PushNotificationUser.php | 20 ++++++ .../PushNotificationUserValidator.php | 52 ++++++++++++++++ src/WebPushSender/WebPushSender.php | 25 ++++++++ src/WebPushSender/WebPushSenderInterface.php | 3 + .../Generate/_form.html.twig | 10 ++- tests/Application/config/bundles.php | 1 + translations/messages.en.yaml | 1 + translations/messages.pl.yaml | 1 + translations/validators.en.yaml | 4 ++ translations/validators.pl.yaml | 3 + 15 files changed, 179 insertions(+), 81 deletions(-) create mode 100644 src/Form/Model/SendPushNotificationFormModel.php create mode 100644 src/Validator/Constraints/PushNotificationUser.php create mode 100644 src/Validator/Constraints/PushNotificationUserValidator.php create mode 100644 translations/validators.en.yaml create mode 100644 translations/validators.pl.yaml diff --git a/.gitignore b/.gitignore index c03bd0e..1cd5dae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.idea /vendor/ /node_modules/ /composer.lock diff --git a/composer.json b/composer.json index 56c84b0..73e871a 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "license": "MIT", "require": { "php": "^8.0", - "bentools/webpush-bundle": "0.9", + "bentools/webpush-bundle": "0.12", "sylius/mailer-bundle": "^1.8 || ^2.0@beta", "sylius/sylius": "^1.9", "symfony/webpack-encore-bundle": "^1.15" diff --git a/src/Controller/Admin/SendPushNotificationAction.php b/src/Controller/Admin/SendPushNotificationAction.php index f4755cd..dcda0ff 100644 --- a/src/Controller/Admin/SendPushNotificationAction.php +++ b/src/Controller/Admin/SendPushNotificationAction.php @@ -4,31 +4,22 @@ namespace SpearDevs\SyliusPushNotificationsPlugin\Controller\Admin; +use Psr\Log\LoggerInterface; use SpearDevs\SyliusPushNotificationsPlugin\Context\ChannelContextInterface; -use SpearDevs\SyliusPushNotificationsPlugin\Factory\Interfaces\WebPushFactoryInterface; +use SpearDevs\SyliusPushNotificationsPlugin\Form\Model\SendPushNotificationFormModel; use SpearDevs\SyliusPushNotificationsPlugin\Form\Type\Admin\SendPushNotificationType; -use SpearDevs\SyliusPushNotificationsPlugin\ParameterMapper\ParameterMapperInterface; use SpearDevs\SyliusPushNotificationsPlugin\WebPushSender\WebPushSenderInterface; -use Sylius\Component\Core\Model\ChannelInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Contracts\Translation\TranslatorInterface; -use Twig\Environment; +use Symfony\Component\Translation\TranslatableMessage; final class SendPushNotificationAction extends AbstractController { - public const USER_RECEIVER = 'user'; - - public const GROUP_RECEIVER = 'group'; - public function __construct( - private Environment $twig, - private TranslatorInterface $translator, private WebPushSenderInterface $webPushSender, private ChannelContextInterface $channelContext, - private WebPushFactoryInterface $webPushFactory, - private ParameterMapperInterface $orderParameterMapper, + private LoggerInterface $logger, ) { } @@ -39,37 +30,27 @@ public function __invoke(Request $request): Response $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $data = $form->getData(); - - $pushTitle = $data['title'] ?? ''; - $pushContent = $data['body'] ?? ''; - $customerGroup = $data['groups']?->getName() ?? ''; - $receiver = $data['receiver'] ?? ''; - $user = $data['user']?->getUsername() ?? ''; - - $this->channelContext->setChannelCode($data['channel']->getCode()); - - /** @var ChannelInterface $channel */ - $channel = $this->channelContext->getChannel(); - - $webPush = $this->webPushFactory->create($this->orderParameterMapper, null, null, $pushTitle, $pushContent); - - if ($receiver === self::USER_RECEIVER) { - $this->webPushSender->sendToUser($webPush, $channel, $user); + try { + /** @var SendPushNotificationFormModel $data */ + $data = $form->getData(); + $channel = $data->channel; + $this->channelContext->setChannelCode($channel->getCode()); + $this->webPushSender->sendWebPush($data); + + $this->addFlash('success', new TranslatableMessage( + 'speardevs_sylius_push_notifications_plugin.ui.sent_success', + )); + } catch (\Exception $exception) { + $this->logger->error('Problem while sending push notifications ' . $exception->getMessage()); + + $this->addFlash('error', new TranslatableMessage( + 'speardevs_sylius_push_notifications_plugin.ui.sent_error', + )); } - if ($receiver === self::GROUP_RECEIVER) { - $this->webPushSender->sendToGroup($webPush, $channel, $customerGroup); - } - - $this->addFlash('success', $this->translator->trans('speardevs_sylius_push_notifications_plugin.ui.sent_success')); - return $this->redirect($request->getUri()); } - return new Response($this->twig->render( - $request->get('template'), - ['form' => $form->createView()], - )); + return $this->render($request->get('template'), ['form' => $form->createView()]); } } diff --git a/src/Form/Model/SendPushNotificationFormModel.php b/src/Form/Model/SendPushNotificationFormModel.php new file mode 100644 index 0000000..8343fe7 --- /dev/null +++ b/src/Form/Model/SendPushNotificationFormModel.php @@ -0,0 +1,30 @@ + [ 'class' => 'form-control', ], - 'constraints' => [ - new NotBlank(), - ], ]) ->add('body', TextareaType::class, [ 'label' => 'speardevs_sylius_push_notifications_plugin.ui.content', @@ -42,19 +38,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'class' => 'form-control', 'rows' => 4, ], - 'constraints' => [ - new NotBlank(), - ], ]) ->add('channel', EntityType::class, [ 'label' => 'sylius.ui.channel', 'required' => true, 'class' => Channel::class, - 'constraints' => [ - new NotBlank([ - 'groups' => 'sylius', - ]), - ], ]) ->add('receiver', ChoiceType::class, [ 'label' => 'speardevs_sylius_push_notifications_plugin.ui.receiver', @@ -63,7 +51,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'speardevs_sylius_push_notifications_plugin.ui.user' => 'user', ], ]) - ->add('groups', EntityType::class, [ + ->add('group', EntityType::class, [ 'label' => 'speardevs_sylius_push_notifications_plugin.ui.send_to', 'class' => CustomerGroup::class, 'required' => false, @@ -73,25 +61,15 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'messages', ), ]) - ->add('user', EntityType::class, [ + ->add('userEmail', EmailType::class, [ 'label' => 'speardevs_sylius_push_notifications_plugin.ui.user', - 'class' => ShopUser::class, - 'required' => false, - 'placeholder' => $this->translator->trans( - 'speardevs_sylius_push_notifications_plugin.ui.choose_user', - [], - 'messages', - ), - 'query_builder' => function (EntityRepository $shopUserRepository) { - return $shopUserRepository->createQueryBuilder('shopUser') - ->leftJoin( - UserSubscription::class, - 'userSubscription', - 'WITH', - 'userSubscription.user = shopUser.id', - ) - ->where('userSubscription IS NOT NULL'); - }, ]); } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => SendPushNotificationFormModel::class, + ]); + } } diff --git a/src/Validator/Constraints/PushNotificationUser.php b/src/Validator/Constraints/PushNotificationUser.php new file mode 100644 index 0000000..0f92f55 --- /dev/null +++ b/src/Validator/Constraints/PushNotificationUser.php @@ -0,0 +1,20 @@ +receiver === WebPushSender::GROUP_RECEIVER) { + return; + } + + $subscriptions = $this->userSubscriptionRepository->getSubscriptionsForUserByEmail( + $value->userEmail, + $value->channel, + ); + + /** @var Traversable $subscriptions * */ + $subscriptionCount = iterator_count($subscriptions); + + if ($subscriptionCount > 0) { + return; + } + + $this->context + ->buildViolation($constraint->message) + ->atPath('userEmail') + ->addViolation(); + } +} diff --git a/src/WebPushSender/WebPushSender.php b/src/WebPushSender/WebPushSender.php index 8b02d53..b828bdd 100644 --- a/src/WebPushSender/WebPushSender.php +++ b/src/WebPushSender/WebPushSender.php @@ -10,6 +10,7 @@ use SpearDevs\SyliusPushNotificationsPlugin\Context\ChannelContextInterface; use SpearDevs\SyliusPushNotificationsPlugin\Entity\PushNotificationTemplate\PushNotificationTemplate; use SpearDevs\SyliusPushNotificationsPlugin\Factory\Interfaces\WebPushFactoryInterface; +use SpearDevs\SyliusPushNotificationsPlugin\Form\Model\SendPushNotificationFormModel; use SpearDevs\SyliusPushNotificationsPlugin\ParameterMapper\ParameterMapperInterface; use SpearDevs\SyliusPushNotificationsPlugin\Repository\PushNotificationTemplate\PushNotificationTemplateRepositoryInterface; use SpearDevs\SyliusPushNotificationsPlugin\Repository\UserSubscriptionRepositoryInterface; @@ -27,6 +28,10 @@ final class WebPushSender implements WebPushSenderInterface public const PUSH_ORDER_SHIPPED_CODE = "'push_order_shipped'"; + public const USER_RECEIVER = 'user'; + + public const GROUP_RECEIVER = 'group'; + public function __construct( private UserSubscriptionRepositoryInterface $userSubscriptionRepository, private UserSubscriptionManagerInterface $userSubscriptionManager, @@ -40,6 +45,26 @@ public function __construct( ) { } + public function sendWebPush(SendPushNotificationFormModel $sendPushNotificationFormModel): void + { + $pushTitle = $sendPushNotificationFormModel->title; + $pushContent = $sendPushNotificationFormModel->body; + $receiver = $sendPushNotificationFormModel->receiver; + $channel = $sendPushNotificationFormModel->channel; + $userEmail = $sendPushNotificationFormModel->userEmail; + $customerGroup = $sendPushNotificationFormModel->group; + + $webPush = $this->webPushFactory->create($this->orderParameterMapper, null, null, $pushTitle, $pushContent); + + if ($receiver === self::USER_RECEIVER) { + $this->sendToUser($webPush, $channel, $userEmail); + } + + if ($receiver === self::GROUP_RECEIVER) { + $this->sendToGroup($webPush, $channel, $customerGroup); + } + } + public function sendToGroup(WebPushInterface $webPush, ChannelInterface $channel, ?string $receiver = null): void { $subscriptions = ($receiver) ? diff --git a/src/WebPushSender/WebPushSenderInterface.php b/src/WebPushSender/WebPushSenderInterface.php index 847f018..99a7e61 100644 --- a/src/WebPushSender/WebPushSenderInterface.php +++ b/src/WebPushSender/WebPushSenderInterface.php @@ -4,12 +4,15 @@ namespace SpearDevs\SyliusPushNotificationsPlugin\WebPushSender; +use SpearDevs\SyliusPushNotificationsPlugin\Form\Model\SendPushNotificationFormModel; use SpearDevs\SyliusPushNotificationsPlugin\WebPush\WebPushInterface; use Sylius\Component\Core\Model\ChannelInterface; use Sylius\Component\Core\Model\OrderInterface; interface WebPushSenderInterface { + public function sendWebPush(SendPushNotificationFormModel $sendPushNotificationFormModel): void; + public function sendToGroup(WebPushInterface $webPush, ChannelInterface $channel, ?string $receiver = null): void; public function sendToUser(WebPushInterface $webPush, ChannelInterface $channel, ?string $receiver = null): void; diff --git a/templates/Admin/PushNotifications/Generate/_form.html.twig b/templates/Admin/PushNotifications/Generate/_form.html.twig index 551a09f..0de7ef9 100644 --- a/templates/Admin/PushNotifications/Generate/_form.html.twig +++ b/templates/Admin/PushNotifications/Generate/_form.html.twig @@ -10,14 +10,12 @@ {{ form_row(form.receiver, { attr: { 'data-form-field': 'receiver' } }) }} -
- {{ form_label(form.groups) }} - {{ form_widget(form.groups) }} +
+ {{ form_row(form.group) }}
-
- {{ form_label(form.user) }} - {{ form_widget(form.user) }} +
+ {{ form_row(form.userEmail) }}
diff --git a/tests/Application/config/bundles.php b/tests/Application/config/bundles.php index 6e48447..8f1d326 100644 --- a/tests/Application/config/bundles.php +++ b/tests/Application/config/bundles.php @@ -1,6 +1,7 @@ ['all' => true], Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index c1695ea..c730b14 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -23,6 +23,7 @@ speardevs_sylius_push_notifications_plugin: content: Content code: Code sent_success: Push notification sent + sent_error: An error occurred while sending push notifications send_to: Send to receiver: Receiver group: Group diff --git a/translations/messages.pl.yaml b/translations/messages.pl.yaml index 638407c..7d9b7e7 100644 --- a/translations/messages.pl.yaml +++ b/translations/messages.pl.yaml @@ -23,6 +23,7 @@ speardevs_sylius_push_notifications_plugin: content: Treść code: Kod sent_success: Wysłano notyfikacje push + sent_error: Wystąpił błąd podczas wysyłki notyfikacji push send_to: Wyślij do receiver: Odbiorca group: Grupa diff --git a/translations/validators.en.yaml b/translations/validators.en.yaml new file mode 100644 index 0000000..e234278 --- /dev/null +++ b/translations/validators.en.yaml @@ -0,0 +1,4 @@ +push_notifications: + send: + user_subscription_not_exist: The user with the provided email address has not consented to receiving push notifications. + diff --git a/translations/validators.pl.yaml b/translations/validators.pl.yaml new file mode 100644 index 0000000..a9cd4c7 --- /dev/null +++ b/translations/validators.pl.yaml @@ -0,0 +1,3 @@ +push_notifications: + send: + user_subscription_not_exist: Użytkownik o podanym adresie email nie wyraził zgody na otrzymywanie push notyfikacji. From 3b15b89d4bbc305d810f195c27ab2efb43090d2b Mon Sep 17 00:00:00 2001 From: TomaszLach2 Date: Mon, 29 Jul 2024 13:12:58 +0200 Subject: [PATCH 2/3] Code review fixes --- .gitignore | 1 - src/Form/Model/SendPushNotificationFormModel.php | 14 +++++++------- ... => PushNotificationUserSubscriptionExists.php} | 2 +- ...otificationUserSubscriptionExistsValidator.php} | 4 ++-- src/WebPushSender/WebPushSender.php | 6 +++--- translations/validators.en.yaml | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) rename src/Validator/Constraints/{PushNotificationUser.php => PushNotificationUserSubscriptionExists.php} (84%) rename src/Validator/Constraints/{PushNotificationUserValidator.php => PushNotificationUserSubscriptionExistsValidator.php} (90%) diff --git a/.gitignore b/.gitignore index 1cd5dae..c03bd0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/.idea /vendor/ /node_modules/ /composer.lock diff --git a/src/Form/Model/SendPushNotificationFormModel.php b/src/Form/Model/SendPushNotificationFormModel.php index 8343fe7..3a48ffe 100644 --- a/src/Form/Model/SendPushNotificationFormModel.php +++ b/src/Form/Model/SendPushNotificationFormModel.php @@ -4,27 +4,27 @@ namespace SpearDevs\SyliusPushNotificationsPlugin\Form\Model; -use SpearDevs\SyliusPushNotificationsPlugin\Validator\Constraints\PushNotificationUser; +use SpearDevs\SyliusPushNotificationsPlugin\Validator\Constraints\PushNotificationUserSubscriptionExists; use Sylius\Component\Core\Model\ChannelInterface; use Sylius\Component\Customer\Model\CustomerGroupInterface; use Symfony\Component\Validator\Constraints as Assert; -/** @PushNotificationUser() */ +/** @PushNotificationUserSubscriptionExists() */ final class SendPushNotificationFormModel { /** @Assert\NotBlank() */ - public ?string $title = null; + public string $title; /** @Assert\NotBlank() */ - public ?string $body = null; + public string $body; /** @Assert\NotBlank() */ - public ?ChannelInterface $channel = null; + public ChannelInterface $channel; - public ?string $receiver = null; + public string $receiver; public ?CustomerGroupInterface $group = null; /** @Assert\Email() */ - public ?string $userEmail = null; + public string $userEmail; } diff --git a/src/Validator/Constraints/PushNotificationUser.php b/src/Validator/Constraints/PushNotificationUserSubscriptionExists.php similarity index 84% rename from src/Validator/Constraints/PushNotificationUser.php rename to src/Validator/Constraints/PushNotificationUserSubscriptionExists.php index 0f92f55..0845754 100644 --- a/src/Validator/Constraints/PushNotificationUser.php +++ b/src/Validator/Constraints/PushNotificationUserSubscriptionExists.php @@ -9,7 +9,7 @@ /** * @Annotation */ -class PushNotificationUser extends Constraint +class PushNotificationUserSubscriptionExists extends Constraint { public string $message = 'push_notifications.send.user_subscription_not_exist'; diff --git a/src/Validator/Constraints/PushNotificationUserValidator.php b/src/Validator/Constraints/PushNotificationUserSubscriptionExistsValidator.php similarity index 90% rename from src/Validator/Constraints/PushNotificationUserValidator.php rename to src/Validator/Constraints/PushNotificationUserSubscriptionExistsValidator.php index 5a032f7..7988a14 100644 --- a/src/Validator/Constraints/PushNotificationUserValidator.php +++ b/src/Validator/Constraints/PushNotificationUserSubscriptionExistsValidator.php @@ -12,7 +12,7 @@ use Symfony\Component\Validator\ConstraintValidator; use Traversable; -final class PushNotificationUserValidator extends ConstraintValidator +final class PushNotificationUserSubscriptionExistsValidator extends ConstraintValidator { public function __construct( private UserSubscriptionRepositoryInterface $userSubscriptionRepository, @@ -24,7 +24,7 @@ public function __construct( */ public function validate($value, Constraint $constraint): void { - if (!$constraint instanceof PushNotificationUser) { + if (!$constraint instanceof PushNotificationUserSubscriptionExists) { throw new UnexpectedTypeException($constraint, PushNotificationUser::class); } diff --git a/src/WebPushSender/WebPushSender.php b/src/WebPushSender/WebPushSender.php index b828bdd..7fe7bb9 100644 --- a/src/WebPushSender/WebPushSender.php +++ b/src/WebPushSender/WebPushSender.php @@ -51,17 +51,17 @@ public function sendWebPush(SendPushNotificationFormModel $sendPushNotificationF $pushContent = $sendPushNotificationFormModel->body; $receiver = $sendPushNotificationFormModel->receiver; $channel = $sendPushNotificationFormModel->channel; - $userEmail = $sendPushNotificationFormModel->userEmail; - $customerGroup = $sendPushNotificationFormModel->group; $webPush = $this->webPushFactory->create($this->orderParameterMapper, null, null, $pushTitle, $pushContent); if ($receiver === self::USER_RECEIVER) { + $userEmail = $sendPushNotificationFormModel->userEmail; $this->sendToUser($webPush, $channel, $userEmail); } if ($receiver === self::GROUP_RECEIVER) { - $this->sendToGroup($webPush, $channel, $customerGroup); + $customerGroup = $sendPushNotificationFormModel->group; + $this->sendToGroup($webPush, $channel, $customerGroup?->getName()); } } diff --git a/translations/validators.en.yaml b/translations/validators.en.yaml index e234278..5b76e21 100644 --- a/translations/validators.en.yaml +++ b/translations/validators.en.yaml @@ -1,4 +1,4 @@ push_notifications: send: - user_subscription_not_exist: The user with the provided email address has not consented to receiving push notifications. + user_subscription_not_exist: The user with the provided email address do not consent to receive push notifications. From d7b32412505abf74827be4ac19dc4822cd82dfed Mon Sep 17 00:00:00 2001 From: TomaszLach2 Date: Tue, 30 Jul 2024 15:41:00 +0200 Subject: [PATCH 3/3] Drop final from class --- src/Form/Model/SendPushNotificationFormModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Form/Model/SendPushNotificationFormModel.php b/src/Form/Model/SendPushNotificationFormModel.php index 3a48ffe..b236e8d 100644 --- a/src/Form/Model/SendPushNotificationFormModel.php +++ b/src/Form/Model/SendPushNotificationFormModel.php @@ -10,7 +10,7 @@ use Symfony\Component\Validator\Constraints as Assert; /** @PushNotificationUserSubscriptionExists() */ -final class SendPushNotificationFormModel +class SendPushNotificationFormModel { /** @Assert\NotBlank() */ public string $title;