custom/plugins/CogiAffiliateAmbassador/src/CogiAffiliateAmbassador.php line 22

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Cogi\Affiliate\Ambassador;
  3. use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
  4. use Shopware\Core\Content\ImportExport\Exception\FileNotFoundException;
  5. use Shopware\Core\Content\MailTemplate\Aggregate\MailTemplateType\MailTemplateTypeEntity;
  6. use Shopware\Core\Defaults;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\Plugin;
  13. use Shopware\Core\Framework\Plugin\Context\InstallContext;
  14. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  15. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  16. use Shopware\Core\Framework\Uuid\Uuid;
  17. use Shopware\Core\System\CustomField\CustomFieldTypes;
  18. use Shopware\Core\System\Language\LanguageEntity;
  19. class CogiAffiliateAmbassador extends Plugin
  20. {
  21.     // Mails
  22.     public const AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME 'ca_ambassador_affiliate_contract_pdf';
  23.     /**
  24.      * Installs the plugin (Email templates, custom field set)
  25.      * @param InstallContext $installContext
  26.      * @return void
  27.      */
  28.     public function install(InstallContext $installContext): void
  29.     {
  30.         // Install custom field sets
  31.         $this->installCustomFieldSets($installContext->getContext());
  32.         // Install email templates
  33.         $this->installEmailTemplates($installContext->getContext());
  34.     }
  35.     /**
  36.      * postUpdate installs scheduled task, email templates and custom field sets, if not existent
  37.      * @param UpdateContext $updateContext
  38.      * @return void
  39.      */
  40.     public function postUpdate(UpdateContext $updateContext): void
  41.     {
  42.         parent::postUpdate($updateContext);
  43.         // Update custom field sets
  44.         $this->removeCustomFieldSets($updateContext->getContext());
  45.         $this->installCustomFieldSets($updateContext->getContext());
  46.         // Update email templates
  47.         $this->installEmailTemplates($updateContext->getContext());
  48.     }
  49.     /**
  50.      * Uninstalls the extension
  51.      * @param UninstallContext $uninstallContext
  52.      * @return void
  53.      */
  54.     public function uninstall(UninstallContext $uninstallContext): void
  55.     {
  56.         parent::uninstall($uninstallContext);
  57.         if ($uninstallContext->keepUserData()) {
  58.             return;
  59.         }
  60.         // Uninstall custom field sets
  61.         $this->removeCustomFieldSets($uninstallContext->getContext());
  62.         // Uninstall email templates
  63.         $this->removeEmailTemplate(self::AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME$uninstallContext->getContext());
  64.     }
  65.     /**
  66.      * Installs the custom field sets
  67.      * @param Context $context
  68.      * @return void
  69.      */
  70.     public function installCustomFieldSets(Context $context) {
  71.         $customFieldSetRepository $this->container->get('custom_field_set.repository');
  72.         $productFieldSetId $this->getFieldSetId($customFieldSetRepository'cogi_affiliate_ambassador_product_set'$context);
  73.         if (!$productFieldSetId) {
  74.             $customFieldSetRepository->create([[
  75.                 'name' => 'cogi_affiliate_ambassador_product_set',
  76.                 'customFields' => [
  77.                     [
  78.                         'name' => 'ca_ambassador_provision_rate',
  79.                         'type' => 'number',
  80.                         'config' => [
  81.                             'label' => [
  82.                                 'en-GB' => 'Provision rate for ambassadors',
  83.                                 'de-DE' => 'Provisionsrate für Botschafter'
  84.                             ],
  85.                             'placeholder' => [
  86.                                 'en-GB' => 'In percent (0 - 100)',
  87.                                 'de-DE' => 'In Prozent (0 - 100)'
  88.                             ],
  89.                             'helpText' => [
  90.                                 'en-GB' => 'If an ambassador bought this product, he will receive the specified provision rate.',
  91.                                 'de-DE' => 'Wenn ein Botschafter dieses Produkt gekauft hat, erhält er die angegebene Provisionsrate.'
  92.                             ],
  93.                             'numberType' => CustomFieldTypes::FLOAT,
  94.                             'componentName' => 'sw-field',
  95.                             'customFieldType' => 'number',
  96.                             'max' => 100,
  97.                             'min' => 0,
  98.                             'step' => 0.1,
  99.                             'customFieldPosition' => 1,
  100.                             'translated' => false
  101.                         ]
  102.                     ]
  103.                 ],
  104.                 'relations' => [
  105.                     [
  106.                         'entityName' => 'product'
  107.                     ]
  108.                 ],
  109.                 'config' => [
  110.                     'label' => [
  111.                         'en-GB' => 'Affiliate Marketing Ambassador products',
  112.                         'de-DE' => 'Affiliate-Marketing Botschafter-Produkte'
  113.                     ],
  114.                     'translated' => true
  115.                 ],
  116.             ]], $context);
  117.         }
  118.         $affiliateFieldSetId $this->getFieldSetId($customFieldSetRepository'cogi_affiliate_ambassador_customer_set'$context);
  119.         if (!$affiliateFieldSetId) {
  120.             $customFieldSetRepository->create([[
  121.                 'name' => 'cogi_affiliate_ambassador_customer_set',
  122.                 'customFields' => [
  123.                     [
  124.                         'name' => 'ca_ambassador_superior_affiliate_id',
  125.                         'type' => CustomFieldTypes::ENTITY,
  126.                         'config' => [
  127.                             'entity' => 'customer',
  128.                             'label' => [
  129.                                 'en-GB' => 'Assign superior ambassador',
  130.                                 'de-DE' => 'Übergeordneten Botschafter zuweisen'
  131.                             ],
  132.                             'placeholder' => [
  133.                                 'en-GB' => 'Superior ambassador',
  134.                                 'de-DE' => 'Übergeordneter Botschafter'
  135.                             ],
  136.                             'helpText' => [
  137.                                 'en-GB' => 'The superior ambassador benefits from the provision that this affiliate generates',
  138.                                 'de-DE' => 'Der übergeordnete Botschafter profitiert von der Provision, welche dieser Affiliate generiert'
  139.                             ],
  140.                             'componentName' => 'sw-entity-single-select',
  141.                             'customFieldType' => CustomFieldTypes::ENTITY,
  142.                             'customFieldPosition' => 1,
  143.                             'labelProperty' => ["firstName""lastName"],
  144.                             'translated' => false
  145.                         ]
  146.                     ],[
  147.                         'name' => 'ca_ambassador_contract_id',
  148.                         'type' => CustomFieldTypes::MEDIA,
  149.                         'config' => [
  150.                             'label' => [
  151.                                 'en-GB' => 'Contract PDF',
  152.                                 'de-DE' => 'Vertrags-PDF'
  153.                             ],
  154.                             'helpText' => [
  155.                                 'en-GB' => 'Automatically generated during application, if activated in the configuration',
  156.                                 'de-DE' => 'Wird bei der Bewerbung automatisch generiert, falls in der Konfiguration aktiviert'
  157.                             ],
  158.                             'componentName' => 'sw-media-field',
  159.                             'customFieldType' => CustomFieldTypes::MEDIA,
  160.                             'customFieldPosition' => 2,
  161.                             'translated' => false
  162.                         ]
  163.                     ]
  164.                 ],
  165.                 'relations' => [
  166.                     [
  167.                         'entityName' => 'customer'
  168.                     ]
  169.                 ],
  170.                 'config' => [
  171.                     'label' => [
  172.                         'en-GB' => 'Affiliate Marketing Ambassador',
  173.                         'de-DE' => 'Affiliate-Marketing Botschafter'
  174.                     ],
  175.                     'translated' => true
  176.                 ],
  177.             ]], $context);
  178.         }
  179.     }
  180.     /**
  181.      * Removes the custom field sets
  182.      * @param Context $context
  183.      * @return void
  184.      */
  185.     public function removeCustomFieldSets(Context $context)
  186.     {
  187.         $customFieldSetRepository $this->container->get('custom_field_set.repository');
  188.         $this->removeCustomFieldSet($customFieldSetRepository'cogi_affiliate_ambassador_product_set'$context);
  189.         $this->removeCustomFieldSet($customFieldSetRepository'cogi_affiliate_ambassador_customer_set'$context);
  190.     }
  191.     /**
  192.      * Removes a specific custom field set
  193.      * @param $customFieldSetRepository
  194.      * @param string $setName
  195.      * @param Context $context
  196.      * @return void
  197.      */
  198.     public function removeCustomFieldSet($customFieldSetRepositorystring $setNameContext $context)
  199.     {
  200.         $fieldSetId $this->getFieldSetId($customFieldSetRepository$setName$context);
  201.         if ($fieldSetId) {
  202.             $customFieldSetRepository->delete([["id" => $fieldSetId]], $context);
  203.         }
  204.     }
  205.     /**
  206.      * Gets a specific custom field set id
  207.      * @param $customFieldSetRepository
  208.      * @param string $setName
  209.      * @param Context $context
  210.      * @return string|null
  211.      */
  212.     public function getFieldSetId($customFieldSetRepositorystring $setNameContext $context): ?string
  213.     {
  214.         $criteria = new Criteria();
  215.         $criteria->addFilter(new EqualsFilter('custom_field_set.name'$setName));
  216.         $customFieldSet $customFieldSetRepository->search($criteria$context)->first();
  217.         return (!$customFieldSet null $customFieldSet->getId());
  218.     }
  219.     /**
  220.      * Installs all email templates
  221.      * @param Context $context
  222.      * @return void
  223.      */
  224.     public function installEmailTemplates(Context $context) {
  225.         // To affiliate: Contract PDF
  226.         $this->addEmailTemplate(
  227.             [
  228.                 'en-GB' => 'Affiliate Marketing Ambassador (Affiliate): Contract PDF',
  229.                 'de-DE' => 'Affiliate-Marketing Botschafter (Affiliate): Contract PDF'
  230.             ],
  231.             self::AFFILIATE_CONTRACT_PDF_TEMPLATE_TYPE_TECHNICAL_NAME,
  232.             [
  233.                 'en-GB' => 'Ambassador contract',
  234.                 'de-DE' => 'Botschafter-Vertrag'
  235.             ],
  236.             [
  237.                 'en-GB' => 'This template is sent if contract documents are enabled.',
  238.                 'de-DE' => 'Dieses Template wird gesendet, wenn Vertragsdokumente aktiviert sind.'
  239.             ],
  240.             [
  241.                 'customer' => 'customer'
  242.             ], $context);
  243.     }
  244.     /**
  245.      * Adds a single email template, if it does not already exist
  246.      * @param $templateTypeName
  247.      * @param $templateTypeTechnicalName
  248.      * @param $mailSubject
  249.      * @param $mailDescription
  250.      * @param $availableEntities
  251.      * @param Context $context
  252.      * @return void
  253.      */
  254.     public function addEmailTemplate($templateTypeName$templateTypeTechnicalName$mailSubject$mailDescription$availableEntitiesContext $context)
  255.     {
  256.         /** @var EntityRepositoryInterface $mailTemplateTypeRepository */
  257.         $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  258.         /** @var EntityRepositoryInterface $mailTemplateRepository */
  259.         $mailTemplateRepository $this->container->get('mail_template.repository');
  260.         $mailTemplateTypeId Uuid::randomHex();
  261.         $mailTemplateType = [
  262.             [
  263.                 'id' => $mailTemplateTypeId,
  264.                 'name' => $templateTypeName,
  265.                 'technicalName' => $templateTypeTechnicalName,
  266.                 'availableEntities' => $availableEntities
  267.             ]
  268.         ];
  269.         // Add fallback
  270.         $defaultLocaleCode $this->getDefaultLocaleCode($context);
  271.         if (!in_array($defaultLocaleCode, ['de-DE''en-GB'])) {
  272.             $mailTemplateType[0]['name'][$defaultLocaleCode] = $templateTypeName['en-GB'];
  273.         }
  274.         $mailTemplate = [
  275.             [
  276.                 'id' => Uuid::randomHex(),
  277.                 'mailTemplateTypeId' => $mailTemplateTypeId,
  278.                 'senderName' => [
  279.                     'en-GB' => '{{ salesChannel.translated.name }}',
  280.                     'de-DE' => '{{ salesChannel.translated.name }}'
  281.                 ],
  282.                 'subject' => $mailSubject,
  283.                 'description' => $mailDescription,
  284.                 'contentPlain' => [
  285.                     'en-GB' => $this->getMailContent('en-GB'$templateTypeTechnicalName'plain'),
  286.                     'de-DE' => $this->getMailContent('de-DE'$templateTypeTechnicalName'plain')
  287.                 ],
  288.                 'contentHtml' => [
  289.                     'en-GB' => $this->getMailContent('en-GB'$templateTypeTechnicalName'html'),
  290.                     'de-DE' => $this->getMailContent('de-DE'$templateTypeTechnicalName'html')
  291.                 ]
  292.             ]
  293.         ];
  294.         // Add fallback
  295.         if (!in_array($defaultLocaleCode, ['de-DE''en-GB'])) {
  296.             $mailTemplate[0]['senderName'][$defaultLocaleCode] = '{{ salesChannel.translated.name }}';
  297.             $mailTemplate[0]['subject'][$defaultLocaleCode] = $mailSubject['en-GB'];
  298.             $mailTemplate[0]['description'][$defaultLocaleCode] = $mailDescription['en-GB'];
  299.             $mailTemplate[0]['contentPlain'][$defaultLocaleCode] = $this->getMailContent('en-GB'$templateTypeTechnicalName'plain');
  300.             $mailTemplate[0]['contentHtml'][$defaultLocaleCode] = $this->getMailContent('en-GB'$templateTypeTechnicalName'html');
  301.         }
  302.         try {
  303.             $mailTemplateTypeRepository->create($mailTemplateType$context);
  304.             $mailTemplateRepository->create($mailTemplate$context);
  305.         } catch (UniqueConstraintViolationException $exception) {}
  306.     }
  307.     /**
  308.      * Gets the default locale code
  309.      * @param $context
  310.      * @return string
  311.      */
  312.     private function getDefaultLocaleCode($context): string {
  313.         /** @var EntityRepository $languageRepository */
  314.         $languageRepository $this->container->get('language.repository');
  315.         $criteria = new Criteria();
  316.         $criteria->addAssociation('locale');
  317.         $criteria->addFilter(new EqualsFilter('id'Defaults::LANGUAGE_SYSTEM));
  318.         /** @var LanguageEntity $languageEntity */
  319.         $languageEntity $languageRepository->search($criteria$context)->get(Defaults::LANGUAGE_SYSTEM);
  320.         return $languageEntity->getLocale()->getCode();
  321.     }
  322.     /**
  323.      * Gets the content of a mail while considering the locale
  324.      * @param string $locale
  325.      * @param string $prefix
  326.      * @param string $type
  327.      * @return string
  328.      */
  329.     private function getMailContent(string $localestring $prefixstring $type): string {
  330.         $path $this->getPath() . '/Resources/email/' $locale '/';
  331.         switch ($type) {
  332.             case 'html':
  333.                 $ext 'html';
  334.                 break;
  335.             case 'plain':
  336.                 $ext 'txt';
  337.                 break;
  338.             default:
  339.                 $ext 'txt';
  340.         }
  341.         $file $path $prefix '.' $ext;
  342.         if (!is_file($file)) {
  343.             throw new FileNotFoundException($file);
  344.         }
  345.         return file_get_contents($file);
  346.     }
  347.     /**
  348.      * Removes a specific email template by templateTypeTechnicalName
  349.      * @param $templateTypeTechnicalName
  350.      * @param Context $context
  351.      * @return void
  352.      */
  353.     public function removeEmailTemplate($templateTypeTechnicalNameContext $context) {
  354.         /** @var EntityRepositoryInterface $mailTemplateTypeRepository */
  355.         $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  356.         /** @var EntityRepositoryInterface $mailTemplateRepository */
  357.         $mailTemplateRepository $this->container->get('mail_template.repository');
  358.         /** @var MailTemplateTypeEntity $customMailTemplateType */
  359.         $customMailTemplateType $mailTemplateTypeRepository->search(
  360.             (new Criteria())
  361.                 ->addFilter(new EqualsFilter('technicalName'$templateTypeTechnicalName)),
  362.             $context
  363.         )->first();
  364.         if ($customMailTemplateType) {
  365.             $mailTemplateIds $mailTemplateRepository->searchIds(
  366.                 (new Criteria())
  367.                     ->addFilter(new EqualsFilter('mailTemplateTypeId'$customMailTemplateType->getId())),
  368.                 $context
  369.             )->getIds();
  370.             $ids array_map(static function ($id) {
  371.                 return ['id' => $id];
  372.             }, $mailTemplateIds);
  373.             $mailTemplateRepository->delete($ids$context);
  374.             // Delete the TemplateType which were added by this Plugin
  375.             $mailTemplateTypeRepository->delete([
  376.                 ['id' => $customMailTemplateType->getId()]
  377.             ], $context);
  378.         }
  379.     }
  380. }