<?php
declare(strict_types=1);
namespace LinkMobility\ShopwareSmsApiPlugin\Subscriber;
use LinkMobility\ShopwareSmsApiPlugin\Exception\SmsApiRequestException;
use LinkMobility\ShopwareSmsApiPlugin\Service\ContactService;
use Shopware\Core\Checkout\Customer\CustomerDefinition;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\ChangeSetAware;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
use Shopware\Core\Framework\Event\DataMappingEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Contracts\Translation\TranslatorInterface;
class CustomerWrittenSubscriber implements EventSubscriberInterface
{
public function __construct(
private EntityRepository $customerRepository,
private ContactService $contactService,
private RequestStack $requestStack,
private TranslatorInterface $translator
) {
}
public static function getSubscribedEvents(): array
{
return [
CustomerEvents::MAPPING_CUSTOMER_PROFILE_SAVE => 'onProfileSaved',
CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerWritten',
CustomerEvents::MAPPING_REGISTER_CUSTOMER => 'onProfileSaved',
CustomerEvents::CUSTOMER_DELETED_EVENT => 'onCustomerDeleted',
PreWriteValidationEvent::class => 'triggerChangeSet',
];
}
public function onProfileSaved(DataMappingEvent $event): void
{
$data = $event->getInput();
$customer = $event->getOutput();
$consent = 'on' === $data->get('link_mobility_shopware_sms_api_plugin_consent');
$customer['customFields']['link_mobility_shopware_sms_api_plugin_consent'] = $consent;
$event->setOutput($customer);
}
public function onCustomerWritten(EntityWrittenEvent $event): void
{
$ids = $event->getIds();
if (0 === \count($ids)) {
return;
}
$criteria = new Criteria($ids);
$criteria->addAssociation('defaultBillingAddress');
$context = $event->getContext();
$customers = $this->customerRepository->search($criteria, $context)->getEntities();
/** @var CustomerEntity $customer */
foreach ($customers as $customer) {
$customFields = $customer->getCustomFields();
$customerSmsApiId = $customFields['link_mobility_shopware_sms_api_plugin_customer_id'] ?? null;
$consent = $customFields['link_mobility_shopware_sms_api_plugin_consent'] ?? true;
if (!$consent) {
if (null !== $customerSmsApiId) {
$this->contactService->delete($customer, $customerSmsApiId, $context);
}
continue;
}
if (null !== $customerSmsApiId) {
try {
$this->contactService->edit($customer, $customerSmsApiId, $context);
} catch (SmsApiRequestException $exception) {
/** @var Session $session */
$session = $this->requestStack->getSession();
$session->getFlashBag()->add('danger', $this->translator->trans($exception->getMessage()));
}
continue;
}
try {
$this->contactService->create($customer, $context);
} catch (SmsApiRequestException $exception) {
/** @var Session $session */
$session = $this->requestStack->getSession();
$alreadyFlashed = false;
$translated = $this->translator->trans($exception->getMessage());
$flashes = $session->getFlashBag()->peek('danger');
foreach ($flashes as $message) {
if ($message === $translated) {
$alreadyFlashed = true;
}
}
if (!$alreadyFlashed) {
$session->getFlashBag()->add('danger', $translated);
}
}
}
}
public function onCustomerDeleted(EntityDeletedEvent $event)
{
foreach ($event->getWriteResults() as $item) {
/** @var string|null $customFields */
$customFields = $item->getChangeSet()?->getBefore('custom_fields');
if (null === $customFields) {
continue;
}
$customFieldsDecode = json_decode($customFields, true);
$customerSmsApiId = $customFieldsDecode['link_mobility_shopware_sms_api_plugin_customer_id'] ?? null;
if (null === $customerSmsApiId) {
continue;
}
$this->contactService->deleteContact($customerSmsApiId);
}
}
public function triggerChangeSet(PreWriteValidationEvent $event): void
{
foreach ($event->getCommands() as $command) {
if (!$command instanceof ChangeSetAware ||
CustomerDefinition::ENTITY_NAME !== $command->getDefinition()->getEntityName()) {
continue;
}
$command->requestChangeSet();
}
}
}