custom/plugins/PickwareErpStarter/src/PickwareErpStarter.php line 52

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) Pickware GmbH. All rights reserved.
  4.  * This file is part of software that is released under a proprietary license.
  5.  * You must not copy, modify, distribute, make publicly available, or execute
  6.  * its contents or parts thereof without express permission by the copyright
  7.  * holder, unless otherwise permitted by law.
  8.  */
  9. declare(strict_types=1);
  10. namespace Pickware\PickwareErpStarter;
  11. use Doctrine\DBAL\Connection;
  12. use Pickware\BundleInstaller\BundleInstaller;
  13. use Pickware\DalBundle\DalBundle;
  14. use Pickware\DebugBundle\ShopwarePluginsDebugBundle;
  15. use Pickware\DocumentBundle\DocumentBundle;
  16. use Pickware\MoneyBundle\MoneyBundle;
  17. use Pickware\PickwareErpStarter\ImportExport\DependencyInjection\ExporterRegistryCompilerPass;
  18. use Pickware\PickwareErpStarter\ImportExport\DependencyInjection\ImporterRegistryCompilerPass;
  19. use Pickware\PickwareErpStarter\Installation\PickwareErpInstaller;
  20. use Pickware\PickwareErpStarter\Stock\Indexer\StockIndexer;
  21. use Pickware\PickwareErpStarter\Supplier\ProductSupplierConfigurationIndexer;
  22. use Pickware\PickwareErpStarter\SupplierOrder\Indexer\IncomingStockIndexer;
  23. use Pickware\ShopwareExtensionsBundle\PickwareShopwareExtensionsBundle;
  24. use Pickware\ShopwarePlugins\ShopwareIntegrationTestPlugin\ShopwareIntegrationTestPlugin;
  25. use Pickware\ValidationBundle\PickwareValidationBundle;
  26. use Shopware\Core\Framework\Bundle;
  27. use Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexerRegistry;
  28. use Shopware\Core\Framework\Migration\MigrationCollectionLoader;
  29. use Shopware\Core\Framework\Migration\MigrationRuntime;
  30. use Shopware\Core\Framework\Migration\MigrationSource;
  31. use Shopware\Core\Framework\Parameter\AdditionalBundleParameters;
  32. use Shopware\Core\Framework\Plugin;
  33. use Shopware\Core\Framework\Plugin\Context\ActivateContext;
  34. use Shopware\Core\Framework\Plugin\Context\InstallContext;
  35. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  36. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  37. use Shopware\Core\Framework\Struct\Collection;
  38. use SwagMigrationAssistant\Migration\Writer\WriterInterface;
  39. use SwagMigrationAssistant\SwagMigrationAssistant;
  40. use Symfony\Bridge\Monolog\Logger;
  41. use Symfony\Component\Config\FileLocator;
  42. use Symfony\Component\DependencyInjection\ContainerBuilder;
  43. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  44. if (file_exists(__DIR__ '/../vendor/pickware/dependency-loader/src/DependencyLoader.php')) {
  45.     require_once __DIR__ '/../vendor/pickware/dependency-loader/src/DependencyLoader.php';
  46. }
  47. class PickwareErpStarter extends Plugin
  48. {
  49.     public const DOCUMENT_TYPE_TECHNICAL_NAME_IMPORT 'pickware_erp_import';
  50.     public const DOCUMENT_TYPE_TECHNICAL_NAME_EXPORT 'pickware_erp_export';
  51.     public const DOCUMENT_TYPE_TECHNICAL_NAME_DESCRIPTION_MAPPING = [
  52.         self::DOCUMENT_TYPE_TECHNICAL_NAME_IMPORT => 'Imported file',
  53.         self::DOCUMENT_TYPE_TECHNICAL_NAME_EXPORT => 'Exported file',
  54.     ];
  55.     /**
  56.      * @var class-string<Bundle>[]
  57.      */
  58.     private const ADDITIONAL_BUNDLES = [
  59.         DalBundle::class,
  60.         DocumentBundle::class,
  61.         MoneyBundle::class,
  62.         ShopwarePluginsDebugBundle::class,
  63.         PickwareShopwareExtensionsBundle::class,
  64.         PickwareValidationBundle::class,
  65.     ];
  66.     public function getAdditionalBundles(AdditionalBundleParameters $parameters): array
  67.     {
  68.         // Ensure the bundle classes can be loaded via auto-loading.
  69.         if (isset($GLOBALS['PICKWARE_DEPENDENCY_LOADER'])) {
  70.             $kernelParameters $parameters->getKernelParameters();
  71.             $GLOBALS['PICKWARE_DEPENDENCY_LOADER']->ensureLatestDependenciesOfPluginsLoaded(
  72.                 $kernelParameters['kernel.plugin_infos'],
  73.                 $kernelParameters['kernel.project_dir'],
  74.             );
  75.         }
  76.         // For some reason Collection is abstract
  77.         // phpcs:ignore Squiz.WhiteSpace.ScopeClosingBrace.ContentBefore -- PHP CS does not understand the PHP 7 syntax
  78.         $bundleCollection = new class() extends Collection {};
  79.         foreach (self::ADDITIONAL_BUNDLES as $bundle) {
  80.             $bundle::register($bundleCollection);
  81.         }
  82.         return $bundleCollection->getElements();
  83.     }
  84.     public static function getDistPackages(): array
  85.     {
  86.         return include __DIR__ '/../Packages.php';
  87.     }
  88.     public function build(ContainerBuilder $containerBuilder): void
  89.     {
  90.         parent::build($containerBuilder);
  91.         $loader = new XmlFileLoader($containerBuilder, new FileLocator(__DIR__));
  92.         $loader->load('Address/DependencyInjection/model.xml');
  93.         $loader->load('Address/DependencyInjection/model-extension.xml');
  94.         $loader->load('Analytics/DependencyInjection/controller.xml');
  95.         $loader->load('Analytics/DependencyInjection/model.xml');
  96.         $loader->load('Analytics/DependencyInjection/model-extension.xml');
  97.         $loader->load('Analytics/DependencyInjection/service.xml');
  98.         $loader->load('Config/DependencyInjection/controller.xml');
  99.         $loader->load('Config/DependencyInjection/service.xml');
  100.         $loader->load('DemandPlanning/DependencyInjection/analytics.xml');
  101.         $loader->load('DemandPlanning/DependencyInjection/controller.xml');
  102.         $loader->load('DemandPlanning/DependencyInjection/service.xml');
  103.         $loader->load('DemodataGeneration/DependencyInjection/command.xml');
  104.         $loader->load('DemodataGeneration/DependencyInjection/demodata-generator.xml');
  105.         $loader->load('ImportExport/DependencyInjection/controller.xml');
  106.         $loader->load('ImportExport/DependencyInjection/model.xml');
  107.         $loader->load('ImportExport/DependencyInjection/model-extension.xml');
  108.         $loader->load('ImportExport/DependencyInjection/model-subscriber.xml');
  109.         $loader->load('ImportExport/DependencyInjection/service.xml');
  110.         $loader->load('ImportExport/Profiles/DependencyInjection/service.xml');
  111.         $loader->load('ImportExport/Profiles/DependencyInjection/absolute-stock.xml');
  112.         $loader->load('ImportExport/Profiles/DependencyInjection/relative-stock-change.xml');
  113.         $loader->load('ImportExport/Profiles/DependencyInjection/bin-location.xml');
  114.         $loader->load('ImportExport/Profiles/DependencyInjection/stock-per-product.xml');
  115.         $loader->load('ImportExport/Profiles/DependencyInjection/stock-per-stock-location.xml');
  116.         $loader->load('ImportExport/Profiles/DependencyInjection/stock-per-warehouse.xml');
  117.         $loader->load('ImportExport/Profiles/DependencyInjection/product-supplier-configuration.xml');
  118.         $loader->load('ImportExport/Profiles/DependencyInjection/supplier-order.xml');
  119.         $loader->load('ImportExport/Profiles/DependencyInjection/stock-valuation.xml');
  120.         $loader->load('Installation/DependencyInjection/service.xml');
  121.         $loader->load('InvoiceCorrection/DependencyInjection/service.xml');
  122.         $loader->load('InvoiceStack/DependencyInjection/service.xml');
  123.         $loader->load('Logger/DependencyInjection/service.xml');
  124.         $loader->load('MailDraft/DependencyInjection/controller.xml');
  125.         $loader->load('MailDraft/DependencyInjection/service.xml');
  126.         $loader->load('MessageQueueMonitoring/DependencyInjection/controller.xml');
  127.         $loader->load('MessageQueueMonitoring/DependencyInjection/service.xml');
  128.         $loader->load('Order/DependencyInjection/model.xml');
  129.         $loader->load('Order/DependencyInjection/model-extension.xml');
  130.         $loader->load('OrderCalculation/DependencyInjection/service.xml');
  131.         $loader->load('OrderShipping/DependencyInjection/controller.xml');
  132.         $loader->load('OrderShipping/DependencyInjection/service.xml');
  133.         $loader->load('Picking/DependencyInjection/service.xml');
  134.         $loader->load('Picklist/DependencyInjection/service.xml');
  135.         $loader->load('PriceCalculation/DependencyInjection/service.xml');
  136.         $loader->load('Product/DependencyInjection/model.xml');
  137.         $loader->load('Product/DependencyInjection/model-extension.xml');
  138.         $loader->load('Product/DependencyInjection/service.xml');
  139.         $loader->load('Product/DependencyInjection/template.xml');
  140.         $loader->load('PurchaseList/DependencyInjection/controller.xml');
  141.         $loader->load('PurchaseList/DependencyInjection/exception-handler.xml');
  142.         $loader->load('PurchaseList/DependencyInjection/model.xml');
  143.         $loader->load('PurchaseList/DependencyInjection/model-extension.xml');
  144.         $loader->load('PurchaseList/DependencyInjection/service.xml');
  145.         $loader->load('Reorder/DependencyInjection/scheduled-task.xml');
  146.         $loader->load('Reorder/DependencyInjection/service.xml');
  147.         $loader->load('Reorder/DependencyInjection/subscriber.xml');
  148.         $loader->load('Reporting/DependencyInjection/model.xml');
  149.         $loader->load('ReturnOrder/DependencyInjection/model.xml');
  150.         $loader->load('Stock/DependencyInjection/container-override.xml');
  151.         $loader->load('Stock/DependencyInjection/decorator.xml');
  152.         $loader->load('Stock/DependencyInjection/indexer.xml');
  153.         $loader->load('Stock/DependencyInjection/model.xml');
  154.         $loader->load('Stock/DependencyInjection/model-extension.xml');
  155.         $loader->load('Stock/DependencyInjection/service.xml');
  156.         $loader->load('StockApi/DependencyInjection/controller.xml');
  157.         $loader->load('StockApi/DependencyInjection/service.xml');
  158.         $loader->load('StockApi/DependencyInjection/subscriber.xml');
  159.         $loader->load('StockFlow/DependencyInjection/controller.xml');
  160.         $loader->load('StockFlow/DependencyInjection/service.xml');
  161.         $loader->load('Stocking/DependencyInjection/service.xml');
  162.         $loader->load('Supplier/DependencyInjection/exception-handler.xml');
  163.         $loader->load('Supplier/DependencyInjection/model.xml');
  164.         $loader->load('Supplier/DependencyInjection/model-extension.xml');
  165.         $loader->load('Supplier/DependencyInjection/model-subscriber.xml');
  166.         $loader->load('Supplier/DependencyInjection/service.xml');
  167.         $loader->load('Supplier/DependencyInjection/indexer.xml');
  168.         $loader->load('SupplierOrder/DependencyInjection/controller.xml');
  169.         $loader->load('SupplierOrder/DependencyInjection/indexer.xml');
  170.         $loader->load('SupplierOrder/DependencyInjection/model.xml');
  171.         $loader->load('SupplierOrder/DependencyInjection/service.xml');
  172.         $loader->load('Translation/DependencyInjection/service.xml');
  173.         $loader->load('Warehouse/DependencyInjection/exception-handler.xml');
  174.         $loader->load('Warehouse/DependencyInjection/model.xml');
  175.         $loader->load('Warehouse/DependencyInjection/model-extension.xml');
  176.         $loader->load('Warehouse/DependencyInjection/service.xml');
  177.         $loader->load('Warehouse/DependencyInjection/subscriber.xml');
  178.         // If shopware-integration-test-plugin is loaded, register benchmarks in DIC
  179.         if (in_array(ShopwareIntegrationTestPlugin::class, $containerBuilder->getParameter('kernel.bundles'), true)) {
  180.             $loader->load('Benchmarking/DependencyInjection/benchmark.xml');
  181.         }
  182.         $containerBuilder->addCompilerPass(new ImporterRegistryCompilerPass());
  183.         $containerBuilder->addCompilerPass(new ExporterRegistryCompilerPass());
  184.         // Add SwagMigrationAssistant service decoration when the plugin is present.
  185.         $activePlugins $containerBuilder->getParameter('kernel.active_plugins');
  186.         if (isset($activePlugins[SwagMigrationAssistant::class]) && interface_exists(WriterInterface::class)) {
  187.             $loader->load('ShopwareMigration/DependencyInjection/service.xml');
  188.         }
  189.     }
  190.     public function install(InstallContext $installContext): void
  191.     {
  192.         $this->loadDependenciesForSetup();
  193.         $this->executeMigrationsOfBundles();
  194.         BundleInstaller::createForContainerAndClass($this->containerself::class)
  195.             ->install(self::ADDITIONAL_BUNDLES$installContext);
  196.     }
  197.     public function postInstall(InstallContext $installContext): void
  198.     {
  199.         $installer PickwareErpInstaller::initFromContainer($this->container);
  200.         $installer->postInstall();
  201.     }
  202.     public function update(UpdateContext $updateContext): void
  203.     {
  204.         $this->loadDependenciesForSetup();
  205.         $this->executeMigrationsOfBundles();
  206.         BundleInstaller::createForContainerAndClass($this->containerself::class)
  207.             ->install(self::ADDITIONAL_BUNDLES$updateContext);
  208.         // There are Migrations that require the stock-tables to be rebuilt after a plugin update.
  209.         if ($updateContext->getPlugin()->isActive()) {
  210.             // Only run the indexer when the plugin is activated during the update. If the plugin is disabled during the
  211.             // update, the rerun of the indexer is triggered when activating the plugin.
  212.             $this->runIndexer();
  213.         }
  214.     }
  215.     public function postUpdate(UpdateContext $updateContext): void
  216.     {
  217.         $installer PickwareErpInstaller::initFromContainer($this->container);
  218.         $installer->postUpdate();
  219.         if ($updateContext->getPlugin()->isActive()) {
  220.             BundleInstaller::createForContainerAndClass($this->containerself::class)
  221.                 ->onAfterActivate(self::ADDITIONAL_BUNDLES$updateContext);
  222.         }
  223.     }
  224.     private function executeMigrationsOfBundles(): void
  225.     {
  226.         // All the services required for migration execution are private in the DI-Container. As a workaround the
  227.         // services are instantiated explicitly here.
  228.         /** @var Connection $db */
  229.         $db $this->container->get(Connection::class);
  230.         // See vendor/symfony/monolog-bundle/Resources/config/monolog.xml on how the logger is defined.
  231.         $logger = new Logger('app');
  232.         $logger->useMicrosecondTimestamps($this->container->getParameter('monolog.use_microseconds'));
  233.         $migrationCollectionLoader = new MigrationCollectionLoader($db, new MigrationRuntime($db$logger));
  234.         $migrationSource = new MigrationSource('PickwareErpStarter');
  235.         foreach (self::ADDITIONAL_BUNDLES as $bundle) {
  236.             $bundle::registerMigrations($migrationSource);
  237.         }
  238.         $migrationCollectionLoader->addSource($migrationSource);
  239.         foreach ($migrationCollectionLoader->collectAll() as $migrationCollection) {
  240.             $migrationCollection->sync();
  241.             $migrationCollection->migrateInPlace();
  242.         }
  243.     }
  244.     public function activate(ActivateContext $activateContext): void
  245.     {
  246.         // After the plugin has been activated, the indexer needs to run in order to ensure that any aggregated data
  247.         // is consistent (i.e. stock quantities that are calculated from stock movements).
  248.         // The StockIndexer is particularly important when the plugin is first installed, because the plugin creates
  249.         // initial stock movements during its installation process, but the stock indexer is not yet registered so that
  250.         // the aggregated stock quantities can not written during the initialization. Explicitly running the stock
  251.         // indexer during activation ensures the aggregated stock entities are updated.
  252.         $this->runIndexer();
  253.         BundleInstaller::createForContainerAndClass($this->containerself::class)
  254.             ->onAfterActivate(self::ADDITIONAL_BUNDLES$activateContext);
  255.     }
  256.     private function runIndexer(): void
  257.     {
  258.         /** @var EntityIndexerRegistry $entityIndexerRegistry */
  259.         $entityIndexerRegistry $this->container->get('pickware.pickware_erp.entity_indexer_registry_public');
  260.         $entityIndexerRegistry->sendIndexingMessage([
  261.             StockIndexer::NAME,
  262.             IncomingStockIndexer::NAME,
  263.             ProductSupplierConfigurationIndexer::NAME,
  264.         ]);
  265.     }
  266.     public function uninstall(UninstallContext $uninstallContext): void
  267.     {
  268.         parent::uninstall($uninstallContext);
  269.         if ($uninstallContext->keepUserData()) {
  270.             return;
  271.         }
  272.         $this->loadDependenciesForSetup();
  273.         $this->container->get(Connection::class)->executeStatement('
  274.             SET FOREIGN_KEY_CHECKS = 0;
  275.             -- Migration1556014423CreateAddressSchema.php
  276.             DROP TABLE IF EXISTS `pickware_erp_address`;
  277.             -- Migration1556014424CreateWarehouseSchema.php
  278.             DROP TABLE IF EXISTS `pickware_erp_warehouse`;
  279.             DROP TABLE IF EXISTS `pickware_erp_bin_location`;
  280.             -- Migration1556118797CreateStockSchema.php
  281.             DROP TABLE IF EXISTS `pickware_erp_special_stock_location`;
  282.             DROP TABLE IF EXISTS `pickware_erp_location_type`;
  283.             DROP TABLE IF EXISTS `pickware_erp_stock_movement`;
  284.             DROP TABLE IF EXISTS `pickware_erp_stock`;
  285.             -- Migration1584965609CreateConfigSchema.php
  286.             DROP TABLE IF EXISTS `pickware_erp_config`;
  287.             -- Migration1589893337AddWarehouseCustomFields.php
  288.             DELETE FROM `custom_field_set_relation` WHERE `entity_name` = "pickware_erp_warehouse";
  289.             -- Migration1594822086CreateProductWarehouseConfigurationSchema.php
  290.             DROP TABLE IF EXISTS `pickware_erp_product_warehouse_configuration`;
  291.             -- Migration1595323759CreateProductConfigurationSchema.php
  292.             -- Migration1626766063RenameProductConfigurationAndAddIncomingStock
  293.             DROP TABLE IF EXISTS `pickware_erp_product_configuration`;
  294.             DROP TABLE IF EXISTS `pickware_erp_pickware_product`;
  295.             -- Migration1597838146CreateWarehouseStockSchema.php
  296.             DROP TABLE IF EXISTS `pickware_erp_warehouse_stock`;
  297.             -- Migration1599487702CreateProductReorderView.php
  298.             DROP VIEW IF EXISTS `pickware_erp_product_reorder_view`;
  299.             -- Migration1599039841CreateSupplierSchema.php
  300.             DROP TABLE IF EXISTS `pickware_erp_supplier`;
  301.             -- Migration1601043196CreateProductSupplierConfigurationSchema.php
  302.             DROP TABLE IF EXISTS `pickware_erp_product_supplier_configuration`;
  303.             -- Migration1605002744CreateOrderPickabilityView.php
  304.             DROP VIEW IF EXISTS `pickware_erp_order_pickability_view`;
  305.             -- Migration1600420898CreateImportExportSchema
  306.             DROP TABLE IF EXISTS `pickware_erp_import_export`;
  307.             DROP TABLE IF EXISTS `pickware_erp_import_element`;
  308.             DROP TABLE IF EXISTS `pickware_erp_import_export_profile`;
  309.             -- Migration1606220870CreateStockValuationView.php
  310.             DROP VIEW IF EXISTS `pickware_erp_stock_valuation_view`;
  311.             -- Migration1616419772CreateMessageQueueMonitoring.php
  312.             -- Migration1641313633FixMessageQueueMonitoringTableName.php
  313.             DROP TABLE IF EXISTS `pickware_erp_message_queue_monitoring`;
  314.             -- Migration1614587720CreateDemandPlanningListItemSchema.php
  315.             DROP TABLE IF EXISTS `pickware_erp_demand_planning_session`;
  316.             DROP TABLE IF EXISTS `pickware_erp_demand_planning_list_item`;
  317.             -- Migration1614587720CreatePurchaseListItemSchema.php
  318.             DROP TABLE IF EXISTS `pickware_erp_purchase_list_item`;
  319.             -- Migration1618321583CreateExportElementSchemaAndImportExportConfigField
  320.             DROP TABLE IF EXISTS `pickware_erp_import_export_element`;
  321.             -- Migration1621419761AddSupplierOrderSchema.php
  322.             DROP TABLE IF EXISTS `pickware_erp_supplier_order`;
  323.             DROP TABLE IF EXISTS `pickware_erp_supplier_order_line_item`;
  324.             -- Migration1648127351AddAnalyticsSchema.php
  325.             DROP TABLE IF EXISTS `pickware_erp_analytics_profile`;
  326.             DROP TABLE IF EXISTS `pickware_erp_analytics_session`;
  327.             -- Migration1648127352MigrateDemandPlanningToAnalytics.php
  328.             DROP TABLE IF EXISTS `pickware_erp_analytics_list_item_demand_planning`;
  329.             -- Migration1649759025AddStockContainerSchema.php
  330.             DROP TABLE IF EXISTS `pickware_erp_stock_container`;
  331.             -- Migration1637931476CreateReturnOrderSchema.php
  332.             DROP TABLE IF EXISTS `pickware_erp_return_order`;
  333.             DROP TABLE IF EXISTS `pickware_erp_return_order_refund`;
  334.             DROP TABLE IF EXISTS `pickware_erp_return_order_line_item`;
  335.             DROP TABLE IF EXISTS `pickware_erp_return_order_document_mapping`;
  336.             -- Migration1649314350ChangeAnalyticsToUseAggregationsAndReports.php
  337.             DROP TABLE IF EXISTS `pickware_erp_analytics_aggregation`;
  338.             DROP TABLE IF EXISTS `pickware_erp_analytics_aggregation_session`;
  339.             DROP TABLE IF EXISTS `pickware_erp_analytics_report`;
  340.             DROP TABLE IF EXISTS `pickware_erp_analytics_report_config`;
  341.             -- Migration1649752132AddDemandPlanningAnalyticsAggregationSchema.php
  342.             DROP TABLE IF EXISTS `pickware_erp_analytics_aggregation_item_demand_planning`;
  343.             DROP TABLE IF EXISTS `pickware_erp_demand_planning_list_item`;
  344.             SET FOREIGN_KEY_CHECKS = 1;
  345.         ');
  346.         PickwareErpInstaller::initFromContainer($this->container)->uninstall();
  347.         BundleInstaller::createForContainerAndClass($this->containerself::class)->uninstall($uninstallContext);
  348.     }
  349.     /**
  350.      * Run the dependency loader for a setup step like install/update/uninstall
  351.      *
  352.      * When executing one of these steps but no Pickware plugin is activated, the dependency loader did never run until
  353.      * the call of the corresponding method. You can trigger it with a call of this method.
  354.      */
  355.     private function loadDependenciesForSetup(): void
  356.     {
  357.         if (isset($GLOBALS['PICKWARE_DEPENDENCY_LOADER'])) {
  358.             $plugins $this->container->get('kernel')->getPluginLoader()->getPluginInfos();
  359.             $projectDir $this->container->getParameter('kernel.project_dir');
  360.             $GLOBALS['PICKWARE_DEPENDENCY_LOADER']->ensureLatestDependenciesOfPluginsLoaded($plugins$projectDir);
  361.         }
  362.     }
  363. }