Skip to content

Commit

Permalink
Merge pull request #39 from SpearDevs/rc/v1.1.0
Browse files Browse the repository at this point in the history
Update translates, send push notification by enter user email
  • Loading branch information
TomaszLach2 authored Jul 30, 2024
2 parents f7973a5 + d7b3241 commit b51e9a3
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 81 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
61 changes: 21 additions & 40 deletions src/Controller/Admin/SendPushNotificationAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
) {
}

Expand All @@ -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()]);
}
}
30 changes: 30 additions & 0 deletions src/Form/Model/SendPushNotificationFormModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace SpearDevs\SyliusPushNotificationsPlugin\Form\Model;

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;

/** @PushNotificationUserSubscriptionExists() */
class SendPushNotificationFormModel
{
/** @Assert\NotBlank() */
public string $title;

/** @Assert\NotBlank() */
public string $body;

/** @Assert\NotBlank() */
public ChannelInterface $channel;

public string $receiver;

public ?CustomerGroupInterface $group = null;

/** @Assert\Email() */
public string $userEmail;
}
46 changes: 12 additions & 34 deletions src/Form/Type/Admin/SendPushNotificationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@

namespace SpearDevs\SyliusPushNotificationsPlugin\Form\Type\Admin;

use Doctrine\ORM\EntityRepository;
use SpearDevs\SyliusPushNotificationsPlugin\Entity\UserSubscription\UserSubscription;
use SpearDevs\SyliusPushNotificationsPlugin\Form\Model\SendPushNotificationFormModel;
use Sylius\Component\Core\Model\Channel;
use Sylius\Component\Core\Model\ShopUser;
use Sylius\Component\Customer\Model\CustomerGroup;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;

class SendPushNotificationType extends AbstractType
Expand All @@ -32,29 +31,18 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'attr' => [
'class' => 'form-control',
],
'constraints' => [
new NotBlank(),
],
])
->add('body', TextareaType::class, [
'label' => 'speardevs_sylius_push_notifications_plugin.ui.content',
'attr' => [
'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',
Expand All @@ -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,
Expand All @@ -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,
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace SpearDevs\SyliusPushNotificationsPlugin\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
* @Annotation
*/
class PushNotificationUserSubscriptionExists extends Constraint
{
public string $message = 'push_notifications.send.user_subscription_not_exist';

public function getTargets(): string
{
return self::CLASS_CONSTRAINT;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace SpearDevs\SyliusPushNotificationsPlugin\Validator\Constraints;

use SpearDevs\SyliusPushNotificationsPlugin\Form\Model\SendPushNotificationFormModel;
use SpearDevs\SyliusPushNotificationsPlugin\Repository\UserSubscriptionRepositoryInterface;
use SpearDevs\SyliusPushNotificationsPlugin\WebPushSender\WebPushSender;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Traversable;

final class PushNotificationUserSubscriptionExistsValidator extends ConstraintValidator
{
public function __construct(
private UserSubscriptionRepositoryInterface $userSubscriptionRepository,
) {
}

/**
* @param SendPushNotificationFormModel $value
*/
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof PushNotificationUserSubscriptionExists) {
throw new UnexpectedTypeException($constraint, PushNotificationUser::class);
}

if ($value === null || $value === '' || $value->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();
}
}
25 changes: 25 additions & 0 deletions src/WebPushSender/WebPushSender.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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;

$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) {
$customerGroup = $sendPushNotificationFormModel->group;
$this->sendToGroup($webPush, $channel, $customerGroup?->getName());
}
}

public function sendToGroup(WebPushInterface $webPush, ChannelInterface $channel, ?string $receiver = null): void
{
$subscriptions = ($receiver) ?
Expand Down
3 changes: 3 additions & 0 deletions src/WebPushSender/WebPushSenderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 4 additions & 6 deletions templates/Admin/PushNotifications/Generate/_form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@

{{ form_row(form.receiver, { attr: { 'data-form-field': 'receiver' } }) }}

<div class="field" data-form-row="send-to">
{{ form_label(form.groups) }}
{{ form_widget(form.groups) }}
<div data-form-row="send-to">
{{ form_row(form.group) }}
</div>

<div class="field" data-form-row="user">
{{ form_label(form.user) }}
{{ form_widget(form.user) }}
<div data-form-row="user">
{{ form_row(form.userEmail) }}
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions tests/Application/config/bundles.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

return [
Sylius\Abstraction\StateMachine\SyliusStateMachineAbstractionBundle::class => ['all' => true],
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Expand Down
1 change: 1 addition & 0 deletions translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit b51e9a3

Please sign in to comment.