Skip to content

Commit 252dd90

Browse files
authored
Merge pull request #6325 from magento-l3/TANGO-PR-11-05-2020_24
TANGO PR 11-05-2020 v24
2 parents 884d148 + 6a5a1b6 commit 252dd90

File tree

30 files changed

+1918
-181
lines changed

30 files changed

+1918
-181
lines changed

app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Rows.php

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@
1313
use Magento\Store\Model\StoreManagerInterface;
1414
use Magento\Framework\DB\Query\Generator as QueryGenerator;
1515
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Framework\Indexer\IndexerRegistry;
1617
use Magento\Catalog\Model\Config;
1718
use Magento\Catalog\Model\Category;
18-
use Magento\Framework\Indexer\IndexerRegistry;
1919
use Magento\Catalog\Model\Indexer\Product\Category as ProductCategoryIndexer;
20+
use Magento\Catalog\Model\Indexer\Category\Product as CategoryProductIndexer;
21+
use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer;
22+
use Magento\Indexer\Model\WorkingStateProvider;
2023

2124
/**
2225
* Reindex multiple rows action.
2326
*
24-
* @package Magento\Catalog\Model\Indexer\Category\Product\Action
2527
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2628
*/
2729
class Rows extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractAction
@@ -48,30 +50,42 @@ class Rows extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
4850
*/
4951
private $indexerRegistry;
5052

53+
/**
54+
* @var WorkingStateProvider
55+
*/
56+
private $workingStateProvider;
57+
5158
/**
5259
* @param ResourceConnection $resource
5360
* @param StoreManagerInterface $storeManager
5461
* @param Config $config
5562
* @param QueryGenerator|null $queryGenerator
5663
* @param MetadataPool|null $metadataPool
64+
* @param TableMaintainer|null $tableMaintainer
5765
* @param CacheContext|null $cacheContext
5866
* @param EventManagerInterface|null $eventManager
5967
* @param IndexerRegistry|null $indexerRegistry
68+
* @param WorkingStateProvider|null $workingStateProvider
69+
* @SuppressWarnings(PHPMD.ExcessiveParameterList) Preserve compatibility with the parent class
6070
*/
6171
public function __construct(
6272
ResourceConnection $resource,
6373
StoreManagerInterface $storeManager,
6474
Config $config,
6575
QueryGenerator $queryGenerator = null,
6676
MetadataPool $metadataPool = null,
77+
?TableMaintainer $tableMaintainer = null,
6778
CacheContext $cacheContext = null,
6879
EventManagerInterface $eventManager = null,
69-
IndexerRegistry $indexerRegistry = null
80+
IndexerRegistry $indexerRegistry = null,
81+
?WorkingStateProvider $workingStateProvider = null
7082
) {
71-
parent::__construct($resource, $storeManager, $config, $queryGenerator, $metadataPool);
83+
parent::__construct($resource, $storeManager, $config, $queryGenerator, $metadataPool, $tableMaintainer);
7284
$this->cacheContext = $cacheContext ?: ObjectManager::getInstance()->get(CacheContext::class);
7385
$this->eventManager = $eventManager ?: ObjectManager::getInstance()->get(EventManagerInterface::class);
7486
$this->indexerRegistry = $indexerRegistry ?: ObjectManager::getInstance()->get(IndexerRegistry::class);
87+
$this->workingStateProvider = $workingStateProvider ?:
88+
ObjectManager::getInstance()->get(WorkingStateProvider::class);
7589
}
7690

