<?php declare(strict_types=1);
namespace Acris\DiscountGroup;
use Doctrine\DBAL\Connection;
use Shopware\Core\Content\ImportExport\ImportExportProfileEntity;
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\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\InstallContext;
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
use Shopware\Core\Framework\Plugin\Context\UpdateContext;
use Shopware\Core\System\CustomField\CustomFieldTypes;
use Shopware\Core\System\Snippet\SnippetEntity;
class AcrisDiscountGroupCS extends Plugin
{
/** @deprecated */
const CUSTOM_FIELD_SET_NAME_DISCOUNT_GROUP = 'acris_discount_group';
const CUSTOM_FIELD_SET_NAME_CUSTOMER_DISCOUNT_GROUP = 'acris_discount_group_customer';
const CUSTOM_FIELD_SET_NAME_PRODUCT_DISCOUNT_GROUP = 'acris_discount_group_product';
const IMPORT_EXPORT_PROFILE_NAME = 'ACRIS Discount Groups';
public function install(InstallContext $context): void
{
$this->addCustomFields($context->getContext());
$this->addImportExportProfile($context->getContext());
}
public function postUpdate(UpdateContext $updateContext): void
{
if(version_compare($updateContext->getCurrentPluginVersion(), '1.2.0', '<') && $updateContext->getPlugin()->isActive() === true) {
$this->addImportExportProfile($updateContext->getContext());
}
if(version_compare($updateContext->getCurrentPluginVersion(), '1.4.0', '<')
&& version_compare($updateContext->getUpdatePluginVersion(), '1.4.0', '>=')) {
$this->addCustomFields($updateContext->getContext());
}
}
public function uninstall(UninstallContext $context): void
{
if ($context->keepUserData()) {
return;
}
$this->cleanupImportExportProfile($context->getContext());
$this->removeCustomFields($context->getContext(), [self::CUSTOM_FIELD_SET_NAME_DISCOUNT_GROUP, self::CUSTOM_FIELD_SET_NAME_PRODUCT_DISCOUNT_GROUP, self::CUSTOM_FIELD_SET_NAME_CUSTOMER_DISCOUNT_GROUP]);
$this->cleanupDatabase();
}
private function cleanupDatabase(): void
{
$connection = $this->container->get(Connection::class);
$connection->executeStatement('DROP TABLE IF EXISTS acris_discount_group_rule');
$connection->executeStatement('DROP TABLE IF EXISTS acris_discount_dynamic_groups');
$connection->executeStatement('DROP TABLE IF EXISTS acris_discount_group');
$connection->executeStatement('DROP TABLE IF EXISTS acris_discount_group_translation');
$connection->executeUpdate('ALTER TABLE `rule` DROP COLUMN `acrisDiscountGroups`');
$connection->executeUpdate('ALTER TABLE `product_stream` DROP COLUMN `acrisDiscountGroups`');
$connection->executeUpdate('ALTER TABLE `product` DROP COLUMN `acrisDiscountGroups`');
$connection->executeUpdate('ALTER TABLE `customer` DROP COLUMN `acrisDiscountGroups`');
}
private function addCustomFields(Context $context): void
{
/* Check for snippets if they exist for custom fields */
$this->checkForExistingCustomFieldSnippets($context);
$this->removeCustomFields($context, [self::CUSTOM_FIELD_SET_NAME_DISCOUNT_GROUP]);
$customFieldSet = $this->container->get('custom_field_set.repository');
if($customFieldSet->search((new Criteria())->addFilter(new EqualsFilter('name', self::CUSTOM_FIELD_SET_NAME_CUSTOMER_DISCOUNT_GROUP)), $context)->count() == 0) {
$customFieldSet->create([[
'name' => self::CUSTOM_FIELD_SET_NAME_CUSTOMER_DISCOUNT_GROUP,
'config' => [
'label' => [
'en-GB' => 'Customer discount group',
'de-DE' => 'Kunden-Rabattgruppe'
]
],
'customFields' => [
['name' => 'acris_discount_group_customer_value', 'type' => CustomFieldTypes::TEXT,
'config' => [
'componentName' => 'sw-field',
'type' => 'text',
'customFieldType' => 'text',
'customFieldPosition' => 1,
'label' => [
'en-GB' => 'Customer discount group',
'de-DE' => 'Kunden-Rabattgruppe'
],
'helpText' => [
'en-GB' => 'The customer discount group can be used via the ACRIS plugin to allow multiple customers with the same customer discount group to receive a discount.',
'de-DE' => 'Die Kunden-Rabattgruppe kann über das ACRIS Plugin verwendet werden, um mehreren Kunden mit derselben Kunden-Rabattgruppe einen Rabatt zu ermöglichen.'
]
]]
],
'relations' => [
[
'entityName' => 'customer'
]
]
]], $context);
};
if($customFieldSet->search((new Criteria())->addFilter(new EqualsFilter('name', self::CUSTOM_FIELD_SET_NAME_PRODUCT_DISCOUNT_GROUP)), $context)->count() == 0) {
$customFieldSet->create([[
'name' => self::CUSTOM_FIELD_SET_NAME_PRODUCT_DISCOUNT_GROUP,
'config' => [
'label' => [
'en-GB' => 'Merchandise group (discount group)',
'de-DE' => 'Warengruppe (Rabattgruppe)'
]
],
'customFields' => [
['name' => 'acris_discount_group_product_value', 'type' => CustomFieldTypes::TEXT,
'config' => [
'componentName' => 'sw-field',
'type' => 'text',
'customFieldType' => 'text',
'customFieldPosition' => 1,
'label' => [
'en-GB' => 'Merchandise group (discount group)',
'de-DE' => 'Warengruppe (Rabattgruppe)'
],
'helpText' => [
'en-GB' => 'The merchandise group (discount group) can be used via the ACRIS plugin to allow all products with the same merchandise group (discount group) to receive a discount.',
'de-DE' => 'Die Warengruppe (Rabattgruppe) kann über das ACRIS Plugin verwendet werden, um allen Produkten mit derselben Warengruppe (Rabattgruppe) einen Rabatt zu ermöglichen.'
]
]]
],
'relations' => [
[
'entityName' => 'product'
]
]
]], $context);
};
}
private function removeCustomFields(Context $context, array $setNames): void
{
/* Check for snippets if they exist for custom fields */
$this->checkForExistingCustomFieldSnippets($context);
$customFieldSet = $this->container->get('custom_field_set.repository');
foreach ($setNames as $setName) {
$id = $customFieldSet->searchIds((new Criteria())->addFilter(new EqualsFilter('name', $setName)), $context)->firstId();
if($id) $customFieldSet->delete([['id' => $id]], $context);
}
}
private function checkForExistingCustomFieldSnippets(Context $context)
{
/** @var EntityRepositoryInterface $snippetRepository */
$snippetRepository = $this->container->get('snippet.repository');
$criteria = new Criteria();
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('translationKey', 'customFields.' . 'acris_discount_group_value'),
new EqualsFilter('translationKey', 'customFields.' . 'acris_discount_group_customer_value'),
new EqualsFilter('translationKey', 'customFields.' . 'acris_discount_group_product_value'),
]));
/** @var EntitySearchResult $searchResult */
$searchResult = $snippetRepository->search($criteria, $context);
if ($searchResult->count() > 0) {
$snippetIds = [];
/** @var SnippetEntity $snippet */
foreach ($searchResult->getEntities()->getElements() as $snippet) {
$snippetIds[] = [
'id' => $snippet->getId()
];
}
if (!empty($snippetIds)) {
$snippetRepository->delete($snippetIds, $context);
}
}
}
private function addImportExportProfile(Context $context): void
{
$importExportProfileRepository = $this->container->get('import_export_profile.repository');
foreach ($this->getOptimizedSystemDefaultProfiles() as $profile) {
$this->createIfNotExists($importExportProfileRepository, [['name' => 'name', 'value' => $profile['name']]], $profile, $context);
}
}
private function getOptimizedSystemDefaultProfiles(): array
{
return [
[
'name' => self::IMPORT_EXPORT_PROFILE_NAME,
'label' => self::IMPORT_EXPORT_PROFILE_NAME,
'systemDefault' => true,
'sourceEntity' => 'acris_discount_group',
'fileType' => 'text/csv',
'delimiter' => ';',
'enclosure' => '"',
'mapping' => [
['key' => 'id', 'mappedKey' => 'id'],
['key' => 'internalName', 'mappedKey' => 'internalName'],
['key' => 'active', 'mappedKey' => 'active'],
['key' => 'activeFrom', 'mappedKey' => 'activeFrom'],
['key' => 'activeUntil', 'mappedKey' => 'activeUntil'],
['key' => 'priority', 'mappedKey' => 'priority'],
['key' => 'excluded', 'mappedKey' => 'excluded'],
['key' => 'customerAssignmentType', 'mappedKey' => 'customerAssignmentType'],
['key' => 'customer.id', 'mappedKey' => 'customerId'],
['key' => 'discountGroup', 'mappedKey' => 'categoryDiscountGroup'],
['key' => 'rules', 'mappedKey' => 'ruleIds'],
['key' => 'productAssignmentType', 'mappedKey' => 'productAssignmentType'],
['key' => 'product.id', 'mappedKey' => 'productId'],
['key' => 'materialGroup', 'mappedKey' => 'productDiscountGroup'],
['key' => 'productStreams', 'mappedKey' => 'productStreamIds'],
['key' => 'discountType', 'mappedKey' => 'discountType'],
['key' => 'discount', 'mappedKey' => 'discount'],
['key' => 'calculationType', 'mappedKey' => 'calculationType'],
['key' => 'listPriceType', 'mappedKey' => 'listPriceType'],
],
'translations' => [
'en-GB' => [
'label' => self::IMPORT_EXPORT_PROFILE_NAME
],
'de-DE' => [
'label' => self::IMPORT_EXPORT_PROFILE_NAME
]
],
],
];
}
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);
}
}
private function cleanupImportExportProfile(Context $context): void
{
$importExportProfile = $this->container->get('import_export_profile.repository');
$storeLocatorProfiles = $importExportProfile->search((new Criteria())->addFilter(new EqualsFilter('sourceEntity', 'acris_discount_group')), $context);
$ids = [];
if ($storeLocatorProfiles->getTotal() > 0 && $storeLocatorProfiles->first()) {
/** @var ImportExportProfileEntity $entity */
foreach ($storeLocatorProfiles->getEntities() as $entity) {
if ($entity->getSystemDefault() === true) {
$importExportProfile->update([
['id' => $entity->getId(), 'systemDefault' => false ]
], $context);
}
$ids[] = ['id' => $entity->getId()];
}
$importExportProfile->delete($ids, $context);
}
}
}