Skip to content

Commit 758f2ca

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-62593' into 2.0.15-develop-pr14
2 parents bf0a620 + 54e8480 commit 758f2ca

File tree

7 files changed

+365
-76
lines changed

7 files changed

+365
-76
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,28 @@ protected function _prepareFinalPriceData($entityIds = null)
235235
* @param string|null $type product type, all if null
236236
* @return $this
237237
* @throws \Magento\Framework\Exception\LocalizedException
238-
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
239238
*/
240239
protected function prepareFinalPriceDataForType($entityIds, $type)
241240
{
242241
$this->_prepareDefaultFinalPriceTable();
243242

243+
$select = $this->getSelect($entityIds, $type);
244+
$query = $select->insertFromSelect($this->_getDefaultFinalPriceTable(), [], false);
245+
$this->getConnection()->query($query);
246+
return $this;
247+
}
248+
249+
/**
250+
* Get select by entity ids or/and product type.
251+
*
252+
* @param int|array $entityIds the entity ids limitation
253+
* @param string|null $type product type, all if null
254+
* @return \Magento\Framework\DB\Select
255+
* @throws \Magento\Framework\Exception\LocalizedException
256+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
257+
*/
258+
protected function getSelect($entityIds = null, $type = null)
259+
{
244260
$connection = $this->getConnection();
245261
$select = $connection->select()->from(
246262
['e' => $this->getTable('catalog_product_entity')],
@@ -340,9 +356,7 @@ protected function prepareFinalPriceDataForType($entityIds, $type)
340356
]
341357
);
342358

343-
$query = $select->insertFromSelect($this->_getDefaultFinalPriceTable(), [], false);
344-
$connection->query($query);
345-
return $this;
359+
return $select;
346360
}
347361

348362
/**

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -86,44 +86,13 @@ public function reindexEntity($entityIds)
8686
protected function reindex($entityIds = null)
8787
{
8888
if ($this->hasEntity() || !empty($entityIds)) {
89-
if (!empty($entityIds)) {
90-
$allEntityIds = $this->getRelatedProducts($entityIds);
91-
$this->prepareFinalPriceDataForType($allEntityIds, null);
92-
} else {
93-
$this->_prepareFinalPriceData($entityIds);
94-
}
89+
$this->prepareFinalPriceDataForType($entityIds, $this->getTypeId());
9590
$this->_applyCustomOption();
96-
$this->_applyConfigurableOption($entityIds);
91+
$this->_applyConfigurableOption();
9792
$this->_movePriceDataToIndexTable($entityIds);
9893
}
99-
return $this;
100-
}
10194

102-
/**
103-
* Get related product
104-
*
105-
* @param int[] $entityIds
106-
* @return int[]
107-
*/
108-
private function getRelatedProducts($entityIds)
109-
{
110-
$select = $this->getConnection()->select()->union(
111-
[
112-
$this->getConnection()->select()
113-
->from($this->getTable('catalog_product_super_link'), 'parent_id')
114-
->where('parent_id in (?)', $entityIds),
115-
$this->getConnection()->select()
116-
->from($this->getTable('catalog_product_super_link'), 'product_id')
117-
->where('parent_id in (?)', $entityIds),
118-
$this->getConnection()->select()
119-
->from($this->getTable('catalog_product_super_link'), 'product_id')
120-
->where('product_id in (?)', $entityIds),
121-
]
122-
);
123-
return array_map(
124-
'intval',
125-
$this->getConnection()->fetchCol($select)
126-
);
95+
return $this;
12796
}
12897