7791
/**
@@ -97,44 +111,64 @@ public function execute(array $entityIds = [], $useTempTable = false)
97111
$this->limitationByCategories = array_unique($this->limitationByCategories);
98112
$this->useTempTable = $useTempTable;
99113
$indexer = $this->indexerRegistry->get(ProductCategoryIndexer::INDEXER_ID);
100-
$workingState = $indexer->isWorking();
114+
$workingState = $this->isWorkingState();
101115

102-
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
103-
foreach ($this->storeManager->getStores() as $store) {
104-
$this->connection->truncateTable($this->getIndexTable($store->getId()));
116+
if (!$indexer->isScheduled()
117+
|| ($indexer->isScheduled() && !$useTempTable)
118+
|| ($indexer->isScheduled() && $useTempTable && !$workingState)) {
119+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
120+
foreach ($this->storeManager->getStores() as $store) {
121+
$this->connection->truncateTable($this->getIndexTable($store->getId()));
122+
}
123+
} else {
124+
$this->removeEntries();
105125
}
106-
} else {
107-
$this->removeEntries();
108-
}
109126

110-
$this->reindex();
111-
112-
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
113-
foreach ($this->storeManager->getStores() as $store) {
114-
$removalCategoryIds = array_diff($this->limitationByCategories, [$this->getRootCategoryId($store)]);
115-
$this->connection->delete(
116-
$this->tableMaintainer->getMainTable($store->getId()),
117-
['category_id IN (?)' => $removalCategoryIds]
118-
);
119-
$select = $this->connection->select()
120-
->from($this->tableMaintainer->getMainReplicaTable($store->getId()));
121-
$this->connection->query(
122-
$this->connection->insertFromSelect(
123-
$select,
127+
$this->reindex();
128+
129+
// get actual state
130+
$workingState = $this->isWorkingState();
131+
132+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
133+
foreach ($this->storeManager->getStores() as $store) {
134+
$removalCategoryIds = array_diff($this->limitationByCategories, [$this->getRootCategoryId($store)]);
135+
$this->connection->delete(
124136
$this->tableMaintainer->getMainTable($store->getId()),
125-
[],
126-
AdapterInterface::INSERT_ON_DUPLICATE
127-
)
128-
);
137+
['category_id IN (?)' => $removalCategoryIds]
138+
);
139+
$select = $this->connection->select()
140+
->from($this->tableMaintainer->getMainReplicaTable($store->getId()));
141+
$this->connection->query(
142+
$this->connection->insertFromSelect(
143+
$select,
144+
$this->tableMaintainer->getMainTable($store->getId()),
145+
[],
146+
AdapterInterface::INSERT_ON_DUPLICATE
147+
)
148+
);
149+
}
129150
}
130-
}
131151

132-
$this->registerCategories($entityIds);
133-
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
152+
$this->registerCategories($entityIds);
153+
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
154+
}
134155

135156
return $this;
136157
}
137158

159+
/**
160+
* Get state for current and shared indexer
161+
*
162+
* @return bool
163+
*/
164+
private function isWorkingState() : bool
165+
{
166+
$indexer = $this->indexerRegistry->get(ProductCategoryIndexer::INDEXER_ID);
167+
$sharedIndexer = $this->indexerRegistry->get(CategoryProductIndexer::INDEXER_ID);
168+
return $this->workingStateProvider->isWorking($indexer->getId())
169+
|| $this->workingStateProvider->isWorking($sharedIndexer->getId());
170+
}
171+
138172
/**
139173
* Register categories assigned to products
140174
*

app/code/Magento/Catalog/Model/Indexer/Product/Category/Action/Rows.php

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
use Magento\Store\Model\StoreManagerInterface;
1818
use Magento\Framework\DB\Adapter\AdapterInterface;
1919
use Magento\Framework\Indexer\IndexerRegistry;
20+
use Magento\Catalog\Model\Indexer\Product\Category as ProductCategoryIndexer;
2021
use Magento\Catalog\Model\Indexer\Category\Product as CategoryProductIndexer;
22+
use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer;
23+
use Magento\Indexer\Model\WorkingStateProvider;
2124

2225
/**
2326
* Category rows indexer.
@@ -48,30 +51,42 @@ class Rows extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio
4851
*/
4952
private $indexerRegistry;
5053

