Skip to content

Commit 94355ca

Browse files
committed
Introduce worker for product export
1 parent e2c721c commit 94355ca

4 files changed

Lines changed: 469 additions & 1 deletion

File tree

src/Command/ExportBatchCommand.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Omikron\FactFinder\Shopware6\Command;
6+
7+
use Omikron\FactFinder\Shopware6\Export\CurrencyFieldsProvider;
8+
use Omikron\FactFinder\Shopware6\Export\Data\Entity\ProductEntity;
9+
use Omikron\FactFinder\Shopware6\Export\FeedFactory;
10+
use Omikron\FactFinder\Shopware6\Export\Field\FieldInterface;
11+
use Omikron\FactFinder\Shopware6\Export\FieldsProvider;
12+
use Omikron\FactFinder\Shopware6\Export\SalesChannelService;
13+
use Omikron\FactFinder\Shopware6\Export\Stream\CsvFile;
14+
use Shopware\Core\Framework\Api\Context\SystemSource;
15+
use Shopware\Core\Framework\Context;
16+
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
17+
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
18+
use Symfony\Component\Console\Attribute\AsCommand;
19+
use Symfony\Component\Console\Command\Command;
20+
use Symfony\Component\Console\Input\InputArgument;
21+
use Symfony\Component\Console\Input\InputInterface;
22+
use Symfony\Component\Console\Output\OutputInterface;
23+
24+
#[AsCommand(name: 'factfinder:export:batch', description: 'Internal worker command for exporting a batch of products', hidden: true)]
25+
class ExportBatchCommand extends Command
26+
{
27+
private const PRODUCTS_EXPORT_TYPE = 'products';
28+
29+
public function __construct(
30+
private readonly SalesChannelService $channelService,
31+
private readonly FeedFactory $feedFactory,
32+
private readonly FieldsProvider $fieldProviders,
33+
private readonly array $productsColumnsBase,
34+
private readonly CurrencyFieldsProvider $currencyFieldsProvider,
35+
private readonly EntityRepository $salesChannelRepository,
36+
) {
37+
parent::__construct();
38+
}
39+
40+
protected function configure(): void
41+
{
42+
$this->addArgument('sales_channel', InputArgument::REQUIRED, 'ID of the sales channel');
43+
$this->addArgument('language', InputArgument::REQUIRED, 'ID of the language');
44+
$this->addArgument('offset', InputArgument::REQUIRED, 'Offset');
45+
$this->addArgument('limit', InputArgument::REQUIRED, 'Limit');
46+
$this->addArgument('file_path', InputArgument::REQUIRED, 'Path to output CSV');
47+
}
48+
49+
protected function execute(InputInterface $input, OutputInterface $output): int
50+
{
51+
$offset = (int) $input->getArgument('offset');
52+
$limit = (int) $input->getArgument('limit');
53+
$filePath = $input->getArgument('file_path');
54+
$salesChannelId = $input->getArgument('sales_channel');
55+
$salesChannel = null;
56+
57+
if (!empty($salesChannelId)) {
58+
$salesChannel = $this->salesChannelRepository->search(
59+
new Criteria([$salesChannelId]),
60+
new Context(new SystemSource())
61+
)->first();
62+
}
63+
64+
$context = $this->channelService->getSalesChannelContext(
65+
$salesChannel,
66+
$input->getArgument('language')
67+
);
68+
69+
$entityClass = ProductEntity::class;
70+
$feedService = $this->feedFactory->create($context, $entityClass);
71+
72+
$fileResource = fopen($filePath, 'a');
73+
$out = new CsvFile($fileResource);
74+
75+
$feedColumns = $this->getFeedColumns('products', ProductEntity::class);
76+
$processedCount = $feedService->generateBatch($out, $feedColumns, $offset, $limit, $offset === 0);
77+
78+
fclose($fileResource);
79+
80+
$memoryUsageMB = memory_get_usage(true) / 1024 / 1024;
81+
$peakMemoryMB = memory_get_peak_usage(true) / 1024 / 1024;
82+
83+
$result = [
84+
'count' => $processedCount,
85+
'memory' => round($memoryUsageMB, 2),
86+
'peak' => round($peakMemoryMB, 2),
87+
];
88+
89+
$output->write(json_encode($result));
90+
91+
return Command::SUCCESS;
92+
}
93+
94+
private function getFeedColumns(string $exportType, string $entityClass): array
95+
{
96+
$fields = $this->fieldProviders->getFields($entityClass);
97+
return array_values(
98+
array_unique(
99+
array_merge(
100+
$this->productsColumnsBase,
101+
array_map([$this, 'getFieldName'], $fields),
102+
$exportType === self::PRODUCTS_EXPORT_TYPE ? $this->currencyFieldsProvider->getCurrencyFields() : []
103+
)
104+
)
105+
);
106+
}
107+
108+
private function getFieldName(FieldInterface $field): string
109+
{
110+
return $field->getName();
111+
}
112+
}

0 commit comments

Comments
 (0)