<?php
declare(strict_types=1);
namespace WbfkExtensions\Subscriber;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Order\OrderCollection;
use Shopware\Core\Checkout\Order\OrderDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\BeforeDeleteEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LogOrderChanges implements EventSubscriberInterface
{
public function __construct(
private readonly SystemConfigService $systemConfigService,
private readonly LoggerInterface $logger,
private readonly EntityRepositoryInterface $orderRepository,
private readonly Connection $connection,
) {
}
public static function getSubscribedEvents(): array
{
return [
// BeforeDeleteEvent::class => 'beforeDelete',
// OrderEvents::ORDER_WRITTEN_EVENT => 'onOrderWritten',
PreWriteValidationEvent::class => 'preWriteValidation',
];
}
public function preWriteValidation(PreWriteValidationEvent $event): void
{
if (!$this->systemConfigService->get('WbfkExtensions.config.loggingOrder')) {
return;
}
$ctxExt = $event->getContext()->getExtension(self::class);
if (isset($ctxExt['allowToOpen']) && $ctxExt['allowToOpen']) {
return;
}
foreach ($event->getCommands() as $command) {
if ($command->getEntityName() === 'order') {
$payloads = $command->getPayload();
$exist = $command->getEntityExistence();
if ($exist->exists() && isset($payloads['state_id']) && $payloads['state_id'] === hex2bin('d50aa676dd7049a39bbef1dd9ac2fdcb')) {
if ($this->getOrderState($command->getPrimaryKey()) === 'd50aa676dd7049a39bbef1dd9ac2fdcb') {
// Check old state. If it is also "open" than it is OK
return;
}
$this->logger->error('Prevent Order State to be set to OPEN', [
'payloads' => $payloads,
'$_SERVER' => $_SERVER,
'apache_request_headers' => apache_request_headers(),
'stack_trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),
]);
$event->getExceptions()->add(new \Exception('Prevent Order State to be set to OPEN'));
}
}
}
}
private function getOrderState($primaryKeys): ?string
{
try {
$res = $this->connection->executeQuery('SELECT state_id FROM `order` WHERE id = :id and version_id = :version_id', $primaryKeys);
$retArray = $res->fetchAssociative();
return bin2hex($retArray['state_id']);
} catch (Exception|\Doctrine\DBAL\Driver\Exception) {
}
return null;
}
public function onOrderWritten(EntityWrittenEvent $event): void
{
if (!$this->systemConfigService->get('WbfkExtensions.config.loggingOrder')) {
return;
}
$payloads = $event->getPayloads();
$ids = implode(', ', $event->getIds());
$this->logger->info('Written: '.$ids, [
'payloads' => $payloads,
'$_SERVER' => $_SERVER,
'apache_request_headers' => apache_request_headers(),
]);
}
public function beforeDelete(BeforeDeleteEvent $event): void
{
if (!$this->systemConfigService->get('WbfkExtensions.config.loggingOrder')) {
return;
}
$context = $event->getContext();
$ids = $event->getIds(OrderDefinition::ENTITY_NAME);
if (empty($ids)) {
return;
}
$orderCriteria = new Criteria($ids);
$orderCriteria->addAssociation('orderCustomer');
$orderCriteria->addAssociation('billingAddress');
$orderCriteria->addAssociation('deliveries');
$orderCriteria->addAssociation('lineItems');
$orderCriteria->addAssociation('transactions');
$orderCriteria->addAssociation('tags');
/** @var OrderCollection $orders */
$orders = $this->orderRepository->search($orderCriteria, $context);
$event->addSuccess(function () use ($orders): void {
$this->logger->alert('Deleted: '.implode(', ', $orders->getIds()), [
'orders' => $orders,
'$_SERVER' => $_SERVER,
'apache_request_headers' => apache_request_headers(),
]);
});
}
}