54+
/**
55+
* @var WorkingStateProvider
56+
*/
57+
private $workingStateProvider;
58+
5159
/**
5260
* @param ResourceConnection $resource
5361
* @param StoreManagerInterface $storeManager
5462
* @param Config $config
5563
* @param QueryGenerator|null $queryGenerator
5664
* @param MetadataPool|null $metadataPool
65+
* @param TableMaintainer|null $tableMaintainer
5766
* @param CacheContext|null $cacheContext
5867
* @param EventManagerInterface|null $eventManager
5968
* @param IndexerRegistry|null $indexerRegistry
69+
* @param WorkingStateProvider|null $workingStateProvider
70+
* @SuppressWarnings(PHPMD.ExcessiveParameterList) Preserve compatibility with the parent class
6071
*/
6172
public function __construct(
6273
ResourceConnection $resource,
6374
StoreManagerInterface $storeManager,
6475
Config $config,
6576
QueryGenerator $queryGenerator = null,
6677
MetadataPool $metadataPool = null,
78+
?TableMaintainer $tableMaintainer = null,
6779
CacheContext $cacheContext = null,
6880
EventManagerInterface $eventManager = null,
69-
IndexerRegistry $indexerRegistry = null
81+
IndexerRegistry $indexerRegistry = null,
82+
?WorkingStateProvider $workingStateProvider = null
7083
) {
71-
parent::__construct($resource, $storeManager, $config, $queryGenerator, $metadataPool);
84+
parent::__construct($resource, $storeManager, $config, $queryGenerator, $metadataPool, $tableMaintainer);
7285
$this->cacheContext = $cacheContext ?: ObjectManager::getInstance()->get(CacheContext::class);
7386
$this->eventManager = $eventManager ?: ObjectManager::getInstance()->get(EventManagerInterface::class);
7487
$this->indexerRegistry = $indexerRegistry ?: ObjectManager::getInstance()->get(IndexerRegistry::class);
88+
$this->workingStateProvider = $workingStateProvider ?:
89+
ObjectManager::getInstance()->get(WorkingStateProvider::class);
7590
}
7691

7792
/**
@@ -82,6 +97,7 @@ public function __construct(
8297
* @return $this
8398
* @throws \Exception if metadataPool doesn't contain metadata for ProductInterface
8499
* @throws \DomainException
100+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
85101
*/
86102
public function execute(array $entityIds = [], $useTempTable = false)
87103
{
@@ -90,46 +106,68 @@ public function execute(array $entityIds = [], $useTempTable = false)
90106
$this->limitationByProducts = $idsToBeReIndexed;
91107
$this->useTempTable = $useTempTable;
92108
$indexer = $this->indexerRegistry->get(CategoryProductIndexer::INDEXER_ID);
93-
$workingState = $indexer->isWorking();
109+
$workingState = $this->isWorkingState();
94110

95-
$affectedCategories = $this->getCategoryIdsFromIndex($idsToBeReIndexed);
111+
if (!$indexer->isScheduled()
112+
|| ($indexer->isScheduled() && !$useTempTable)
113+
|| ($indexer->isScheduled() && $useTempTable && !$workingState)) {
96114

97-
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
98-
foreach ($this->storeManager->getStores() as $store) {
99-
$this->connection->truncateTable($this->getIndexTable($store->getId()));
115+
$affectedCategories = $this->getCategoryIdsFromIndex($idsToBeReIndexed);
116+
117+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
118+
foreach ($this->storeManager->getStores() as $store) {
119+
$this->connection->truncateTable($this->getIndexTable($store->getId()));
120+
}
121+
} else {
122+
$this->removeEntries();
100123
}
101-
} else {
102-
$this->removeEntries();
103-
}
104-
$this->reindex();
105-
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
106-
foreach ($this->storeManager->getStores() as $store) {
107-
$this->connection->delete(
108-
$this->tableMaintainer->getMainTable($store->getId()),
109-
['product_id IN (?)' => $this->limitationByProducts]
110-
);
111-
$select = $this->connection->select()
112-
->from($this->tableMaintainer->getMainReplicaTable($store->getId()));
113-
$this->connection->query(
114-
$this->connection->insertFromSelect(
115-
$select,
124+
$this->reindex();
125+
126+
// get actual state
127+
$workingState = $this->isWorkingState();
128+
129+
if ($useTempTable && !$workingState && $indexer->isScheduled()) {
130+
foreach ($this->storeManager->getStores() as $store) {
131+
$this->connection->delete(
116132
$this->tableMaintainer->getMainTable($store->getId()),
117-
[],
118-
AdapterInterface::INSERT_ON_DUPLICATE
119-
)
120-
);
133+
['product_id IN (?)' => $this->limitationByProducts]
134+
);
135+
$select = $this->connection->select()
136+
->from($this->tableMaintainer->getMainReplicaTable($store->getId()));
137+
$this->connection->query(
138+
$this->connection->insertFromSelect(
139+
$select,
140+
$this->tableMaintainer->getMainTable($store->getId()),
141+
[],
142+
AdapterInterface::INSERT_ON_DUPLICATE
143+
)
144+
);
145+
}
121146
}
122-
}
123147

124-
$affectedCategories = array_merge($affectedCategories, $this->getCategoryIdsFromIndex($idsToBeReIndexed));
148+
$affectedCategories = array_merge($affectedCategories, $this->getCategoryIdsFromIndex($idsToBeReIndexed));
125149

126-
$this->registerProducts($idsToBeReIndexed);
127-
$this->registerCategories($affectedCategories);
128-
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
150+
$this->registerProducts($idsToBeReIndexed);
151+
$this->registerCategories($affectedCategories);
152+
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
153+
}
129154

