custom/plugins/ShpclShipcloudConnector/src/ShpclShipcloudConnector.php line 21

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace ShpclShipcloudConnector;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\Exception;
  5. use Shopware\Core\Checkout\Order\OrderDefinition;
  6. use Shopware\Core\Content\ImportExport\Exception\FileNotFoundException;
  7. use Shopware\Core\Defaults;
  8. use Shopware\Core\Framework\Api\Context\SystemSource;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\Plugin;
  11. use Shopware\Core\Framework\Plugin\Context\InstallContext;
  12. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  13. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  14. use Shopware\Core\Content\MailTemplate\Aggregate\MailTemplateType\MailTemplateTypeEntity;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  17. use Shopware\Core\Framework\Uuid\Uuid;
  18. class ShpclShipcloudConnector extends Plugin {
  19.     const TEMPLATE_TYPE_TECHNICAL_NAME 'ship_cloud_url';
  20.     const TEMPLATE_TYPE_NAME 'ShipCloudURL';
  21.     public function install(InstallContext $context): void {
  22.         /** @var Connection $connection */
  23.         $connection $this->container->get('Doctrine\DBAL\Connection');
  24.         try {
  25.             $templateTypeData['technicalName'] = self::TEMPLATE_TYPE_TECHNICAL_NAME;
  26.             $templateTypeData['availableEntities'] = [
  27.                 'order' => 'order',
  28.                 'previousState' => 'state_machine_state',
  29.                 'newState' => 'state_machine_state',
  30.                 'salesChannel' => 'sales_channel'
  31.             ];
  32.             $templateTypeData['enName'] = self::TEMPLATE_TYPE_NAME "_EN";
  33.             $templateTypeData['deName'] = self::TEMPLATE_TYPE_NAME"_DE";
  34.             $mailTemplateTypeId $this->createMailTemplateType($connection$templateTypeData);
  35.             $templateData['en-GB']['senderName'] = '{{ salesChannel.name }}';
  36.             $templateData['en-GB']['subject'] = 'Return label for your order';
  37.             $templateData['en-GB']['description'] = '';
  38.             $templateData['en-GB']['contentHtml'] = $this->getMailContent('en-GB''url''html');
  39.             $templateData['en-GB']['contentPlain'] = $this->getMailContent('en-GB''url''plain');
  40.             $templateData['de-DE']['senderName'] = '{{ salesChannel.name }}';
  41.             $templateData['de-DE']['subject'] = 'Rücksendeetikett für Ihre Bestellung';
  42.             $templateData['de-DE']['description'] = '';
  43.             $templateData['de-DE']['contentHtml'] = $this->getMailContent('de-DE''url''html');
  44.             $templateData['de-DE']['contentPlain'] = $this->getMailContent('de-DE''url''plain');
  45.             $this->createMailTemplate($connection$mailTemplateTypeId$templateData);
  46.         } catch (\Exception $e) {
  47.         }
  48.     }
  49.     public function uninstall(UninstallContext $uninstallContext): void {
  50.         //Keep UserData? Then do nothing here
  51.         if ($uninstallContext->keepUserData()) {
  52.             return;
  53.         }
  54.         try {
  55.             $this->deleteMailTemplate($uninstallContext->getContext(), self::TEMPLATE_TYPE_TECHNICAL_NAME);
  56.         } catch (\Exception $e) {
  57.         }
  58.         /** @var Connection $connection */
  59.         try {
  60.             $connection $this->container->get(Connection::class);
  61.             $connection->exec('DROP TABLE s_shpcl_shipcloud_carriers');
  62.             $connection->exec('DROP TABLE s_shpcl_shipcloud_labels');
  63.             $connection->exec('DROP TABLE s_shpcl_shipcloud_tracker');
  64.             $connection->exec('DROP TABLE s_shpcl_shipping_attribute');
  65.             $connection->exec('Delete FROM system_config where configuration_key LIKE "%ShpclShipcloudConnector.config.%"');
  66.             $connection->exec('Delete FROM migration where class LIKE "%s_shpcl_shipcloud_carriers%"');
  67.             $connection->exec('Delete FROM migration where class LIKE "%s_shpcl_shipcloud_labels%"');
  68.             $connection->exec('Delete FROM migration where class LIKE "%s_shpcl_shipcloud_tracker%"');
  69.             $connection->exec('Delete FROM migration where class LIKE "%s_shpcl_shipping_attribute%"');
  70.         } catch (Exception $e) {
  71.         }
  72.     }
  73.     /**
  74.      * @param Connection $connection
  75.      * @param array $data
  76.      *
  77.      * @return string
  78.      *
  79.      * @throws DBALException
  80.      * @throws InconsistentCriteriaIdsException
  81.      * @throws InvalidUuidException
  82.      */
  83.     private function createMailTemplateType(Connection $connection, array $data): string {
  84.         $mailTemplateTypeId Uuid::randomHex();
  85.         $connection->insert('mail_template_type', [
  86.             'id' => Uuid::fromHexToBytes($mailTemplateTypeId),
  87.             'technical_name' => $data['technicalName'],
  88.             'available_entities' => json_encode($data['availableEntities']),
  89.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  90.         ]);
  91.         $connection->insert('mail_template_type_translation', [
  92.             'mail_template_type_id' => Uuid::fromHexToBytes($mailTemplateTypeId),
  93.             'language_id' => Uuid::fromHexToBytes($this->getLanguageIdByLocale('en-GB')),
  94.             'name' => $data['enName'],
  95.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  96.         ]);
  97.         $connection->insert('mail_template_type_translation', [
  98.             'mail_template_type_id' => Uuid::fromHexToBytes($mailTemplateTypeId),
  99.             'language_id' => Uuid::fromHexToBytes($this->getLanguageIdByLocale('de-DE')),
  100.             'name' => $data['deName'],
  101.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  102.         ]);
  103.         return $mailTemplateTypeId;
  104.     }
  105.     /**
  106.      * @param Connection $connection
  107.      * @param string $mailTemplateTypeId
  108.      * @param array $data
  109.      *
  110.      * @return void
  111.      *
  112.      * @throws Exception
  113.      */
  114.     private function createMailTemplate(Connection $connectionstring $mailTemplateTypeId, array $data): void {
  115.         $mailTemplateId Uuid::randomHex();
  116.         $connection->insert('mail_template', [
  117.             'id' => Uuid::fromHexToBytes($mailTemplateId),
  118.             'mail_template_type_id' => Uuid::fromHexToBytes($mailTemplateTypeId),
  119.             'system_default' => true,
  120.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  121.         ]);
  122.         $connection->insert('mail_template_translation', [
  123.             'mail_template_id' => Uuid::fromHexToBytes($mailTemplateId),
  124.             'language_id' => Uuid::fromHexToBytes($this->getLanguageIdByLocale('en-GB')),
  125.             'sender_name' => $data['en-GB']['senderName'],
  126.             'subject' => $data['en-GB']['subject'],
  127.             'description' => $data['en-GB']['description'],
  128.             'content_html' => $data['en-GB']['contentHtml'],
  129.             'content_plain' => $data['en-GB']['contentPlain'],
  130.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  131.         ]);
  132.         $connection->insert('mail_template_translation', [
  133.             'mail_template_id' => Uuid::fromHexToBytes($mailTemplateId),
  134.             'language_id' => Uuid::fromHexToBytes($this->getLanguageIdByLocale('de-DE')),
  135.             'sender_name' => $data['de-DE']['senderName'],
  136.             'subject' => $data['de-DE']['subject'],
  137.             'description' => $data['de-DE']['description'],
  138.             'content_html' => $data['de-DE']['contentHtml'],
  139.             'content_plain' => $data['de-DE']['contentPlain'],
  140.             'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT)
  141.         ]);
  142.     }
  143.     /**
  144.      * @param string $locale
  145.      *
  146.      * @return string
  147.      *
  148.      * @throws InconsistentCriteriaIdsException
  149.      */
  150.     private function getLanguageIdByLocale(string $locale): string {
  151.         $context = new Context(new SystemSource());
  152.         /** @var EntityRepository $languageRepository */
  153.         $languageRepository $this->container->get('language.repository');
  154.         $criteria = new Criteria();
  155.         $criteria->addAssociation('locale');
  156.         $criteria->addFilter(new EqualsFilter('locale.code'$locale));
  157.         /** @var LanguageEntity $languageEntity */
  158.         $languageEntity $languageRepository->search($criteria$context)->first();
  159.         return $languageEntity->getId();
  160.     }
  161.     /**
  162.      * @param string $locale
  163.      * @param string $prefix
  164.      * @param string $type
  165.      *
  166.      * @return string
  167.      */
  168.     private function getMailContent(string $localestring $prefixstring $type): string {
  169.         $path $this->getPath() . '/Resources/email/' $locale '/';
  170.         switch ($type) {
  171.             case 'html':
  172.                 $ext 'html';
  173.                 break;
  174.             case 'plain':
  175.                 $ext 'txt';
  176.                 break;
  177.             default:
  178.                 $ext 'txt';
  179.         }
  180.         $file $path $prefix '-' $type '.' $ext;
  181.         if (!is_file($file)) {
  182.             throw new FileNotFoundException($file);
  183.         }
  184.         return file_get_contents($file);
  185.     }
  186.     /**
  187.      * @param string $mailTemplateId
  188.      *
  189.      * @throws DBALException
  190.      */
  191.     private function deleteMailTemplateFromSalesChannels(string $mailTemplateId): void {
  192.         /** @var Connection $connection */
  193.         $connection $this->container->get('Doctrine\DBAL\Connection');
  194.         $connection->executeQuery('DELETE FROM `mail_template_sales_channel` WHERE `mail_template_id` = :id', ['id' => $mailTemplateId]);
  195.     }
  196.     /**
  197.      * @param Context $context
  198.      * @param string $technicalName
  199.      *
  200.      * @throws InconsistentCriteriaIdsException
  201.      * @throws DBALException
  202.      */
  203.     private function deleteMailTemplate(Context $contextstring $technicalName): void {
  204.         $mailTemplateTypeId $this->getMailTemplateTypeId($context$technicalName);
  205.         $mailTemplateId $this->getMailTemplateId($context$mailTemplateTypeId);
  206.         $this->deleteMailTemplateFromSalesChannels($mailTemplateId);
  207.         /** @var EntityRepository $mailTemplateRepository */
  208.         $mailTemplateRepository $this->container->get('mail_template.repository');
  209.         $mailTemplateRepository->delete([
  210.             [
  211.                 'id' => $mailTemplateId
  212.             ]
  213.         ], $context);
  214.     }
  215.     /**
  216.      * @param Context $context
  217.      * @param string $mailTemplateTypeId
  218.      *
  219.      * @return string
  220.      *
  221.      */
  222.     private function getMailTemplateId(Context $contextstring $mailTemplateTypeId): string {
  223.         /** @var EntityRepository $mailTemplateRepository */
  224.         $mailTemplateRepository $this->container->get('mail_template.repository');
  225.         $criteria = new Criteria();
  226.         $criteria->addFilter(new EqualsFilter('mailTemplateTypeId'$mailTemplateTypeId));
  227.         /** @var MailTemplateEntity $mailTemplateEntity */
  228.         $mailTemplateEntity $mailTemplateRepository->search($criteria$context)->first();
  229.         return $mailTemplateEntity->getId();
  230.     }
  231.     /**
  232.      * @param Context $context
  233.      * @param string $technicalName
  234.      *
  235.      * @throws InconsistentCriteriaIdsException
  236.      */
  237.     private function deleteMailTemplateType(Context $contextstring $technicalName): void {
  238.         $mailTemplateTypeId $this->getMailTemplateTypeId($context$technicalName);
  239.         /** @var EntityRepository $mailTemplateTypeRepository */
  240.         $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  241.         $mailTemplateTypeRepository->delete([
  242.             [
  243.                 'id' => $mailTemplateTypeId
  244.             ]
  245.         ], $context);
  246.     }
  247.     /**
  248.      * @param Context $context
  249.      * @param string $technicalName
  250.      *
  251.      * @return string
  252.      *
  253.      */
  254.     private function getMailTemplateTypeId(Context $contextstring $technicalName): string {
  255.         /** @var EntityRepository $mailTemplateTypeRepository */
  256.         $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  257.         $criteria = new Criteria();
  258.         $criteria->addFilter(new EqualsFilter('technicalName'$technicalName));
  259.         /** @var MailTemplateTypeEntity $mailTemplateTypeEntity */
  260.         $mailTemplateTypeEntity $mailTemplateTypeRepository->search($criteria$context)->first();
  261.         if ($mailTemplateTypeEntity !== null) return $mailTemplateTypeEntity->getId(); else
  262.             return "";
  263.     }
  264.     /**
  265.      * @param UpdateContext $updateContext
  266.      */
  267.     public function update(UpdateContext $updateContext): void {
  268.     }
  269.     /**
  270.      * @param InstallContext $installContext
  271.      */
  272.     public function postInstall(InstallContext $installContext): void {
  273.         $this->upsertExportInformationCustomFields();
  274.     }
  275.     /**
  276.      * @param UpdateContext $updateContext
  277.      */
  278.     public function postUpdate(UpdateContext $updateContext): void {
  279.         $this->upsertExportInformationCustomFields();
  280.     }
  281.     /**
  282.      * Custom fields
  283.      */
  284.     private function upsertExportInformationCustomFields(): void {
  285.         $db $this->container->get(Connection::class);
  286.         $technicalName 'shpcl_shipcloud';
  287.         $config = [
  288.             'label' => [
  289.                 'en-GB' => 'Shipment status',
  290.                 'de-DE' => 'Sendungsstatus',
  291.             ],
  292.             'translated' => true,
  293.         ];
  294.         $fields = [
  295.             [
  296.                 'name' => 'shpcl_hook_status',
  297.                 'type' => \Shopware\Core\System\CustomField\CustomFieldTypes::SELECT,
  298.                 'config' => [
  299.                     'label' => [
  300.                         'de-DE' => 'Sendungsstatus',
  301.                         'en-GB' => 'Shipment status',
  302.                     ],
  303.                     'options' => [
  304.                         [
  305.                             'value' => 'shipment.tracking.label_created',
  306.                             'label' => [
  307.                                 'de-DE' => 'Versandmarke erstellt',
  308.                                 'en-GB' => 'Label created',
  309.                             ]
  310.                         ],
  311.                         [
  312.                             'value' => 'shipment.tracking.picked_up',
  313.                             'label' => [
  314.                                 'de-DE' => 'Paket abgeholt',
  315.                                 'en-GB' => 'Picked Up',
  316.                             ]
  317.                         ],
  318.                         [
  319.                             'value' => 'shipment.tracking.transit',
  320.                             'label' => [
  321.                                 'de-DE' => 'Unterwegs',
  322.                                 'en-GB' => 'Transit',
  323.                             ]
  324.                         ],
  325.                         [
  326.                             'value' => 'shipment.tracking.out_for_delivery',
  327.                             'label' => [
  328.                                 'de-DE' => 'Bereit zur Auslieferung',
  329.                                 'en-GB' => 'Out for Delivery',
  330.                             ]
  331.                         ],
  332.                         [
  333.                             'value' => 'shipment.tracking.delivered',
  334.                             'label' => [
  335.                                 'de-DE' => 'Ausgeliefert',
  336.                                 'en-GB' => 'Delivered',
  337.                             ]
  338.                         ],
  339.                         [
  340.                             'value' => 'shipment.tracking.awaits_pickup_by_receiver',
  341.                             'label' => [
  342.                                 'de-DE' => 'Wartet auf Abholung durch Empfänger',
  343.                                 'en-GB' => 'Awaits pickup by receiver',
  344.                             ]
  345.                         ],
  346.                         [
  347.                             'value' => 'shipment.tracking.canceled',
  348.                             'label' => [
  349.                                 'de-DE' => 'Abgebrochen',
  350.                                 'en-GB' => 'Canceled',
  351.                             ]
  352.                         ],
  353.                         [
  354.                             'value' => 'shipment.tracking.delayed',
  355.                             'label' => [
  356.                                 'de-DE' => 'Verspäted',
  357.                                 'en-GB' => 'Delayed',
  358.                             ]
  359.                         ],
  360.                         [
  361.                             'value' => 'shipment.tracking.exception',
  362.                             'label' => [
  363.                                 'de-DE' => 'Fehler',
  364.                                 'en-GB' => 'Exception',
  365.                             ]
  366.                         ],
  367.                         [
  368.                             'value' => 'shipment.tracking.not_delivered',
  369.                             'label' => [
  370.                                 'de-DE' => 'Nicht ausgeliefert',
  371.                                 'en-GB' => 'Not Delivered',
  372.                             ]
  373.                         ],
  374.                         [
  375.                             'value' => 'shipment.tracking.notification',
  376.                             'label' => [
  377.                                 'de-DE' => 'Hinweis',
  378.                                 'en-GB' => 'Notification',
  379.                             ]
  380.                         ],
  381.                         [
  382.                             'value' => 'shipment.tracking.unknown',
  383.                             'label' => [
  384.                                 'de-DE' => 'Unbekannt',
  385.                                 'en-GB' => 'Unknown',
  386.                             ]
  387.                         ],
  388.                         [
  389.                             'value' => 'shipment.tracking.multi',
  390.                             'label' => [
  391.                                 'de-DE' => 'Mehrere Sendungen (Status uneindeutig)',
  392.                                 'en-GB' => 'Multi sates - not clear',
  393.                             ]
  394.                         ],
  395.                     ],
  396.                     'componentName' => 'sw-single-select',
  397.                     'customFieldType' => 'select',
  398.                     'customFieldPosition' => 0,
  399.                 ],
  400.             ]
  401.         ];
  402.         $db->executeUpdate('INSERT IGNORE INTO `custom_field_set`
  403.                 (id, name, config, active, created_at)
  404.             VALUES
  405.                 (:id, :name, :config, 1, NOW(3))
  406.             ON DUPLICATE KEY UPDATE
  407.                 `config` = VALUES(`config`),
  408.                 `updated_at` = NOW(3)', [
  409.             'id' => md5($technicalName),
  410.             // Workaround to avoid duplicates, see method createDefaultConfiguration()
  411.             'name' => $technicalName,
  412.             'config' => json_encode($config),
  413.         ]);
  414.         $setId $db->fetchColumn('SELECT `id` FROM `custom_field_set` WHERE `name` = :name', [
  415.             'name' => $technicalName,
  416.         ]);
  417.         foreach ($fields as $field) {
  418.             $field['id'] = Uuid::randomBytes();
  419.             $field['setId'] = $setId;
  420.             $field['config'] = json_encode($field['config']);
  421.             $db->executeUpdate('INSERT IGNORE INTO `custom_field`
  422.                     (id, name, type, config, active, set_id, created_at)
  423.                 VALUES
  424.                     (:id, :name, :type, :config, 1, :setId, NOW(3))
  425.                 ON DUPLICATE KEY UPDATE
  426.                     `config` = VALUES(`config`),
  427.                     `type` = VALUES(`type`),
  428.                     `updated_at` = NOW(3)'$field);
  429.         }
  430.         $db->executeUpdate('INSERT INTO custom_field_set_relation
  431.                 (id, set_id, entity_name, created_at)
  432.             VALUES
  433.                 (:id, :setId, :entityName, NOW(3))
  434.             ON DUPLICATE KEY UPDATE
  435.                 `updated_at` = NOW(3)', [
  436.             'id' => Uuid::randomBytes(),
  437.             'setId' => $setId,
  438.             'entityName' => OrderDefinition::ENTITY_NAME,
  439.         ]);
  440.     }
  441. }