<?php declare(strict_types=1);
namespace Acris\ShopSwitch;
use Acris\ShopSwitch\Core\Content\ShopSwitch\Event\ShopSwitchDatabaseUpdateEvent;
use Acris\ShopSwitch\Custom\ShopSwitchExclusionDefinition;
use Acris\ShopSwitch\Custom\ShopSwitchRuleEntity;
use Doctrine\DBAL\Connection;
use Shopware\Core\Content\ImportExport\Aggregate\ImportExportLog\ImportExportLogEntity;
use Shopware\Core\Content\ImportExport\ImportExportProfileEntity;
use Shopware\Core\Content\MailTemplate\MailTemplateActions;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\ActivateContext;
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
use Shopware\Core\Framework\Plugin\Context\UpdateContext;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelType\SalesChannelTypeEntity;
class AcrisShopSwitchCS extends Plugin
{
const DEFAULT_PRODUCT_IMPORT_NAME = "ACRIS_IP_Targeting_and_Language_Detection_Exclusions";
const DEFAULT_PRODUCT_IMPORT_NAME_EN = "ACRIS IP Targeting and Language Detection: Exclusions";
const DEFAULT_PRODUCT_IMPORT_NAME_DE = "ACRIS IP Targeting und Spracherkennung: Ausnahmen";
const DEFAULT_MAIL_TEMPLATE_TYPE_DATABASE_UPDATE_FAILED = 'shopSwitchDatabaseUpdateFailed';
public function activate(ActivateContext $activateContext): void
{
$this->insertDefaultData($activateContext->getContext(), true);
}
public function postUpdate(UpdateContext $updateContext): void
{
if(version_compare($updateContext->getCurrentPluginVersion(), '2.1.0', '<')
|| (version_compare($updateContext->getCurrentPluginVersion(), '3.8.0', '<') && version_compare($updateContext->getUpdatePluginVersion(), '3.8.0', '>='))
|| (version_compare($updateContext->getCurrentPluginVersion(), '3.8.2', '<') && version_compare($updateContext->getUpdatePluginVersion(), '3.8.2', '>='))) {
$this->insertDefaultData($updateContext->getContext(), $updateContext->getPlugin()->isActive());
}
if(version_compare($updateContext->getCurrentPluginVersion(), '3.4.0', '<') && version_compare($updateContext->getUpdatePluginVersion(), '3.4.0', '>=')) {
$this->addTranslationsNewFields($updateContext->getContext(), $updateContext->getPlugin()->isActive());
}
}
public function uninstall(UninstallContext $context): void
{
if ($context->keepUserData()) {
return;
}
$this->cleanupDatabase();
$this->removeDefaultMailTemplate($context->getContext());
$this->removeImportExportProfiles($context->getContext());
}
private function insertDefaultData(Context $context, bool $isActive): void
{
$this->insertDefaultMailTemplate($context);
$this->insertDefaultImportProfile($context);
$this->insertDefaultExclusions($context, $isActive);
}
private function cleanupDatabase(): void
{
$connection = $this->container->get(Connection::class);
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain_language_whitelist');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain_language_blacklist');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain_country_whitelist');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain_country_blacklist');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain_translation');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_domain');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_rule_translation');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_rule');
$connection->executeStatement('DROP TABLE IF EXISTS acris_switch_exclusion');
}
private function insertDefaultMailTemplate(Context $context)
{
$mailTemplateTypeRepository = $this->container->get('mail_template_type.repository');
$salesChannels = $this->getSalesChannels($context);
// Shop switch database update failed
/** @var IdSearchResult $mailTemplateTypeDatabaseUpdateFailedSearchResult */
$mailTemplateTypeDatabaseUpdateFailedSearchResult = $mailTemplateTypeRepository->searchIds((new Criteria())->addFilter(new EqualsFilter('technicalName', self::DEFAULT_MAIL_TEMPLATE_TYPE_DATABASE_UPDATE_FAILED)), $context);
if(empty($mailTemplateTypeDatabaseUpdateFailedSearchResult->firstId())) {
$mailTemplateTypeDatabaseUpdateFailedId = Uuid::randomHex();
$mailTemplateDatabaseUpdateFailedId = Uuid::randomHex();
$mailTemplateTypeDatabaseUpdateFailedData = [
'id' => $mailTemplateTypeDatabaseUpdateFailedId,
'technicalName' => self::DEFAULT_MAIL_TEMPLATE_TYPE_DATABASE_UPDATE_FAILED,
'availableEntities' => ['salesChannel' => 'sales_channel'],
'translations' => [
'de-DE' => [
'name' => 'ACRIS Automatisches Update der IP-Zieldatenbank fehlgeschlagen'
],
'en-GB' => [
'name' => 'ACRIS IP Targeting Database Automatically Update Failed'
],
[
'name' => 'ACRIS IP Targeting Database Automatically Update Failed',
'languageId' => Defaults::LANGUAGE_SYSTEM
]
],
'mailTemplates' => [
[
'id' => $mailTemplateDatabaseUpdateFailedId,
'systemDefault' => true,
'translations' => [
'de-DE' => [
'senderName' => '{{ salesChannel.name }}',
'subject' => 'Automatisches Update der IP-Zieldatenbank fehlgeschlagen',
'description' => 'E-Mail mit der Information, dass die automatische Aktualisierung der IP-Zieldatenbank fehlgeschlagen ist.',
'contentHtml' => file_get_contents($this->path . '/Resources/mail-template/html/de-DE/shop-switch-database-update-failed.html.twig'),
'contentPlain' => file_get_contents($this->path . '/Resources/mail-template/plain/de-DE/shop-switch-database-update-failed.html.twig')
],
'en-GB' => [
'senderName' => '{{ salesChannel.name }}',
'subject' => 'IP targeting database automatically update failed',
'description' => 'E-mail informing that IP targeting database automatically update failed.',
'contentHtml' => file_get_contents($this->path . '/Resources/mail-template/html/en-GB/shop-switch-database-update-failed.html.twig'),
'contentPlain' => file_get_contents($this->path . '/Resources/mail-template/plain/en-GB/shop-switch-database-update-failed.html.twig')
],
[
'senderName' => '{{ salesChannel.name }}',
'subject' => 'IP targeting database automatically update failed',
'description' => 'E-mail informing that IP targeting database automatically update failed.',
'contentHtml' => file_get_contents($this->path . '/Resources/mail-template/html/en-GB/shop-switch-database-update-failed.html.twig'),
'contentPlain' => file_get_contents($this->path . '/Resources/mail-template/plain/en-GB/shop-switch-database-update-failed.html.twig'),
'languageId' => Defaults::LANGUAGE_SYSTEM
]
]
]
]
];
$mailTemplateTypeRepository->upsert([$mailTemplateTypeDatabaseUpdateFailedData], $context);
$eventActionRepository = $this->container->get('event_action.repository');
$eventActionRepository->upsert([[
'eventName' => ShopSwitchDatabaseUpdateEvent::EVENT_NAME,
'actionName' => MailTemplateActions::MAIL_TEMPLATE_MAIL_SEND_ACTION,
'config' => ['mail_template_type_id' => $mailTemplateTypeDatabaseUpdateFailedId, 'mail_template_id' => $mailTemplateDatabaseUpdateFailedId],
'salesChannels' => $salesChannels
]], $context);
}
}
private function removeDefaultMailTemplate(Context $context)
{
$mailTemplateTypeRepository = $this->container->get('mail_template_type.repository');
/** @var IdSearchResult $mailTemplateTypeStockNotificationSearchResult */
$mailTemplateTypeStockNotificationSearchResult = $mailTemplateTypeRepository->searchIds((new Criteria())->addFilter(new EqualsAnyFilter('technicalName', [self::DEFAULT_MAIL_TEMPLATE_TYPE_DATABASE_UPDATE_FAILED])), $context);
if($mailTemplateTypeStockNotificationSearchResult->firstId()) {
$mailTemplateRepository = $this->container->get('mail_template.repository');
$deleteTemplateTypeData = [];
$deleteTemplateData = [];
foreach ($mailTemplateTypeStockNotificationSearchResult->getIds() as $templateTypeId) {
/** @var IdSearchResult $mailTemplateSearchResult */
$mailTemplateSearchResult = $mailTemplateRepository->searchIds((new Criteria())->addFilter(new EqualsFilter('mailTemplateTypeId', $templateTypeId)), $context);
if ($mailTemplateSearchResult->firstId()) {
foreach ($mailTemplateSearchResult->getIds() as $id) {
$deleteTemplateData[] = ['id' => $id];
}
}
$deleteTemplateTypeData[] = ['id' => $templateTypeId];
}
if (!empty($deleteTemplateData)) {
$mailTemplateRepository->delete($deleteTemplateData, $context);
}
if (!empty($deleteTemplateTypeData)) {
$mailTemplateTypeRepository->delete($deleteTemplateTypeData, $context);
}
}
$eventActionRepository = $this->container->get('event_action.repository');
/** @var IdSearchResult $eventActionSearchResult */
$eventActionSearchResult = $eventActionRepository->searchIds((new Criteria())->addFilter(new EqualsAnyFilter('eventName', [ShopSwitchDatabaseUpdateEvent::EVENT_NAME])), $context);
if($eventActionSearchResult->firstId()) {
$deleteBusinessEvents = [];
foreach ($eventActionSearchResult->getIds() as $id) {
$deleteBusinessEvents[] = ['id' => $id];
}
if (!empty($deleteBusinessEvents)) {
$eventActionRepository->delete($deleteBusinessEvents, $context);
}
}
}
private function getSalesChannels(Context $context): array
{
/** @var EntityRepositoryInterface $salesChannelTypeRepository */
$salesChannelTypeRepository = $this->container->get('sales_channel_type.repository');
/** @var EntityRepositoryInterface $salesChannelRepository */
$salesChannelRepository = $this->container->get('sales_channel.repository');
/** @var SalesChannelTypeEntity $salesChannelType */
$salesChannelType = $salesChannelTypeRepository->search((new Criteria())->addFilter(new EqualsFilter('id', Defaults::SALES_CHANNEL_TYPE_STOREFRONT)), $context)->first();
if (!$salesChannelType) return [];
$salesChannelIds = [];
$salesChannelResult = $salesChannelRepository->searchIds((new Criteria())->addFilter(new EqualsFilter('typeId', $salesChannelType->getId())), $context);
if ($salesChannelResult->firstId()) {
foreach ($salesChannelResult->getIds() as $id) {
$salesChannelIds[] = ['id' => $id];
}
}
return $salesChannelIds;
}
private function addTranslationsNewFields(Context $context, bool $true)
{
/** @var EntityRepositoryInterface $shopSwitchRuleRepository */
$shopSwitchRuleRepository = $this->container->get('acris_switch_rule.repository');
$shopSwitchRuleResult = $shopSwitchRuleRepository->search(new Criteria(), $context);
/** @var ShopSwitchRuleEntity $shopSwitchRuleEntity */
foreach ($shopSwitchRuleResult->getElements() as $shopSwitchRuleEntity) {
$shopSwitchRuleRepository->upsert([[
'id' => $shopSwitchRuleEntity->getId(),
'translations' => [
'de-DE' => [
'textButton' => 'Bestätigen',
'labelCountry' => 'Land',
'labelLanguage' => 'Sprache'
],
'en-GB' => [
'textButton' => 'Enter',
'labelCountry' => 'Country',
'labelLanguage' => 'Language'
],
[
'textButton' => 'Enter',
'labelCountry' => 'Country',
'labelLanguage' => 'Language',
'languageId' => Defaults::LANGUAGE_SYSTEM
]
],
]], $context);
}
}
private function insertDefaultImportProfile(Context $context)
{
/** @var EntityRepositoryInterface $profileRepository */
$profileRepository = $this->container->get('import_export_profile.repository');
$defaultProfiles = [
[
'name' => self::DEFAULT_PRODUCT_IMPORT_NAME,
'fileType' => 'text/csv',
'delimiter' => ';',
'enclosure' => '"',
'sourceEntity' => 'acris_switch_exclusion',
'mapping' => $this->getDefaultImportProfileMappingData(),
'systemDefault' => false,
'translations' => [
'de-DE' => [
'label' => self::DEFAULT_PRODUCT_IMPORT_NAME_DE
],
'en-GB' => [
'label' => self::DEFAULT_PRODUCT_IMPORT_NAME_EN
],
[
'label' => self::DEFAULT_PRODUCT_IMPORT_NAME_EN,
'languageId' => Defaults::LANGUAGE_SYSTEM
]
]
]
];
foreach ($defaultProfiles as $defaultProfile) {
$this->createImportProfileIfNotExists($profileRepository, $context, $defaultProfile);
}
}
private function getDefaultImportProfileMappingData()
{
return array(
["id"=>"ae49a685ac014e2a8bd863265fa10a00","key"=>"id","mappedKey"=>"id"],["id"=>"8422635b72574b5f82c43ccd571ea923","key"=>"active","mappedKey"=>"active"],["id"=>"dec83b5346444670a6343272829152eb","key"=>"type","mappedKey"=>"type"],["id"=>"ec08e8124ea1468caca7f5c0468684e3","key"=>"searchUrlBy","mappedKey"=>"searchUrlBy"],["id"=>"4137c60c60ec4031b570b6ad656d324d","key"=>"regex","mappedKey"=>"regex"],["id"=>"f576d1d12c6745f78b53d9348657eeed","key"=>"url","mappedKey"=>"url"],["id"=>"e246779168634e3d84498edb34585c17","key"=>"ip","mappedKey"=>"ip"]
);
}
private function createImportProfileIfNotExists(EntityRepositoryInterface $entityRepository, Context $context, array $profileData): void
{
$exists = $entityRepository->search((new Criteria())->addFilter(new EqualsFilter('name', $profileData['name'])), $context);
if($exists->getTotal() === 0) {
$entityRepository->create([$profileData], $context);
}
}
private function removeImportExportProfiles(Context $context): void
{
$connection = $this->container->get(Connection::class);
$importExportProfileRepository = $this->container->get('import_export_profile.repository');
$importExportLogRepository = $this->container->get('import_export_log.repository');
/** @var EntitySearchResult $searchResult */
$searchResult = $importExportProfileRepository->search((new Criteria())->addFilter(new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('sourceEntity', 'product'),
new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('name', self::DEFAULT_PRODUCT_IMPORT_NAME)
])
])), $context);
$ids = [];
/** @var \Shopware\Core\Framework\Uuid\Uuid $uuid */
$uuid = new \Shopware\Core\Framework\Uuid\Uuid();
if($searchResult->getTotal() > 0 && $searchResult->first()) {
/** @var ImportExportProfileEntity $entity */
foreach ($searchResult->getEntities()->getElements() as $entity) {
if ($entity->getSystemDefault() === true) {
$importExportProfileRepository->update([
['id' => $entity->getId(), 'systemDefault' => false ]
], $context);
}
/** @var EntitySearchResult $logResult */
$logResult = $importExportLogRepository->search((new Criteria())->addFilter(new EqualsFilter('profileId', $entity->getId())), $context);
if ($logResult->getTotal() > 0 && $logResult->first()) {
/** @var ImportExportLogEntity $logEntity */
foreach ($logResult->getEntities() as $logEntity) {
$stmt = $connection->prepare("UPDATE import_export_log SET profile_id = :profileId WHERE id = :id");
$stmt->execute(['profileId' => null, 'id' => $uuid::fromHexToBytes($logEntity->getId()) ]);
}
}
$ids[] = ['id' => $entity->getId()];
}
$importExportProfileRepository->delete($ids, $context);
}
}
private function insertDefaultExclusions(Context $context, bool $isActive): void
{
if($isActive !== true) {
return;
}
$exclusionRepository = $this->container->get('acris_switch_exclusion.repository');
$data = [
'active' => true,
'type' => ShopSwitchExclusionDefinition::EXCLUSION_TYPE_URL,
'searchUrlBy' => ShopSwitchExclusionDefinition::EXCLUSION_SEARCH_URL_BY_REGEX,
'regex' => '\/stripe-payment\/'
];
$this->createIfNotExists($exclusionRepository, [['name' => 'regex', 'value' => $data['regex']]], $data, $context);
}
private function createIfNotExists(EntityRepositoryInterface $repository, array $equalFields, array $data, Context $context)
{
$filters = [];
foreach ($equalFields as $equalField) {
$filters[] = new EqualsFilter($equalField['name'], $equalField['value']);
}
if(sizeof($filters) > 1) {
$filter = new MultiFilter(MultiFilter::CONNECTION_OR, $filters);
} else {
$filter = array_shift($filters);
}
$searchResult = $repository->search((new Criteria())->addFilter($filter), $context);
if($searchResult->count() == 0) {
$repository->create([$data], $context);
}
}
}