130155
return $this;
131156
}
132157

158+
/**
159+
* Get state for current and shared indexer
160+
*
161+
* @return bool
162+
*/
163+
private function isWorkingState() : bool
164+
{
165+
$indexer = $this->indexerRegistry->get(CategoryProductIndexer::INDEXER_ID);
166+
$sharedIndexer = $this->indexerRegistry->get(ProductCategoryIndexer::INDEXER_ID);
167+
return $this->workingStateProvider->isWorking($indexer->getId())
168+
|| $this->workingStateProvider->isWorking($sharedIndexer->getId());
169+
}
170+
133171
/**
134172
* Get IDs of parent products by their child IDs.
135173
*

app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,26 +77,26 @@ protected function processDeletedImages($product, array &$images)
7777
{
7878
$filesToDelete = [];
7979
$recordsToDelete = [];
80-
$picturesInOtherStores = [];
8180
$imagesToDelete = [];
82-
83-
foreach ($this->resourceModel->getProductImages($product, $this->extractStoreIds($product)) as $image) {
84-
$picturesInOtherStores[$image['filepath']] = true;
81+
$imagesToNotDelete = [];
82+
foreach ($images as $image) {
83+
if (empty($image['removed'])) {
84+
$imagesToNotDelete[] = $image['file'];
85+
}
8586
}
8687

87-
foreach ($images as &$image) {
88+
foreach ($images as $image) {
8889
if (!empty($image['removed'])) {
8990
if (!empty($image['value_id'])) {
9091
if (preg_match('/\.\.(\\\|\/)/', $image['file'])) {
9192
continue;
9293
}
9394
$recordsToDelete[] = $image['value_id'];
94-
$imagesToDelete[] = $image['file'];
95-
$catalogPath = $this->mediaConfig->getBaseMediaPath();
96-
$isFile = $this->mediaDirectory->isFile($catalogPath . $image['file']);
97-
// only delete physical files if they are not used by any other products and if this file exist
98-
if ($isFile && !($this->resourceModel->countImageUses($image['file']) > 1)) {
99-
$filesToDelete[] = ltrim($image['file'], '/');
95+
if (!in_array($image['file'], $imagesToNotDelete)) {
96+
$imagesToDelete[] = $image['file'];
97+
if ($this->canDeleteImage($image['file'])) {
98+
$filesToDelete[] = ltrim($image['file'], '/');
99+
}
100100
}
101101
}
102102
}
@@ -107,6 +107,19 @@ protected function processDeletedImages($product, array &$images)
107107
$this->removeDeletedImages($filesToDelete);
108108
}
109109

110+
/**
111+
* Check if image exists and is not used by any other products
112+
*
113+
* @param string $file
114+
* @return bool
115+
*/
116+
private function canDeleteImage(string $file): bool
117+
{
118+
$catalogPath = $this->mediaConfig->getBaseMediaPath();
119+
return $this->mediaDirectory->isFile($catalogPath . $file)
120+
&& $this->resourceModel->countImageUses($file) <= 1;
121+
}
122+
110123
/**
111124
* @inheritdoc
112125
*

0 commit comments

Comments
 (0)