<?php
namespace Wbfk\IntediaDoofinderSW6\Subscriber;
use Enqueue\MessengerAdapter\EnvelopeItem\TransportConfiguration;
use Psr\Log\LoggerInterface;
use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\BeforeDeleteEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Wbfk\IntediaDoofinderSW6\Core\Content\Settings\Service\Operation;
use Wbfk\IntediaDoofinderSW6\MessageQueue\DoofinderIndexMessage;
class ProductSubscriber implements EventSubscriberInterface
{
protected int $startTime = 22; // Define the start and end hours for the restricted time range
protected int $endTime = 6; // Define the start and end hours for the restricted time range
protected bool $realtimeIndexing = true;
public function __construct(
private readonly MessageBusInterface $messageBus,
private readonly EntityRepository $productRepository,
private readonly LoggerInterface $logger,
private readonly SystemConfigService $systemConfigService
) {
$this->startTime = (int)substr($this->systemConfigService->get('WbfkIntediaDoofinderSW6.config.startTime'), 0, 2);
$this->endTime = (int)substr($this->systemConfigService->get('WbfkIntediaDoofinderSW6.config.endTime'), 0, 2);
$this->realtimeIndexing = (bool)$this->systemConfigService->get('WbfkIntediaDoofinderSW6.config.realtimeIndexing');
}
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_WRITTEN_EVENT => 'onProductWrittenEvent',
BeforeDeleteEvent::class => 'onProductDeletedEvent',
];
}
public function onProductWrittenEvent(EntityWrittenEvent $event): void
{
if ($this->skipIndexing()) {
return;
}
$this->logger->info("Doofinder Product written Event", $event->jsonSerialize());
$this->createMessage($event);
}
public function onProductDeletedEvent(BeforeDeleteEvent $event): void
{
if ($this->skipIndexing()) {
return;
}
$productIds = $event->getIds(ProductDefinition::ENTITY_NAME);
if (empty($productIds)) {
return;
}
$this->logger->warning("Fetching ProductNumbers for following Ids: ".json_encode($productIds));
$productNumbers = [];
$criteria = new Criteria($productIds);
$productSearchResult = $this->productRepository->search($criteria, $event->getContext());
/* @var ProductEntity $currentProduct */
foreach ($productSearchResult as $currentProduct) {
$productNumbers[] = $currentProduct->getProductNumber();
}
$event->addSuccess(function () use ($productNumbers): void {
$this->messageBus->dispatch(
new DoofinderIndexMessage(
$productNumbers,
Operation::DELETE
),
[
new TransportConfiguration([
'metadata' => [
'priority' => -1000, // make the priority in the enqueue table less than mails. Mail have priority = 0
], // because we can wait a few minutes for the index to be updated if there are other more important things queued
]),
]
);
});
}
/**
* @param EntityWrittenEvent $event
* @return void
*/
public function createMessage(EntityWrittenEvent $event): void
{
$productIds = array_map(function ($writeResult) {
return $writeResult->getPrimaryKey();
}, $event->getWriteResults());
$this->messageBus->dispatch(
new DoofinderIndexMessage(
$productIds,
Operation::UPSERT
),
[
new TransportConfiguration([
'metadata' => [
'priority' => -1000, // make the priority in the enqueue table less than mails. Mail have priority = 0
], // because we can wait a few minutes for the index to be updated if there are other more important things queued
]),
]
);
}
/**
* Updates to Doofinder should not happen, when the product update is triggered through an
* automated process. E.g. a warehouse calculation. These processes happen in the night.
* Therefore, we check if it is in the middle of the night, if yes, we do not update Doofinder.
*
* Also: Only do the indexing if the setting realtime indexing is enabled
*
* @return bool
*/
public function skipIndexing(): bool
{
$originalTimeZone = date_default_timezone_get();
//switch to Berlin timezone to have the correct time
date_default_timezone_set('Europe/Berlin');
// Get the current hour in 24-hour format
$currentHour = (int)date('G');
date_default_timezone_set($originalTimeZone);
// Check if update to Doofinder Index is paused
if ($this->realtimeIndexing && $currentHour < $this->startTime && $currentHour >= $this->endTime) {
return false;
} else {
return true;
}
}
}