vendor/shopware/core/Content/ProductExport/ScheduledTask/ProductExportPartialGenerationHandler.php line 104

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\ProductExport\ScheduledTask;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Content\ProductExport\ProductExportEntity;
  5. use Shopware\Core\Content\ProductExport\Service\ProductExportFileHandlerInterface;
  6. use Shopware\Core\Content\ProductExport\Service\ProductExportGeneratorInterface;
  7. use Shopware\Core\Content\ProductExport\Service\ProductExportRendererInterface;
  8. use Shopware\Core\Content\ProductExport\Struct\ExportBehavior;
  9. use Shopware\Core\Content\ProductExport\Struct\ProductExportResult;
  10. use Shopware\Core\Defaults;
  11. use Shopware\Core\Framework\Adapter\Translation\Translator;
  12. use Shopware\Core\Framework\Context;
  13. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  16. use Shopware\Core\Framework\Log\Package;
  17. use Shopware\Core\Framework\MessageQueue\Handler\AbstractMessageHandler;
  18. use Shopware\Core\Framework\Routing\Exception\SalesChannelNotFoundException;
  19. use Shopware\Core\Framework\Uuid\Uuid;
  20. use Shopware\Core\System\Locale\LanguageLocaleCodeProvider;
  21. use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
  22. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
  23. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  24. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceInterface;
  25. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
  26. use Symfony\Component\Messenger\MessageBusInterface;
  27. /**
  28.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will only implement MessageHandlerInterface and all MessageHandler will be internal and final starting with v6.5.0.0
  29.  */
  30. #[Package('inventory')]
  31. class ProductExportPartialGenerationHandler extends AbstractMessageHandler
  32. {
  33.     private AbstractSalesChannelContextFactory $salesChannelContextFactory;
  34.     private EntityRepositoryInterface $productExportRepository;
  35.     private ProductExportGeneratorInterface $productExportGenerator;
  36.     private int $readBufferSize;
  37.     private MessageBusInterface $messageBus;
  38.     private ProductExportFileHandlerInterface $productExportFileHandler;
  39.     private ProductExportRendererInterface $productExportRender;
  40.     private Translator $translator;
  41.     private SalesChannelContextServiceInterface $salesChannelContextService;
  42.     private SalesChannelContextPersister $contextPersister;
  43.     private Connection $connection;
  44.     private LanguageLocaleCodeProvider $languageLocaleProvider;
  45.     /**
  46.      * @internal
  47.      */
  48.     public function __construct(
  49.         ProductExportGeneratorInterface $productExportGenerator,
  50.         AbstractSalesChannelContextFactory $salesChannelContextFactory,
  51.         EntityRepositoryInterface $productExportRepository,
  52.         ProductExportFileHandlerInterface $productExportFileHandler,
  53.         MessageBusInterface $messageBus,
  54.         ProductExportRendererInterface $productExportRender,
  55.         Translator $translator,
  56.         SalesChannelContextServiceInterface $salesChannelContextService,
  57.         SalesChannelContextPersister $contextPersister,
  58.         Connection $connection,
  59.         int $readBufferSize,
  60.         LanguageLocaleCodeProvider $languageLocaleProvider
  61.     ) {
  62.         $this->productExportGenerator $productExportGenerator;
  63.         $this->salesChannelContextFactory $salesChannelContextFactory;
  64.         $this->productExportRepository $productExportRepository;
  65.         $this->productExportFileHandler $productExportFileHandler;
  66.         $this->messageBus $messageBus;
  67.         $this->productExportRender $productExportRender;
  68.         $this->translator $translator;
  69.         $this->salesChannelContextService $salesChannelContextService;
  70.         $this->contextPersister $contextPersister;
  71.         $this->connection $connection;
  72.         $this->readBufferSize $readBufferSize;
  73.         $this->languageLocaleProvider $languageLocaleProvider;
  74.     }
  75.     public static function getHandledMessages(): iterable
  76.     {
  77.         return [
  78.             ProductExportPartialGeneration::class,
  79.         ];
  80.     }
  81.     /**
  82.      * @param ProductExportPartialGeneration $productExportPartialGeneration
  83.      *
  84.      * @throws SalesChannelNotFoundException
  85.      * @throws InconsistentCriteriaIdsException
  86.      */
  87.     public function handle($productExportPartialGeneration): void
  88.     {
  89.         $context $this->getContext($productExportPartialGeneration);
  90.         $productExport $this->fetchProductExport($productExportPartialGeneration$context);
  91.         if (!$productExport) {
  92.             return;
  93.         }
  94.         $exportResult $this->runExport($productExport$productExportPartialGeneration->getOffset(), $context);
  95.         $filePath $this->productExportFileHandler->getFilePath($productExporttrue);
  96.         if ($exportResult === null) {
  97.             $this->finalizeExport($productExport$filePath);
  98.             return;
  99.         }
  100.         $this->productExportFileHandler->writeProductExportContent(
  101.             $exportResult->getContent(),
  102.             $filePath,
  103.             $productExportPartialGeneration->getOffset() > 0
  104.         );
  105.         if ($productExportPartialGeneration->getOffset() + $this->readBufferSize $exportResult->getTotal()) {
  106.             $this->messageBus->dispatch(
  107.                 new ProductExportPartialGeneration(
  108.                     $productExportPartialGeneration->getProductExportId(),
  109.                     $productExportPartialGeneration->getSalesChannelId(),
  110.                     $productExportPartialGeneration->getOffset() + $this->readBufferSize
  111.                 )
  112.             );
  113.             return;
  114.         }
  115.         $this->finalizeExport($productExport$filePath);
  116.     }
  117.     private function getContext(ProductExportPartialGeneration $productExportPartialGeneration): Context
  118.     {
  119.         $context $this->salesChannelContextFactory->create(
  120.             Uuid::randomHex(),
  121.             $productExportPartialGeneration->getSalesChannelId()
  122.         );
  123.         if ($context->getSalesChannel()->getTypeId() !== Defaults::SALES_CHANNEL_TYPE_STOREFRONT) {
  124.             throw new SalesChannelNotFoundException();
  125.         }
  126.         return $context->getContext();
  127.     }
  128.     private function fetchProductExport(
  129.         ProductExportPartialGeneration $productExportPartialGeneration,
  130.         Context $context
  131.     ): ?ProductExportEntity {
  132.         $criteria = new Criteria([$productExportPartialGeneration->getProductExportId()]);
  133.         $criteria
  134.             ->addAssociation('salesChannel')
  135.             ->addAssociation('salesChannelDomain.salesChannel')
  136.             ->addAssociation('salesChannelDomain.language.locale')
  137.             ->addAssociation('productStream.filters.queries')
  138.             ->setLimit(1);
  139.         return $this->productExportRepository
  140.             ->search($criteria$context)
  141.             ->first();
  142.     }
  143.     private function runExport(
  144.         ProductExportEntity $productExport,
  145.         int $offset,
  146.         Context $context
  147.     ): ?ProductExportResult {
  148.         $this->productExportRepository->update([[
  149.             'id' => $productExport->getId(),
  150.             'isRunning' => true,
  151.         ]], $context);
  152.         return $this->productExportGenerator->generate(
  153.             $productExport,
  154.             new ExportBehavior(
  155.                 false,
  156.                 false,
  157.                 true,
  158.                 false,
  159.                 false,
  160.                 $offset
  161.             )
  162.         );
  163.     }
  164.     private function finalizeExport(ProductExportEntity $productExportstring $filePath): void
  165.     {
  166.         $contextToken Uuid::randomHex();
  167.         $this->contextPersister->save(
  168.             $contextToken,
  169.             [
  170.                 SalesChannelContextService::CURRENCY_ID => $productExport->getCurrencyId(),
  171.             ],
  172.             $productExport->getSalesChannelId()
  173.         );
  174.         $context $this->salesChannelContextService->get(
  175.             new SalesChannelContextServiceParameters(
  176.                 $productExport->getStorefrontSalesChannelId(),
  177.                 $contextToken,
  178.                 $productExport->getSalesChannelDomain()->getLanguageId(),
  179.                 $productExport->getSalesChannelDomain()->getCurrencyId() ?? $productExport->getCurrencyId()
  180.             )
  181.         );
  182.         $this->translator->injectSettings(
  183.             $productExport->getStorefrontSalesChannelId(),
  184.             $productExport->getSalesChannelDomain()->getLanguageId(),
  185.             $this->languageLocaleProvider->getLocaleForLanguageId($productExport->getSalesChannelDomain()->getLanguageId()),
  186.             $context->getContext()
  187.         );
  188.         $headerContent $this->productExportRender->renderHeader($productExport$context);
  189.         $footerContent $this->productExportRender->renderFooter($productExport$context);
  190.         $finalFilePath $this->productExportFileHandler->getFilePath($productExport);
  191.         $this->translator->resetInjection();
  192.         $writeProductExportSuccessful $this->productExportFileHandler->finalizePartialProductExport(
  193.             $filePath,
  194.             $finalFilePath,
  195.             $headerContent,
  196.             $footerContent
  197.         );
  198.         $this->connection->delete('sales_channel_api_context', ['token' => $contextToken]);
  199.         if (!$writeProductExportSuccessful) {
  200.             return;
  201.         }
  202.         $this->productExportRepository->update(
  203.             [
  204.                 [
  205.                     'id' => $productExport->getId(),
  206.                     'generatedAt' => new \DateTime(),
  207.                     'isRunning' => false,
  208.                 ],
  209.             ],
  210.             $context->getContext()
  211.         );
  212.     }
  213. }