<?php declare(strict_types=1);
namespace NewsletterSendinblue\Subscriber;
use Monolog\Logger;
use NewsletterSendinblue\Service\BaseSyncService;
use NewsletterSendinblue\Service\ConfigService;
use NewsletterSendinblue\Traits\HelperTrait;
use Shopware\Core\Content\Category\CategoryDefinition;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Category\CategoryEvents;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityWriteResult;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\ChangeSetAware;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\DeleteCommand;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CategorySubscriber implements EventSubscriberInterface
{
use HelperTrait;
/** @var BaseSyncService */
private $categorySyncService;
/** @var EntityRepositoryInterface */
private $systemConfigRepository;
/** @var ConfigService */
private $configService;
/** @var Logger */
private $logger;
/** @var array */
private $deleteCategories = [];
/** @var array */
private $deletableIds = [];
/**
* @param BaseSyncService $categorySyncService
* @param EntityRepositoryInterface $systemConfigRepository
* @param ConfigService $configService
* @param Logger $logger
*/
public function __construct(
BaseSyncService $categorySyncService,
EntityRepositoryInterface $systemConfigRepository,
ConfigService $configService,
Logger $logger
)
{
$this->categorySyncService = $categorySyncService;
$this->systemConfigRepository = $systemConfigRepository;
$this->configService = $configService;
$this->logger = $logger;
}
/**
* @return string[]
*/
public static function getSubscribedEvents()
{
return [
CategoryEvents::CATEGORY_TRANSLATION_WRITTEN_EVENT => 'onCategoryWrittenEvent',
CategoryEvents::CATEGORY_DELETED_EVENT => 'onCategoryDeletedEvent',
PreWriteValidationEvent::class => 'onPreWriteValidationEvent',
];
}
/**
* @param PreWriteValidationEvent $event
* @return void
*/
public function onPreWriteValidationEvent(PreWriteValidationEvent $event): void
{
if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
return;
}
foreach ($event->getCommands() as $command) {
if (!$command instanceof ChangeSetAware) {
continue;
}
if ($command->getDefinition()->getEntityName() === CategoryDefinition::ENTITY_NAME
&& get_class($command) === DeleteCommand::class
&& !empty($command->getPrimaryKey()['id'])
) {
$catId = Uuid::fromBytesToHex($command->getPrimaryKey()['id']);
$this->deletableIds[] = $catId;
$childrenIds = $this->categorySyncService->getChildrenIds($catId, $event->getContext());
$this->deletableIds = array_merge($this->deletableIds, $childrenIds);
}
}
foreach ($this->deletableIds as $id) {
$this->deleteCategories[$id] = $this->categorySyncService->getEntity($id, $event->getContext());
}
if (!empty($this->deleteCategories)) {
$this->categorySyncService->setDeleteEntities($this->deleteCategories);
}
}
/**
* @param EntityDeletedEvent $event
* @return void
*/
public function onCategoryDeletedEvent(EntityDeletedEvent $event): void
{
$connectionId = $this->getAutoSyncConnectionId(
ConfigService::CONFIG_IS_CATEGORY_AUTO_SYNC_ENABLED,
$event->getContext()
);
if (empty($connectionId)) {
return;
}
foreach ($event->getWriteResults() as $writeResult) {
$categoryId = $writeResult->getPrimaryKey();
if (empty($categoryId)) {
continue;
}
if ($writeResult->getOperation() === EntityWriteResult::OPERATION_DELETE
&& isset($this->deleteCategories[$categoryId])
&& $this->deleteCategories[$categoryId] instanceof CategoryEntity
) {
foreach ($this->deleteCategories as $deleteCategory) {
if ($deleteCategory instanceof CategoryEntity) {
$this->categorySyncService->syncDelete($deleteCategory, $connectionId, $event->getContext());
}
}
$this->deleteCategories = [];
$this->categorySyncService->setDeleteEntities([]);
break;
}
}
}
/**
* @param EntityWrittenEvent $event
* @return void
*/
public function onCategoryWrittenEvent(EntityWrittenEvent $event): void
{
$connectionId = $this->getAutoSyncConnectionId(
ConfigService::CONFIG_IS_CATEGORY_AUTO_SYNC_ENABLED,
$event->getContext()
);
if (empty($connectionId)) {
return;
}
foreach ($event->getWriteResults() as $writeResult) {
$categoryId = $writeResult->getPrimaryKey()['categoryId'];
if (empty($categoryId)) {
continue;
}
// it is for avoiding call "sync" action when custom field is saved
if (!$this->checkChangeSet($writeResult)) {
continue;
}
if ($writeResult->getOperation() !== EntityWriteResult::OPERATION_DELETE) {
/** @var CategoryEntity $category */
$category = $this->categorySyncService->getEntity($categoryId, $event->getContext());
if (!$category->getActive()) {
$this->categorySyncService->syncDelete($category, $connectionId, $event->getContext(), true);
} else {
$this->categorySyncService->sync($categoryId, $connectionId, $event->getContext());
}
}
}
}
}