Skip to content

Commit fe032c6

Browse files
authored
Merge pull request #18 from akaplya/product-override-prices
[Product overrides] group prices
2 parents deeb805 + 8da0b80 commit fe032c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2793
-3
lines changed

app/code/Magento/CatalogDataExporter/etc/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@
282282
</arguments>
283283
</virtualType>
284284

285-
<virtualType name="Magento\CatalogDataExporter\Model\Indexer\ProductFeedIndexer" type="Magento\DataExporter\Model\Indexer\FeedIndexer">
285+
<virtualType name="Magento\CatalogDataExporter\Model\Indexer\ProductFeedIndexer" type="Magento\DataExporter\Model\Indexer\LegacyFeedIndexer">
286286
<arguments>
287287
<argument name="feedIndexMetadata" xsi:type="object">Magento\CatalogDataExporter\Model\Indexer\ProductFeedIndexMetadata</argument>
288288
<argument name="serializer" xsi:type="object">Magento\CatalogDataExporter\Model\Indexer\ProductDataSerializer</argument>

app/code/Magento/DataExporter/Export/Extractor.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ private function extractDataForNode(Info $info, Node $node, array $value)
8585

8686
$data = [];
8787
if (!empty($value) || $isRoot) {
88-
$data = $this->indexDataByArguments($node->getField(), $provider->get($value), $isRoot);
88+
$t = microtime(true);
89+
$data = $this->indexDataByArguments($node->getField(), array_values($provider->get($value)), $isRoot);
90+
// echo PHP_EOL;
91+
// echo $providerClass . " " . (microtime(true) - $t);
8992
foreach ($node->getChildren() as $child) {
9093
$output = array_replace_recursive(
9194
$output,

app/code/Magento/DataExporter/Export/Transformer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ private function convertComplexRow(array $row, array $type, array $snapshot) : a
202202
*/
203203
private function convertComplexData(array $field, array $snapshot, ?string $lookup)
204204
{
205+
//Add check if data already present than no need to convert it
205206
if ($lookup) {
206207
if (!isset($snapshot[$this->getKey($field)][$lookup])) {
207208
return null;
Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\DataExporter\Model\Indexer;
9+
10+
use Magento\DataExporter\Export\Processor;
11+
use Magento\DataExporter\Model\FeedPool;
12+
use Magento\Framework\App\ResourceConnection;
13+
use Magento\Framework\DB\Select;
14+
use Magento\Framework\Indexer\ActionInterface as IndexerActionInterface;
15+
use Magento\Framework\Mview\ActionInterface as MviewActionInterface;
16+
17+
/**
18+
* Product export feed indexer class
19+
*/
20+
class LegacyFeedIndexer implements IndexerActionInterface, MviewActionInterface
21+
{
22+
/**
23+
* @var Processor
24+
*/
25+
protected $processor;
26+
27+
/**
28+
* @var ResourceConnection
29+
*/
30+
protected $resourceConnection;
31+
32+
/**
33+
* @var FeedIndexMetadata
34+
*/
35+
protected $feedIndexMetadata;
36+
37+
/**
38+
* @var DataSerializerInterface
39+
*/
40+
protected $dataSerializer;
41+
42+
/**
43+
* @var FeedIndexerCallbackInterface
44+
*/
45+
protected $feedIndexerCallback;
46+
47+
/**
48+
* @var array
49+
*/
50+
protected $callbackSkipAttributes;
51+
52+
/**
53+
* @var FeedPool
54+
*/
55+
protected $feedPool;
56+
57+
/**
58+
* @param Processor $processor
59+
* @param ResourceConnection $resourceConnection
60+
* @param DataSerializerInterface $serializer
61+
* @param FeedIndexMetadata $feedIndexMetadata
62+
* @param FeedIndexerCallbackInterface $feedIndexerCallback
63+
* @param FeedPool $feedPool
64+
* @param array $callbackSkipAttributes
65+
*/
66+
public function __construct(
67+
Processor $processor,
68+
ResourceConnection $resourceConnection,
69+
DataSerializerInterface $serializer,
70+
FeedIndexMetadata $feedIndexMetadata,
71+
FeedIndexerCallbackInterface $feedIndexerCallback,
72+
FeedPool $feedPool,
73+
array $callbackSkipAttributes = []
74+
) {
75+
$this->processor = $processor;
76+
$this->resourceConnection = $resourceConnection;
77+
$this->feedIndexMetadata = $feedIndexMetadata;
78+
$this->dataSerializer = $serializer;
79+
$this->feedIndexerCallback = $feedIndexerCallback;
80+
$this->feedPool = $feedPool;
81+
$this->callbackSkipAttributes = $callbackSkipAttributes;
82+
}
83+
84+
/**
85+
* Get Ids select
86+
*
87+
* @param int $lastKnownId
88+
* @return Select
89+
*/
90+
private function getIdsSelect(int $lastKnownId) : Select
91+
{
92+
$columnExpression = sprintf('s.%s', $this->feedIndexMetadata->getSourceTableField());
93+
$whereClause = sprintf('s.%s > ?', $this->feedIndexMetadata->getSourceTableField());
94+
$connection = $this->resourceConnection->getConnection();
95+
return $connection->select()
96+
->from(
97+
['s' => $this->resourceConnection->getTableName($this->feedIndexMetadata->getSourceTableName())],
98+
[
99+
$this->feedIndexMetadata->getFeedIdentity() =>
100+
's.' . $this->feedIndexMetadata->getSourceTableField()
101+
]
102+
)
103+
->where($whereClause, $lastKnownId)
104+
->order($columnExpression)
105+
->limit($this->feedIndexMetadata->getBatchSize());
106+
}
107+
108+
/**
109+
* Get all product IDs
110+
*
111+
* @return \Generator
112+
* @throws \Zend_Db_Statement_Exception
113+
*/
114+
private function getAllIds() : ?\Generator
115+
{
116+
$connection = $this->resourceConnection->getConnection();
117+
$lastKnownId = 0;
118+
$continueReindex = true;
119+
while ($continueReindex) {
120+
$ids = $connection->fetchAll($this->getIdsSelect((int)$lastKnownId));
121+
if (empty($ids)) {
122+
$continueReindex = false;
123+
} else {
124+
yield $ids;
125+
$lastKnownId = end($ids)[$this->feedIndexMetadata->getFeedIdentity()];
126+
}
127+
}
128+
}
129+
130+
/**
131+
* Execute full indexation
132+
*
133+
* @return void
134+
* @throws \Zend_Db_Statement_Exception
135+
*/
136+
public function executeFull()
137+
{
138+
$this->truncateFeedTable();
139+
foreach ($this->getAllIds() as $ids) {
140+
$this->markRemoved($ids);
141+
$this->process($ids);
142+
}
143+
}
144+
145+
/**
146+
* Execute partial indexation by ID list
147+
*
148+
* @param int[] $ids
149+
* @return void
150+
*/
151+
public function executeList(array $ids)
152+
{
153+
$arguments = [];
154+
foreach ($ids as $id) {
155+
$arguments[] = [$this->feedIndexMetadata->getFeedIdentity() => $id];
156+
}
157+
$this->markRemoved($ids);
158+
$this->process($arguments);
159+
}
160+
161+
/**
162+
* Execute partial indexation by ID
163+
*
164+
* @param int $id
165+
* @return void
166+
*/
167+
public function executeRow($id)
168+
{
169+
$this->markRemoved([$id]);
170+
$this->process([[$this->feedIndexMetadata->getFeedIdentity() => $id]]);
171+
}
172+
173+
/**
174+
* Execute materialization on ids entities
175+
*
176+
* @param int[] $ids
177+
* @return void
178+
* @api
179+
*/
180+
public function execute($ids)
181+
{
182+
$arguments = [];
183+
$feedIdentity = $this->feedIndexMetadata->getFeedIdentity();
184+
185+
foreach ($ids as $id) {
186+
$arguments[] = \is_array($id) ? $this->prepareIndexData($id) : [
187+
$feedIdentity => $id,
188+
];
189+
}
190+
191+
$this->markRemoved(\array_column($arguments, $feedIdentity));
192+
$this->process($arguments);
193+
}
194+
195+
/**
196+
* Prepare index data
197+
*
198+
* @param array $indexData
199+
*
200+
* @return array
201+
*/
202+
private function prepareIndexData(array $indexData): array
203+
{
204+
$attributeIds = !empty($indexData['attribute_ids'])
205+
? \array_unique(\explode(',', $indexData['attribute_ids']))
206+
: [];
207+
208+
return [
209+
$this->feedIndexMetadata->getFeedIdentity() => $indexData['entity_id'],
210+
'attribute_ids' => $attributeIds,
211+
'scopeId' => $indexData['store_id'] ?? null,
212+
];
213+
}
214+
215+
/**
216+
* Indexer feed data processor
217+
*
218+
* @param array $indexData
219+
*
220+
* @return void
221+
*/
222+
private function process($indexData = []) : void
223+
{
224+
$feedIdentity = $this->feedIndexMetadata->getFeedIdentity();
225+
$data = $this->processor->process($this->feedIndexMetadata->getFeedName(), $indexData);
226+
$chunks = array_chunk($data, $this->feedIndexMetadata->getBatchSize());
227+
$connection = $this->resourceConnection->getConnection();
228+
$callbackData = [];
229+
$existingFeedData = [];
230+
231+
$updateEntities = \array_filter($indexData, function ($data) {
232+
return !empty($data['attribute_ids']);
233+
});
234+
235+
if (!empty($updateEntities)) {
236+
$existingFeedData = $this->fetchFeedData(\array_column($updateEntities, $feedIdentity));
237+
}
238+
239+
foreach ($chunks as $chunk) {
240+
$connection->insertOnDuplicate(
241+
$this->resourceConnection->getTableName($this->feedIndexMetadata->getFeedTableName()),
242+
$this->dataSerializer->serialize($this->prepareChunkData($chunk, $existingFeedData, $callbackData)),
243+
$this->feedIndexMetadata->getFeedTableMutableColumns()
244+
);
245+
}
246+
247+
$deleteIds = [];
248+
$callbackIds = \array_column($callbackData, $feedIdentity);
249+
foreach ($indexData as $data) {
250+
if (!\in_array($data[$feedIdentity], $callbackIds)) {
251+
$deleteIds[] = $data[$feedIdentity];
252+
}
253+
}
254+
255+
$this->feedIndexerCallback->execute($callbackData, $deleteIds);
256+
}
257+
258+
/**
259+
* Prepare chunk data
260+
*
261+
* @param array $chunk
262+
* @param array $existingFeedData
263+
* @param array $callbackData
264+
*
265+
* @return array
266+
*/
267+
private function prepareChunkData(array $chunk, array $existingFeedData, array &$callbackData): array
268+
{
269+
$feedIdentity = $this->feedIndexMetadata->getFeedIdentity();
270+
foreach ($chunk as &$feedData) {
271+
$existingData = $existingFeedData[$feedData['storeViewCode']][$feedData[$feedIdentity]] ?? null;
272+
$attributes = [];
273+
274+
if (null !== $existingData) {
275+
$attributes = \array_filter(\array_keys($feedData), function ($code) {
276+
return !\in_array($code, $this->callbackSkipAttributes);
277+
});
278+
$feedData = \array_replace_recursive($existingData, $feedData);
279+
}
280+
281+
$callbackData[] = \array_filter(
282+
[
283+
$feedIdentity => $feedData[$feedIdentity],
284+
'storeViewCode' => $feedData['storeViewCode'],
285+
'attributes' => $attributes,
286+
]
287+
);
288+
}
289+
290+
return $chunk;
291+
}
292+
293+
/**
294+
* Fetch feed data
295+
*
296+
* @param int[] $ids
297+
*
298+
* @return array
299+
*/
300+
private function fetchFeedData(array $ids): array
301+
{
302+
$feedData = $this->feedPool->getFeed($this->feedIndexMetadata->getFeedName())->getFeedByIds($ids);
303+
$feedIdentity = $this->feedIndexMetadata->getFeedIdentity();
304+
$output = [];
305+
306+
foreach ($feedData['feed'] as $feedItem) {
307+
$output[$feedItem['storeViewCode']][$feedItem[$feedIdentity]] = $feedItem;
308+
}
309+
310+
return $output;
311+
}
312+
313+
/**
314+
* Mark field removed
315+
*
316+
* @param array $ids
317+
* @return void
318+
*/
319+
private function markRemoved(array $ids) : void
320+
{
321+
$connection = $this->resourceConnection->getConnection();
322+
$select = $connection->select()
323+
->joinLeft(
324+
['s' => $this->resourceConnection->getTableName($this->feedIndexMetadata->getSourceTableName())],
325+
sprintf(
326+
'f.%s = s.%s',
327+
$this->feedIndexMetadata->getFeedTableField(),
328+
$this->feedIndexMetadata->getSourceTableField()
329+
),
330+
['is_deleted' => new \Zend_Db_Expr('1')]
331+
)
332+
->where(sprintf('s.%s IS NULL', $this->feedIndexMetadata->getSourceTableField()))
333+
->where(
334+
sprintf('f.%s IN (?)', $this->feedIndexMetadata->getFeedTableField()),
335+
$ids
336+
);
337+
$update = $connection->updateFromSelect(
338+
$select,
339+
['f' => $this->resourceConnection->getTableName($this->feedIndexMetadata->getFeedTableName())]
340+
);
341+
$connection->query($update);
342+
}
343+
344+
/**
345+
* Truncate feed table
346+
*
347+
* @return void
348+
*/
349+
protected function truncateFeedTable(): void
350+
{
351+
$connection = $this->resourceConnection->getConnection();
352+
$feedTable = $this->resourceConnection->getTableName($this->feedIndexMetadata->getFeedTableName());
353+
$connection->truncateTable($feedTable);
354+
}
355+
}

0 commit comments

Comments
 (0)