<?php
namespace Selfdelve\Cms\Subscriber;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Content\Mail\Service\AbstractMailService;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityWriteResult;
use Shopware\Core\Framework\Api\Context\AdminApiSource;
use Shopware\Core\Framework\Validation\DataBag\DataBag;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
use Shopware\Core\System\SystemConfig\SystemConfigService;
class CustomerWrittenSubscriber implements EventSubscriberInterface
{
private LoggerInterface $logger;
private EntityRepositoryInterface $customerRepository;
private EntityRepositoryInterface $mailTemplateRepository;
private AbstractMailService $mailService;
private SystemConfigService $systemConfigService;
/**
* CustomerWrittenSubscriber constructor.
*
* @param LoggerInterface $logger
* @param EntityRepositoryInterface $customerRepository
* @param EntityRepositoryInterface $mailTemplateRepository
* @param AbstractMailService $mailService
* @param SystemConfigService $systemConfigService
*/
public function __construct(
LoggerInterface $logger,
EntityRepositoryInterface $customerRepository,
EntityRepositoryInterface $mailTemplateRepository,
AbstractMailService $mailService,
SystemConfigService $systemConfigService
) {
$this->logger = $logger;
$this->customerRepository = $customerRepository;
$this->mailTemplateRepository = $mailTemplateRepository;
$this->mailService = $mailService;
$this->systemConfigService = $systemConfigService;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerWritten',
];
}
/**
* Send an email with user credentials if an user creates a customer in the backend.
*
* @param EntityWrittenEvent $event
*/
public function onCustomerWritten(EntityWrittenEvent $event): void
{
// Check backend context
if (!$event->getContext()->getSource() instanceof AdminApiSource) {
return;
}
// Check insert
$insertWriteResult = null;
foreach ($event->getWriteResults() as $res) {
if ($res->getOperation() === EntityWriteResult::OPERATION_INSERT) {
$insertWriteResult = $res;
break;
}
}
if (!$insertWriteResult instanceof EntityWriteResult) {
return;
}
$id = $insertWriteResult->getProperty('id');
/** @var CustomerEntity $customer */
$customer = $this->customerRepository->search(
new Criteria([$id]),
$event->getContext()
)->first();
if (!$customer instanceof CustomerEntity) {
return;
}
// Only accounts, no guests
if ($customer->getGuest() === true) {
return;
}
// Initial password
$pass = $this->generateRandomString();
$this->customerRepository->update([
[
'id' => $id,
'password' => $pass
]
], $event->getContext());
$mailTemplateId = $this->systemConfigService->get('SelfdelveCms.config.creationTemplateId');
/** @var MailTemplateEntity $mailTemplate */
$mailTemplate = $this->mailTemplateRepository->search(
new Criteria([
$mailTemplateId
]),
$event->getContext()
)->first();
if (!$mailTemplate) {
$this->logger->error(
sprintf('Could not find email template for id %s.', $mailTemplateId)
);
return;
}
$data = new DataBag();
$data->set('salesChannelId', $customer->getSalesChannelId());
$data->set('templateId', $mailTemplate->getId());
$data->set('recipients', [
$customer->getEmail() => trim($customer->__toString())
]);
$data->set('senderName', $mailTemplate->getTranslation('senderName'));
$data->set('subject', $mailTemplate->getTranslation('subject'));
$data->set('contentHtml', $mailTemplate->getTranslation('contentHtml'));
$data->set('contentPlain', $mailTemplate->getTranslation('contentPlain'));
if (!$this->mailService->send(
$data->all(),
$event->getContext(),
[
'customer' => $customer,
'pass' => $pass
]
)) {
$this->logger->error(
sprintf('Could not send customer creation email to %s.', $customer->getEmail())
);
return;
}
$this->logger->info(
sprintf('Customer with email %s was informed about its new account.', $customer->getEmail())
);
}
/**
* Generates a random string for the intial password.
*
* @param int $length
* @return string
*/
private function generateRandomString($length = 15) {
$characters = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ_=.-';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
}