<?php declare(strict_types=1);
namespace Cogi\Affiliate\Ambassador;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Shopware\Core\Content\ImportExport\Exception\FileNotFoundException;
use Shopware\Core\Content\MailTemplate\Aggregate\MailTemplateType\MailTemplateTypeEntity;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
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\Framework\Uuid\Uuid;
use Shopware\Core\System\CustomField\CustomFieldTypes;
use Shopware\Core\System\Language\LanguageEntity;
class CogiAffiliateAmbassador extends Plugin
{
// Mails
public const AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME = 'ca_ambassador_affiliate_contract_pdf';
/**
* Installs the plugin (Email templates, custom field set)
* @param InstallContext $installContext
* @return void
*/
public function install(InstallContext $installContext): void
{
// Install custom field sets
$this->installCustomFieldSets($installContext->getContext());
// Install email templates
$this->installEmailTemplates($installContext->getContext());
}
/**
* postUpdate installs scheduled task, email templates and custom field sets, if not existent
* @param UpdateContext $updateContext
* @return void
*/
public function postUpdate(UpdateContext $updateContext): void
{
parent::postUpdate($updateContext);
// Update custom field sets
$this->removeCustomFieldSets($updateContext->getContext());
$this->installCustomFieldSets($updateContext->getContext());
// Update email templates
$this->installEmailTemplates($updateContext->getContext());
}
/**
* Uninstalls the extension
* @param UninstallContext $uninstallContext
* @return void
*/
public function uninstall(UninstallContext $uninstallContext): void
{
parent::uninstall($uninstallContext);
if ($uninstallContext->keepUserData()) {
return;
}
// Uninstall custom field sets
$this->removeCustomFieldSets($uninstallContext->getContext());
// Uninstall email templates
$this->removeEmailTemplate(self::AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME, $uninstallContext->getContext());
}
/**
* Installs the custom field sets
* @param Context $context
* @return void
*/
public function installCustomFieldSets(Context $context) {
$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$productFieldSetId = $this->getFieldSetId($customFieldSetRepository, 'cogi_affiliate_ambassador_product_set', $context);
if (!$productFieldSetId) {
$customFieldSetRepository->create([[
'name' => 'cogi_affiliate_ambassador_product_set',
'customFields' => [
[
'name' => 'ca_ambassador_provision_rate',
'type' => 'number',
'config' => [
'label' => [
'en-GB' => 'Provision rate for ambassadors',
'de-DE' => 'Provisionsrate für Botschafter'
],
'placeholder' => [
'en-GB' => 'In percent (0 - 100)',
'de-DE' => 'In Prozent (0 - 100)'
],
'helpText' => [
'en-GB' => 'If an ambassador bought this product, he will receive the specified provision rate.',
'de-DE' => 'Wenn ein Botschafter dieses Produkt gekauft hat, erhält er die angegebene Provisionsrate.'
],
'numberType' => CustomFieldTypes::FLOAT,
'componentName' => 'sw-field',
'customFieldType' => 'number',
'max' => 100,
'min' => 0,
'step' => 0.1,
'customFieldPosition' => 1,
'translated' => false
]
]
],
'relations' => [
[
'entityName' => 'product'
]
],
'config' => [
'label' => [
'en-GB' => 'Affiliate Marketing Ambassador products',
'de-DE' => 'Affiliate-Marketing Botschafter-Produkte'
],
'translated' => true
],
]], $context);
}
$affiliateFieldSetId = $this->getFieldSetId($customFieldSetRepository, 'cogi_affiliate_ambassador_customer_set', $context);
if (!$affiliateFieldSetId) {
$customFieldSetRepository->create([[
'name' => 'cogi_affiliate_ambassador_customer_set',
'customFields' => [
[
'name' => 'ca_ambassador_superior_affiliate_id',
'type' => CustomFieldTypes::ENTITY,
'config' => [
'entity' => 'customer',
'label' => [
'en-GB' => 'Assign superior ambassador',
'de-DE' => 'Übergeordneten Botschafter zuweisen'
],
'placeholder' => [
'en-GB' => 'Superior ambassador',
'de-DE' => 'Übergeordneter Botschafter'
],
'helpText' => [
'en-GB' => 'The superior ambassador benefits from the provision that this affiliate generates',
'de-DE' => 'Der übergeordnete Botschafter profitiert von der Provision, welche dieser Affiliate generiert'
],
'componentName' => 'sw-entity-single-select',
'customFieldType' => CustomFieldTypes::ENTITY,
'customFieldPosition' => 1,
'labelProperty' => ["firstName", "lastName"],
'translated' => false
]
],[
'name' => 'ca_ambassador_contract_id',
'type' => CustomFieldTypes::MEDIA,
'config' => [
'label' => [
'en-GB' => 'Contract PDF',
'de-DE' => 'Vertrags-PDF'
],
'helpText' => [
'en-GB' => 'Automatically generated during application, if activated in the configuration',
'de-DE' => 'Wird bei der Bewerbung automatisch generiert, falls in der Konfiguration aktiviert'
],
'componentName' => 'sw-media-field',
'customFieldType' => CustomFieldTypes::MEDIA,
'customFieldPosition' => 2,
'translated' => false
]
]
],
'relations' => [
[
'entityName' => 'customer'
]
],
'config' => [
'label' => [
'en-GB' => 'Affiliate Marketing Ambassador',
'de-DE' => 'Affiliate-Marketing Botschafter'
],
'translated' => true
],
]], $context);
}
}
/**
* Removes the custom field sets
* @param Context $context
* @return void
*/
public function removeCustomFieldSets(Context $context)
{
$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$this->removeCustomFieldSet($customFieldSetRepository, 'cogi_affiliate_ambassador_product_set', $context);
$this->removeCustomFieldSet($customFieldSetRepository, 'cogi_affiliate_ambassador_customer_set', $context);
}
/**
* Removes a specific custom field set
* @param $customFieldSetRepository
* @param string $setName
* @param Context $context
* @return void
*/
public function removeCustomFieldSet($customFieldSetRepository, string $setName, Context $context)
{
$fieldSetId = $this->getFieldSetId($customFieldSetRepository, $setName, $context);
if ($fieldSetId) {
$customFieldSetRepository->delete([["id" => $fieldSetId]], $context);
}
}
/**
* Gets a specific custom field set id
* @param $customFieldSetRepository
* @param string $setName
* @param Context $context
* @return string|null
*/
public function getFieldSetId($customFieldSetRepository, string $setName, Context $context): ?string
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('custom_field_set.name', $setName));
$customFieldSet = $customFieldSetRepository->search($criteria, $context)->first();
return (!$customFieldSet ? null : $customFieldSet->getId());
}
/**
* Installs all email templates
* @param Context $context
* @return void
*/
public function installEmailTemplates(Context $context) {
// To affiliate: Contract PDF
$this->addEmailTemplate(
[
'en-GB' => 'Affiliate Marketing Ambassador (Affiliate): Contract PDF',
'de-DE' => 'Affiliate-Marketing Botschafter (Affiliate): Contract PDF'
],
self::AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME,
[
'en-GB' => 'Ambassador contract',
'de-DE' => 'Botschafter-Vertrag'
],
[
'en-GB' => 'This template is sent if contract documents are enabled.',
'de-DE' => 'Dieses Template wird gesendet, wenn Vertragsdokumente aktiviert sind.'
],
[
'customer' => 'customer'
], $context);
}
/**
* Adds a single email template, if it does not already exist
* @param $templateTypeName
* @param $templateTypeTechnicalName
* @param $mailSubject
* @param $mailDescription
* @param $availableEntities
* @param Context $context
* @return void
*/
public function addEmailTemplate($templateTypeName, $templateTypeTechnicalName, $mailSubject, $mailDescription, $availableEntities, Context $context)
{
/** @var EntityRepositoryInterface $mailTemplateTypeRepository */
$mailTemplateTypeRepository = $this->container->get('mail_template_type.repository');
/** @var EntityRepositoryInterface $mailTemplateRepository */
$mailTemplateRepository = $this->container->get('mail_template.repository');
$mailTemplateTypeId = Uuid::randomHex();
$mailTemplateType = [
[
'id' => $mailTemplateTypeId,
'name' => $templateTypeName,
'technicalName' => $templateTypeTechnicalName,
'availableEntities' => $availableEntities
]
];
// Add fallback
$defaultLocaleCode = $this->getDefaultLocaleCode($context);
if (!in_array($defaultLocaleCode, ['de-DE', 'en-GB'])) {
$mailTemplateType[0]['name'][$defaultLocaleCode] = $templateTypeName['en-GB'];
}
$mailTemplate = [
[
'id' => Uuid::randomHex(),
'mailTemplateTypeId' => $mailTemplateTypeId,
'senderName' => [
'en-GB' => '{{ salesChannel.translated.name }}',
'de-DE' => '{{ salesChannel.translated.name }}'
],
'subject' => $mailSubject,
'description' => $mailDescription,
'contentPlain' => [
'en-GB' => $this->getMailContent('en-GB', $templateTypeTechnicalName, 'plain'),
'de-DE' => $this->getMailContent('de-DE', $templateTypeTechnicalName, 'plain')
],
'contentHtml' => [
'en-GB' => $this->getMailContent('en-GB', $templateTypeTechnicalName, 'html'),
'de-DE' => $this->getMailContent('de-DE', $templateTypeTechnicalName, 'html')
]
]
];
// Add fallback
if (!in_array($defaultLocaleCode, ['de-DE', 'en-GB'])) {
$mailTemplate[0]['senderName'][$defaultLocaleCode] = '{{ salesChannel.translated.name }}';
$mailTemplate[0]['subject'][$defaultLocaleCode] = $mailSubject['en-GB'];
$mailTemplate[0]['description'][$defaultLocaleCode] = $mailDescription['en-GB'];
$mailTemplate[0]['contentPlain'][$defaultLocaleCode] = $this->getMailContent('en-GB', $templateTypeTechnicalName, 'plain');
$mailTemplate[0]['contentHtml'][$defaultLocaleCode] = $this->getMailContent('en-GB', $templateTypeTechnicalName, 'html');
}
try {
$mailTemplateTypeRepository->create($mailTemplateType, $context);
$mailTemplateRepository->create($mailTemplate, $context);
} catch (UniqueConstraintViolationException $exception) {}
}
/**
* Gets the default locale code
* @param $context
* @return string
*/
private function getDefaultLocaleCode($context): string {
/** @var EntityRepository $languageRepository */
$languageRepository = $this->container->get('language.repository');
$criteria = new Criteria();
$criteria->addAssociation('locale');
$criteria->addFilter(new EqualsFilter('id', Defaults::LANGUAGE_SYSTEM));
/** @var LanguageEntity $languageEntity */
$languageEntity = $languageRepository->search($criteria, $context)->get(Defaults::LANGUAGE_SYSTEM);
return $languageEntity->getLocale()->getCode();
}
/**
* Gets the content of a mail while considering the locale
* @param string $locale
* @param string $prefix
* @param string $type
* @return string
*/
private function getMailContent(string $locale, string $prefix, string $type): string {
$path = $this->getPath() . '/Resources/email/' . $locale . '/';
switch ($type) {
case 'html':
$ext = 'html';
break;
case 'plain':
$ext = 'txt';
break;
default:
$ext = 'txt';
}
$file = $path . $prefix . '.' . $ext;
if (!is_file($file)) {
throw new FileNotFoundException($file);
}
return file_get_contents($file);
}
/**
* Removes a specific email template by templateTypeTechnicalName
* @param $templateTypeTechnicalName
* @param Context $context
* @return void
*/
public function removeEmailTemplate($templateTypeTechnicalName, Context $context) {
/** @var EntityRepositoryInterface $mailTemplateTypeRepository */
$mailTemplateTypeRepository = $this->container->get('mail_template_type.repository');
/** @var EntityRepositoryInterface $mailTemplateRepository */
$mailTemplateRepository = $this->container->get('mail_template.repository');
/** @var MailTemplateTypeEntity $customMailTemplateType */
$customMailTemplateType = $mailTemplateTypeRepository->search(
(new Criteria())
->addFilter(new EqualsFilter('technicalName', $templateTypeTechnicalName)),
$context
)->first();
if ($customMailTemplateType) {
$mailTemplateIds = $mailTemplateRepository->searchIds(
(new Criteria())
->addFilter(new EqualsFilter('mailTemplateTypeId', $customMailTemplateType->getId())),
$context
)->getIds();
$ids = array_map(static function ($id) {
return ['id' => $id];
}, $mailTemplateIds);
$mailTemplateRepository->delete($ids, $context);
// Delete the TemplateType which were added by this Plugin
$mailTemplateTypeRepository->delete([
['id' => $customMailTemplateType->getId()]
], $context);
}
}
}