12998
/**
@@ -183,49 +152,27 @@ protected function _applyConfigurableOption()
183152

184153
$this->_prepareConfigurableOptionAggregateTable();
185154
$this->_prepareConfigurableOptionPriceTable();
186-
187-
$statusAttribute = $this->_getAttribute(ProductInterface::STATUS);
188-
189-
$select = $connection->select()->from(
190-
['i' => $this->_getDefaultFinalPriceTable()],
191-
[]
192-
)->join(
155+
$subSelect = $this->getSelect();
156+
$subSelect->join(
193157
['l' => $this->getTable('catalog_product_super_link')],
194-
'l.parent_id = i.entity_id',
195-
['parent_id', 'product_id']
196-
)->columns(
197-
['customer_group_id', 'website_id'],
198-
'i'
158+
'l.product_id = e.entity_id',
159+
[]
199160
)->join(
200161
['le' => $this->getTable('catalog_product_entity')],
201-
'le.entity_id = l.product_id',
202-
[]
203-
)->where(
204-
'le.required_options=0'
205-
)->joinLeft(
206-
['status_global_attr' => $statusAttribute->getBackendTable()],
207-
"status_global_attr.entity_id = le.entity_id"
208-
. ' AND status_global_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId()
209-
. ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID,
210-
[]
211-
)->joinLeft(
212-
['status_attr' => $statusAttribute->getBackendTable()],
213-
"status_attr.entity_id = le.entity_id"
214-
. ' AND status_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId()
215-
. ' AND status_attr.store_id = ' . $this->storeResolver->getCurrentStoreId(),
216-
[]
217-
)->where(
218-
'IFNULL(status_attr.value, status_global_attr.value) = ?',
219-
ProductStatus::STATUS_ENABLED
220-
)->group(
221-
['l.parent_id', 'i.customer_group_id', 'i.website_id', 'l.product_id']
162+
'le.entity_id = l.parent_id',
163+
['parent_id' => 'entity_id']
222164
);
223-
$priceColumn = $this->_addAttributeToSelect($select, 'price', 'l.product_id', 0, null, true);
224-
$tierPriceColumn = $connection->getIfNullSql('MIN(i.tier_price)', 'NULL');
225165

226-
$select->columns(
227-
['price' => $priceColumn, 'tier_price' => $tierPriceColumn]
228-
);
166+
$select = $connection->select();
167+
$select->from(['sub' => new \Zend_Db_Expr('(' . (string)$subSelect . ')')], '')
168+
->columns([
169+
'sub.parent_id',
170+
'sub.entity_id',
171+
'sub.customer_group_id',
172+
'sub.website_id',
173+
'sub.price',
174+
'sub.tier_price',
175+
]);
229176

230177
$query = $select->insertFromSelect($coaTable);
231178
$connection->query($query);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
use Magento\Catalog\Model\Indexer\Product\Price\Processor;
7+
use Magento\TestFramework\Helper\Bootstrap;
8+
9+
$indexerProcessor = Bootstrap::getObjectManager()->get(Processor::class);
10+
$indexerProcessor->getIndexer()->setScheduled(true);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
use Magento\Catalog\Model\Indexer\Product\Price\Processor;
7+
use Magento\TestFramework\Helper\Bootstrap;
8+
9+
$indexerProcessor = Bootstrap::getObjectManager()->get(Processor::class);
10+
$indexerProcessor->getIndexer()->setScheduled(false);
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableProduct\Pricing\Price;
7+
8+
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Catalog\Model\Indexer\Product\Price\Processor;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
13+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
16+
class SpecialPriceIndexerTest extends \PHPUnit_Framework_TestCase
17+
{
18+
/**
19+
* @var ProductRepositoryInterface
20+
*/
21+
private $productRepository;
22+
23+
/**
24+
* @var CollectionFactory
25+
*/
26+
private $productCollectionFactory;
27+
28+
/**
29+
* @var Processor
30+
*/
31+
private $indexerProcessor;
32+
33+
protected function setUp()
34+
{
35+
$this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
36+
$this->productCollectionFactory = Bootstrap::getObjectManager()->get(CollectionFactory::class);
37+
$this->indexerProcessor = Bootstrap::getObjectManager()->get(Processor::class);
38+
}
39+
40+
/**
41+
* Use collection to check data in index
42+
* Do not use magentoDbIsolation because index statement changing "tears" transaction (triggers creating)
43+
*
44+
* @magentoAppIsolation enabled
45+
* @magentoDbIsolation enabled
46+
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
47+
* @magentoDataFixture Magento/Catalog/_files/enable_price_index_schedule.php
48+
*/
49+
public function testFullReindexIfChildHasSpecialPrice()
50+
{
51+
$specialPrice = 2;
52+
/** @var Product $childProduct */
53+
$childProduct = $this->productRepository->get('simple_10', true);
54+
$childProduct->setData('special_price', $specialPrice);
55+
56+
$this->productRepository->save($childProduct);
57+
58+
/** @var ProductCollection $collection */
59+
$collection = $this->productCollectionFactory->create();
60+
$collection
61+
->addPriceData()
62+
->addFieldToFilter(ProductInterface::SKU, 'configurable');
63+
64+
/** @var Product[] $items */
65+
$items = array_values($collection->getItems());
66+
self::assertEquals(10, $items[0]->getData('min_price'));
67+
68+
$this->indexerProcessor->reindexAll();
69+
70+
/** @var ProductCollection $collection */
71+
$collection = $this->productCollectionFactory->create();
72+
$collection
73+
->addPriceData()
74+
->addFieldToFilter(ProductInterface::SKU, 'configurable');
75+
76+
/** @var Product $item */
77+
$item = $collection->getFirstItem();
78+
79+
self::assertEquals($specialPrice, $item->getData('min_price'));
80+
}
81+
82+
/**
83+
* Use collection to check data in index
84+
*
85+
* @magentoAppIsolation enabled
86+
* @magentoDbIsolation enabled
87+
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
88+
*/
89+
public function testOnSaveIndexationIfChildHasSpecialPrice()
90+
{
91+
$specialPrice = 2;
92+
93+
/** @var Product $childProduct */
94+
$childProduct = $this->productRepository->get('simple_10', true);
95+
$childProduct->setData('special_price', $specialPrice);
96+
$this->productRepository->save($childProduct);
97+
98+
/** @var ProductCollection $collection */
99+
$collection = $this->productCollectionFactory->create();
100+
$collection
101+
->addPriceData()
102+
->addFieldToFilter(ProductInterface::SKU, 'configurable');
103+
104+
/** @var Product $item */
105+
$item = $collection->getFirstItem();
106+
107+
self::assertEquals($specialPrice, $item->getData('min_price'));
108+
}
109+
}

0 commit comments

Comments
 (0)