Skip to content

Commit d02753e

Browse files
author
Joan He
committed
Merge remote-tracking branch 'upstream/2.3-develop' into MAGETWO-90006
2 parents b7039bb + 4822bb1 commit d02753e

File tree

142 files changed

+3329
-720
lines changed

Some content is hidden

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

142 files changed

+3329
-720
lines changed

app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ define([
145145
_initBraintree: function () {
146146
var self = this;
147147

148+
this.disableEventListeners();
149+
148150
self.braintree.setup(self.clientToken, 'custom', {
149151
id: self.selector,
150152
hostedFields: self.getHostedFields(),
@@ -154,6 +156,7 @@ define([
154156
*/
155157
onReady: function () {
156158
$('body').trigger('processStop');
159+
self.enableEventListeners();
157160
},
158161

159162
/**

app/code/Magento/Catalog/Model/Category.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,11 @@ public function getAnchorsAbove()
954954
*/
955955
public function getProductCount()
956956
{
957-
$count = $this->_getResource()->getProductCount($this);
958-
$this->setData(self::KEY_PRODUCT_COUNT, $count);
957+
if (!$this->hasData(self::KEY_PRODUCT_COUNT)) {
958+
$count = $this->_getResource()->getProductCount($this);
959+
$this->setData(self::KEY_PRODUCT_COUNT, $count);
960+
}
961+
959962
return $this->getData(self::KEY_PRODUCT_COUNT);
960963
}
961964

app/code/Magento/Catalog/Model/Indexer/Category/Product/AbstractAction.php

Lines changed: 113 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66

77
namespace Magento\Catalog\Model\Indexer\Category\Product;
88

9+
use Magento\Catalog\Api\Data\ProductInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Framework\App\ObjectManager;
912
use Magento\Framework\DB\Query\Generator as QueryGenerator;
1013
use Magento\Framework\App\ResourceConnection;
14+
use Magento\Framework\DB\Select;
1115
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Store\Model\Store;
1217

1318
/**
1419
* Class AbstractAction
@@ -43,21 +48,21 @@ abstract class AbstractAction
4348
/**
4449
* Cached non anchor categories select by store id
4550
*
46-
* @var \Magento\Framework\DB\Select[]
51+
* @var Select[]
4752
*/
4853
protected $nonAnchorSelects = [];
4954

5055
/**
5156
* Cached anchor categories select by store id
5257
*
53-
* @var \Magento\Framework\DB\Select[]
58+
* @var Select[]
5459
*/
5560
protected $anchorSelects = [];
5661

5762
/**
5863
* Cached all product select by store id
5964
*
60-
* @var \Magento\Framework\DB\Select[]
65+
* @var Select[]
6166
*/
6267
protected $productsSelects = [];
6368

@@ -116,20 +121,22 @@ abstract class AbstractAction
116121
* @param ResourceConnection $resource
117122
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
118123
* @param \Magento\Catalog\Model\Config $config
119-
* @param QueryGenerator $queryGenerator
124+
* @param QueryGenerator|null $queryGenerator
125+
* @param MetadataPool|null $metadataPool
120126
*/
121127
public function __construct(
122128
\Magento\Framework\App\ResourceConnection $resource,
123129
\Magento\Store\Model\StoreManagerInterface $storeManager,
124130
\Magento\Catalog\Model\Config $config,
125-
QueryGenerator $queryGenerator = null
131+
QueryGenerator $queryGenerator = null,
132+
MetadataPool $metadataPool = null
126133
) {
127134
$this->resource = $resource;
128135
$this->connection = $resource->getConnection();
129136
$this->storeManager = $storeManager;
130137
$this->config = $config;
131-
$this->queryGenerator = $queryGenerator ?: \Magento\Framework\App\ObjectManager::getInstance()
132-
->get(QueryGenerator::class);
138+
$this->queryGenerator = $queryGenerator ?: ObjectManager::getInstance()->get(QueryGenerator::class);
139+
$this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class);
133140
}
134141

135142
/**
@@ -186,9 +193,9 @@ protected function getMainTable()
186193
*/
187194
protected function getMainTmpTable()
188195
{
189-
return $this->useTempTable ? $this->getTable(
190-
self::MAIN_INDEX_TABLE . self::TEMPORARY_TABLE_SUFFIX
191-
) : $this->getMainTable();
196+
return $this->useTempTable
197+
? $this->getTable(self::MAIN_INDEX_TABLE . self::TEMPORARY_TABLE_SUFFIX)
198+
: $this->getMainTable();
192199
}
193200

194201
/**
@@ -216,24 +223,25 @@ protected function getPathFromCategoryId($categoryId)
216223
/**
217224
* Retrieve select for reindex products of non anchor categories
218225
*
219-
* @param \Magento\Store\Model\Store $store
220-
* @return \Magento\Framework\DB\Select
226+
* @param Store $store
227+
* @return Select
228+
* @throws \Exception when metadata not found for ProductInterface
221229
*/
222-
protected function getNonAnchorCategoriesSelect(\Magento\Store\Model\Store $store)
230+
protected function getNonAnchorCategoriesSelect(Store $store)
223231
{
224232
if (!isset($this->nonAnchorSelects[$store->getId()])) {
225233
$statusAttributeId = $this->config->getAttribute(
226-
\Magento\Catalog\Model\Product::ENTITY,
234+
Product::ENTITY,
227235
'status'
228236
)->getId();
229237
$visibilityAttributeId = $this->config->getAttribute(
230-
\Magento\Catalog\Model\Product::ENTITY,
238+
Product::ENTITY,
231239
'visibility'
232240
)->getId();
233241

234242
$rootPath = $this->getPathFromCategoryId($store->getRootCategoryId());
235243

236-
$metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
244+
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
237245
$linkField = $metadata->getLinkField();
238246
$select = $this->connection->select()->from(
239247
['cc' => $this->getTable('catalog_category_entity')],
@@ -302,12 +310,65 @@ protected function getNonAnchorCategoriesSelect(\Magento\Store\Model\Store $stor
302310
]
303311
);
304312

313+
$this->addFilteringByChildProductsToSelect($select, $store);
314+
305315
$this->nonAnchorSelects[$store->getId()] = $select;
306316
}
307317

308318
return $this->nonAnchorSelects[$store->getId()];
309319
}
310320

321+
/**
322+
* Add filtering by child products to select.
323+
*
324+
* It's used for correct handling of composite products.
325+
* This method makes assumption that select already joins `catalog_product_entity` as `cpe`.
326+
*
327+
* @param Select $select
328+
* @param Store $store
329+
* @return void
330+
* @throws \Exception when metadata not found for ProductInterface
331+
*/
332+
private function addFilteringByChildProductsToSelect(Select $select, Store $store)
333+
{
334+
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
335+
$linkField = $metadata->getLinkField();
336+
337+
$statusAttributeId = $this->config->getAttribute(Product::ENTITY, 'status')->getId();
338+
339+
$select->joinLeft(
340+
['relation' => $this->getTable('catalog_product_relation')],
341+
'cpe.' . $linkField . ' = relation.parent_id',
342+
[]
343+
)->joinLeft(
344+
['relation_product_entity' => $this->getTable('catalog_product_entity')],
345+
'relation.child_id = relation_product_entity.entity_id',
346+
[]
347+
)->joinLeft(
348+
['child_cpsd' => $this->getTable('catalog_product_entity_int')],
349+
'child_cpsd.' . $linkField . ' = '. 'relation_product_entity.' . $linkField
350+
. ' AND child_cpsd.store_id = 0'
351+
. ' AND child_cpsd.attribute_id = ' . $statusAttributeId,
352+
[]
353+
)->joinLeft(
354+
['child_cpss' => $this->getTable('catalog_product_entity_int')],
355+
'child_cpss.' . $linkField . ' = '. 'relation_product_entity.' . $linkField . ''
356+
. ' AND child_cpss.attribute_id = child_cpsd.attribute_id'
357+
. ' AND child_cpss.store_id = ' . $store->getId(),
358+
[]
359+
)->where(
360+
'relation.child_id IS NULL OR '
361+
. $this->connection->getIfNullSql('child_cpss.value', 'child_cpsd.value') . ' = ?',
362+
\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
363+
)->group(
364+
[
365+
'cc.entity_id',
366+
'ccp.product_id',
367+
'visibility',
368+
]
369+
);
370+
}
371+
311372
/**
312373
* Check whether select ranging is needed
313374
*
@@ -321,15 +382,15 @@ protected function isRangingNeeded()
321382
/**
322383
* Return selects cut by min and max
323384
*
324-
* @param \Magento\Framework\DB\Select $select
385+
* @param Select $select
325386
* @param string $field
326387
* @param int $range
327-
* @return \Magento\Framework\DB\Select[]
388+
* @return Select[]
328389
*/
329390
protected function prepareSelectsByRange(
330-
\Magento\Framework\DB\Select $select,
331-
$field,
332-
$range = self::RANGE_CATEGORY_STEP
391+
Select $select,
392+
string $field,
393+
int $range = self::RANGE_CATEGORY_STEP
333394
) {
334395
if ($this->isRangingNeeded()) {
335396
$iterator = $this->queryGenerator->generate(
@@ -351,10 +412,10 @@ protected function prepareSelectsByRange(
351412
/**
352413
* Reindex products of non anchor categories
353414
*
354-
* @param \Magento\Store\Model\Store $store
415+
* @param Store $store
355416
* @return void
356417
*/
357-
protected function reindexNonAnchorCategories(\Magento\Store\Model\Store $store)
418+
protected function reindexNonAnchorCategories(Store $store)
358419
{
359420
$selects = $this->prepareSelectsByRange($this->getNonAnchorCategoriesSelect($store), 'entity_id');
360421
foreach ($selects as $select) {
@@ -372,43 +433,41 @@ protected function reindexNonAnchorCategories(\Magento\Store\Model\Store $store)
372433
/**
373434
* Check if anchor select isset
374435
*
375-
* @param \Magento\Store\Model\Store $store
436+
* @param Store $store
376437
* @return bool
377438
*/
378-
protected function hasAnchorSelect(\Magento\Store\Model\Store $store)
439+
protected function hasAnchorSelect(Store $store)
379440
{
380441
return isset($this->anchorSelects[$store->getId()]);
381442
}
382443

383444
/**
384445
* Create anchor select
385446
*
386-
* @param \Magento\Store\Model\Store $store
387-
* @return \Magento\Framework\DB\Select
447+
* @param Store $store
448+
* @return Select
449+
* @throws \Exception when metadata not found for ProductInterface or CategoryInterface
388450
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
389451
*/
390-
protected function createAnchorSelect(\Magento\Store\Model\Store $store)
452+
protected function createAnchorSelect(Store $store)
391453
{
392454
$isAnchorAttributeId = $this->config->getAttribute(
393455
\Magento\Catalog\Model\Category::ENTITY,
394456
'is_anchor'
395457
)->getId();
396-
$statusAttributeId = $this->config->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId();
397-
$visibilityAttributeId = $this->config->getAttribute(
398-
\Magento\Catalog\Model\Product::ENTITY,
399-
'visibility'
400-
)->getId();
458+
$statusAttributeId = $this->config->getAttribute(Product::ENTITY, 'status')->getId();
459+
$visibilityAttributeId = $this->config->getAttribute(Product::ENTITY, 'visibility')->getId();
401460
$rootCatIds = explode('/', $this->getPathFromCategoryId($store->getRootCategoryId()));
402461
array_pop($rootCatIds);
403462

404463
$temporaryTreeTable = $this->makeTempCategoryTreeIndex();
405464

406-
$productMetadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
407-
$categoryMetadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\CategoryInterface::class);
465+
$productMetadata = $this->metadataPool->getMetadata(ProductInterface::class);
466+
$categoryMetadata = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\CategoryInterface::class);
408467
$productLinkField = $productMetadata->getLinkField();
409468
$categoryLinkField = $categoryMetadata->getLinkField();
410469

411-
return $this->connection->select()->from(
470+
$select = $this->connection->select()->from(
412471
['cc' => $this->getTable('catalog_category_entity')],
413472
[]
414473
)->joinInner(
@@ -496,6 +555,10 @@ protected function createAnchorSelect(\Magento\Store\Model\Store $store)
496555
'visibility' => new \Zend_Db_Expr($this->connection->getIfNullSql('cpvs.value', 'cpvd.value')),
497556
]
498557
);
558+
559+
$this->addFilteringByChildProductsToSelect($select, $store);
560+
561+
return $select;
499562
}
500563

501564
/**
@@ -590,10 +653,10 @@ protected function fillTempCategoryTreeIndex($temporaryName)
590653
/**
591654
* Retrieve select for reindex products of non anchor categories
592655
*
593-
* @param \Magento\Store\Model\Store $store
594-
* @return \Magento\Framework\DB\Select
656+
* @param Store $store
657+
* @return Select
595658
*/
596-
protected function getAnchorCategoriesSelect(\Magento\Store\Model\Store $store)
659+
protected function getAnchorCategoriesSelect(Store $store)
597660
{
598661
if (!$this->hasAnchorSelect($store)) {
599662
$this->anchorSelects[$store->getId()] = $this->createAnchorSelect($store);
@@ -604,10 +667,10 @@ protected function getAnchorCategoriesSelect(\Magento\Store\Model\Store $store)
604667
/**
605668
* Reindex products of anchor categories
606669
*
607-
* @param \Magento\Store\Model\Store $store
670+
* @param Store $store
608671
* @return void
609672
*/
610-
protected function reindexAnchorCategories(\Magento\Store\Model\Store $store)
673+
protected function reindexAnchorCategories(Store $store)
611674
{
612675
$selects = $this->prepareSelectsByRange($this->getAnchorCategoriesSelect($store), 'entity_id');
613676

@@ -626,22 +689,17 @@ protected function reindexAnchorCategories(\Magento\Store\Model\Store $store)
626689
/**
627690
* Get select for all products
628691
*
629-
* @param \Magento\Store\Model\Store $store
630-
* @return \Magento\Framework\DB\Select
692+
* @param Store $store
693+
* @return Select
694+
* @throws \Exception when metadata not found for ProductInterface
631695
*/
632-
protected function getAllProducts(\Magento\Store\Model\Store $store)
696+
protected function getAllProducts(Store $store)
633697
{
634698
if (!isset($this->productsSelects[$store->getId()])) {
635-
$statusAttributeId = $this->config->getAttribute(
636-
\Magento\Catalog\Model\Product::ENTITY,
637-
'status'
638-
)->getId();
639-
$visibilityAttributeId = $this->config->getAttribute(
640-
\Magento\Catalog\Model\Product::ENTITY,
641-
'visibility'
642-
)->getId();
699+
$statusAttributeId = $this->config->getAttribute(Product::ENTITY, 'status')->getId();
700+
$visibilityAttributeId = $this->config->getAttribute(Product::ENTITY, 'visibility')->getId();
643701

644-
$metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
702+
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
645703
$linkField = $metadata->getLinkField();
646704

647705
$select = $this->connection->select()->from(
@@ -730,10 +788,10 @@ protected function isIndexRootCategoryNeeded()
730788
/**
731789
* Reindex all products to root category
732790
*
733-
* @param \Magento\Store\Model\Store $store
791+
* @param Store $store
734792
* @return void
735793
*/
736-
protected function reindexRootCategory(\Magento\Store\Model\Store $store)
794+
protected function reindexRootCategory(Store $store)
737795
{
738796
if ($this->isIndexRootCategoryNeeded()) {
739797
$selects = $this->prepareSelectsByRange(
@@ -754,16 +812,4 @@ protected function reindexRootCategory(\Magento\Store\Model\Store $store)
754812
}
755813
}
756814
}
757-
758-
/**
759-
* @return \Magento\Framework\EntityManager\MetadataPool
760-
*/
761-
private function getMetadataPool()
762-
{
763-
if (null === $this->metadataPool) {
764-
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
765-
->get(\Magento\Framework\EntityManager\MetadataPool::class);
766-
}
767-
return $this->metadataPool;
768-
}
769815
}

0 commit comments

Comments
 (0)