Skip to content

Commit bfb57bf

Browse files
committed
Merge branch '2.3-develop' of https://github.com/magento/magento2ce into MC-35149
2 parents 55970f0 + dd63719 commit bfb57bf

File tree

31 files changed

+785
-148
lines changed

31 files changed

+785
-148
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,10 @@ public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC)
17181718
// optimize if using cat index
17191719
$filters = $this->_productLimitationFilters;
17201720
if (isset($filters['category_id']) || isset($filters['visibility'])) {
1721-
$this->getSelect()->order('cat_index.position ' . $dir);
1721+
$this->getSelect()->order([
1722+
'cat_index.position ' . $dir,
1723+
'e.entity_id ' . \Magento\Framework\DB\Select::SQL_DESC
1724+
]);
17221725
} else {
17231726
$this->getSelect()->order('e.entity_id ' . $dir);
17241727
}

app/code/Magento/CatalogGraphQl/Model/ProductLinksTypeResolver.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface;
1111

1212
/**
13-
* {@inheritdoc}
13+
* @inheritdoc
1414
*/
1515
class ProductLinksTypeResolver implements TypeResolverInterface
1616
{
@@ -20,9 +20,9 @@ class ProductLinksTypeResolver implements TypeResolverInterface
2020
private $linkTypes = ['related', 'upsell', 'crosssell'];
2121

2222
/**
23-
* {@inheritdoc}
23+
* @inheritdoc
2424
*/
25-
public function resolveType(array $data) : string
25+
public function resolveType(array $data): string
2626
{
2727
if (isset($data['link_type'])) {
2828
$linkType = $data['link_type'];

app/code/Magento/CatalogGraphQl/Model/Resolver/Product/BatchProductLinks.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,15 @@ class BatchProductLinks implements BatchServiceContractResolverInterface
2222
/**
2323
* @var string[]
2424
*/
25-
private static $linkTypes = ['related', 'upsell', 'crosssell'];
25+
private $linkTypes;
26+
27+
/**
28+
* @param array $linkTypes
29+
*/
30+
public function __construct(array $linkTypes)
31+
{
32+
$this->linkTypes = $linkTypes;
33+
}
2634

2735
/**
2836
* @inheritDoc
@@ -44,7 +52,7 @@ public function convertToServiceArgument(ResolveRequestInterface $request)
4452
/** @var \Magento\Catalog\Model\Product $product */
4553
$product = $value['model'];
4654

47-
return new ListCriteria((string)$product->getId(), self::$linkTypes, $product);
55+
return new ListCriteria((string)$product->getId(), $this->linkTypes, $product);
4856
}
4957

5058
/**

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77

88
namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider;
99

10+
use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
12+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
1013
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionPostProcessor;
14+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface;
15+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch\ProductCollectionSearchCriteriaBuilder;
1116
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierFactory;
1217
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface;
1318
use Magento\Framework\Api\Search\SearchResultInterface;
1419
use Magento\Framework\Api\SearchCriteriaInterface;
15-
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
16-
use Magento\Catalog\Model\ResourceModel\Product\Collection;
17-
use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory;
1820
use Magento\Framework\Api\SearchResultsInterface;
19-
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface;
21+
use Magento\Framework\App\ObjectManager;
2022

2123
/**
2224
* Product field data provider for product search, used for GraphQL resolver processing.
@@ -48,25 +50,34 @@ class ProductSearch
4850
*/
4951
private $searchResultApplierFactory;
5052

53+
/**
54+
* @var ProductCollectionSearchCriteriaBuilder
55+
*/
56+
private $searchCriteriaBuilder;
57+
5158
/**
5259
* @param CollectionFactory $collectionFactory
5360
* @param ProductSearchResultsInterfaceFactory $searchResultsFactory
5461
* @param CollectionProcessorInterface $collectionPreProcessor
5562
* @param CollectionPostProcessor $collectionPostProcessor
5663
* @param SearchResultApplierFactory $searchResultsApplierFactory
64+
* @param ProductCollectionSearchCriteriaBuilder|null $searchCriteriaBuilder
5765
*/
5866
public function __construct(
5967
CollectionFactory $collectionFactory,
6068
ProductSearchResultsInterfaceFactory $searchResultsFactory,
6169
CollectionProcessorInterface $collectionPreProcessor,
6270
CollectionPostProcessor $collectionPostProcessor,
63-
SearchResultApplierFactory $searchResultsApplierFactory
71+
SearchResultApplierFactory $searchResultsApplierFactory,
72+
?ProductCollectionSearchCriteriaBuilder $searchCriteriaBuilder = null
6473
) {
6574
$this->collectionFactory = $collectionFactory;
6675
$this->searchResultsFactory = $searchResultsFactory;
6776
$this->collectionPreProcessor = $collectionPreProcessor;
6877
$this->collectionPostProcessor = $collectionPostProcessor;
6978
$this->searchResultApplierFactory = $searchResultsApplierFactory;
79+
$this->searchCriteriaBuilder = $searchCriteriaBuilder
80+
?? ObjectManager::getInstance()->get(ProductCollectionSearchCriteriaBuilder::class);
7081
}
7182

7283
/**
@@ -85,15 +96,21 @@ public function getList(
8596
/** @var Collection $collection */
8697
$collection = $this->collectionFactory->create();
8798

88-
//Join search results
89-
$this->getSearchResultsApplier($searchResult, $collection, $this->getSortOrderArray($searchCriteria))->apply();
99+
//Create a copy of search criteria without filters to preserve the results from search
100+
$searchCriteriaForCollection = $this->searchCriteriaBuilder->build($searchCriteria);
101+
//Apply CatalogSearch results from search and join table
102+
$this->getSearchResultsApplier(
103+
$searchResult,
104+
$collection,
105+
$this->getSortOrderArray($searchCriteriaForCollection)
106+
)->apply();
90107

91-
$this->collectionPreProcessor->process($collection, $searchCriteria, $attributes);
108+
$this->collectionPreProcessor->process($collection, $searchCriteriaForCollection, $attributes);
92109
$collection->load();
93110
$this->collectionPostProcessor->process($collection, $attributes);
94111

95112
$searchResults = $this->searchResultsFactory->create();
96-
$searchResults->setSearchCriteria($searchCriteria);
113+
$searchResults->setSearchCriteria($searchCriteriaForCollection);
97114
$searchResults->setItems($collection->getItems());
98115
$searchResults->setTotalCount($searchResult->getTotalCount());
99116
return $searchResults;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch;
9+
10+
use Magento\Catalog\Model\CategoryProductLink;
11+
use Magento\Framework\Api\FilterBuilder;
12+
use Magento\Framework\Api\Search\FilterGroupBuilder;
13+
use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory;
14+
use Magento\Framework\Api\SearchCriteriaInterface;
15+
16+
/**
17+
* Builds a search criteria intended for the product collection based on search criteria used on SearchAPI
18+
*/
19+
class ProductCollectionSearchCriteriaBuilder
20+
{
21+
/** @var SearchCriteriaInterfaceFactory */
22+
private $searchCriteriaFactory;
23+
24+
/** @var FilterBuilder */
25+
private $filterBuilder;
26+
27+
/** @var FilterGroupBuilder */
28+
private $filterGroupBuilder;
29+
30+
/**
31+
* @param SearchCriteriaInterfaceFactory $searchCriteriaFactory
32+
* @param FilterBuilder $filterBuilder
33+
* @param FilterGroupBuilder $filterGroupBuilder
34+
*/
35+
public function __construct(
36+
SearchCriteriaInterfaceFactory $searchCriteriaFactory,
37+
FilterBuilder $filterBuilder,
38+
FilterGroupBuilder $filterGroupBuilder
39+
) {
40+
$this->searchCriteriaFactory = $searchCriteriaFactory;
41+
$this->filterBuilder = $filterBuilder;
42+
$this->filterGroupBuilder = $filterGroupBuilder;
43+
}
44+
45+
/**
46+
* Build searchCriteria from search for product collection
47+
*
48+
* @param SearchCriteriaInterface $searchCriteria
49+
* @return SearchCriteriaInterface
50+
*/
51+
public function build(SearchCriteriaInterface $searchCriteria): SearchCriteriaInterface
52+
{
53+
//Create a copy of search criteria without filters to preserve the results from search
54+
$searchCriteriaForCollection = $this->searchCriteriaFactory->create()
55+
->setSortOrders($searchCriteria->getSortOrders())
56+
->setPageSize($searchCriteria->getPageSize())
57+
->setCurrentPage($searchCriteria->getCurrentPage());
58+
59+
//Add category id to enable sorting by position
60+
foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
61+
foreach ($filterGroup->getFilters() as $filter) {
62+
if ($filter->getField() == CategoryProductLink::KEY_CATEGORY_ID) {
63+
$categoryFilter = $this->filterBuilder
64+
->setField($filter->getField())
65+
->setValue($filter->getValue())
66+
->setConditionType($filter->getConditionType())
67+
->create();
68+
69+
$this->filterGroupBuilder->addFilter($categoryFilter);
70+
$categoryGroup = $this->filterGroupBuilder->create();
71+
$searchCriteriaForCollection->setFilterGroups([$categoryGroup]);
72+
}
73+
}
74+
}
75+
return $searchCriteriaForCollection;
76+
}
77+
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99

1010
use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder;
1111
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch;
12-
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13-
use Magento\Framework\Api\Search\SearchCriteriaInterface;
1412
use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResult;
1513
use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory;
14+
use Magento\Framework\Api\Search\SearchCriteriaInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1616
use Magento\Search\Api\SearchInterface;
1717
use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory;
1818
use Magento\Search\Model\Search\PageSizeProvider;
@@ -101,28 +101,18 @@ public function getResult(
101101

102102
$realPageSize = $searchCriteria->getPageSize();
103103
$realCurrentPage = $searchCriteria->getCurrentPage();
104-
// Current page must be set to 0 and page size to max for search to grab all ID's as temporary workaround
104+
//Because of limitations of sort and pagination on search API we will query all IDS
105105
$pageSize = $this->pageSizeProvider->getMaxPageSize();
106106
$searchCriteria->setPageSize($pageSize);
107107
$searchCriteria->setCurrentPage(0);
108108
$itemsResults = $this->search->search($searchCriteria);
109109

110-
//Create copy of search criteria without conditions (conditions will be applied by joining search result)
111-
$searchCriteriaCopy = $this->searchCriteriaFactory->create()
112-
->setSortOrders($searchCriteria->getSortOrders())
113-
->setPageSize($realPageSize)
114-
->setCurrentPage($realCurrentPage);
115-
116-
$searchResults = $this->productsProvider->getList($searchCriteriaCopy, $itemsResults, $queryFields);
117-
118-
//possible division by 0
119-
if ($realPageSize) {
120-
$maxPages = (int)ceil($searchResults->getTotalCount() / $realPageSize);
121-
} else {
122-
$maxPages = 0;
123-
}
110+
//Address limitations of sort and pagination on search API apply original pagination from GQL query
124111
$searchCriteria->setPageSize($realPageSize);
125112
$searchCriteria->setCurrentPage($realCurrentPage);
113+
$searchResults = $this->productsProvider->getList($searchCriteria, $itemsResults, $queryFields);
114+
115+
$totalPages = $realPageSize ? ((int)ceil($searchResults->getTotalCount() / $realPageSize)) : 0;
126116

127117
$productArray = [];
128118
/** @var \Magento\Catalog\Model\Product $product */
@@ -138,7 +128,7 @@ public function getResult(
138128
'searchAggregation' => $itemsResults->getAggregations(),
139129
'pageSize' => $realPageSize,
140130
'currentPage' => $realCurrentPage,
141-
'totalPages' => $maxPages,
131+
'totalPages' => $totalPages,
142132
]
143133
);
144134
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function apply(Filter $filter, AbstractDb $collection)
6161
$category = $this->categoryFactory->create();
6262
$this->categoryResourceModel->load($category, $categoryId);
6363
$categoryProducts[$categoryId] = $category->getProductCollection()->getAllIds();
64+
$collection->addCategoryFilter($category);
6465
}
6566

6667
$categoryProductIds = array_unique(array_merge(...$categoryProducts));

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,14 @@
7373
<preference type="\Magento\CatalogGraphQl\Model\Resolver\Product\Price\Provider" for="\Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderInterface"/>
7474

7575
<preference type="Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search" for="Magento\CatalogGraphQl\Model\Resolver\Products\Query\ProductQueryInterface"/>
76+
77+
<type name="\Magento\CatalogGraphQl\Model\Resolver\Product\BatchProductLinks">
78+
<arguments>
79+
<argument name="linkTypes" xsi:type="array">
80+
<item name="related" xsi:type="string">related</item>
81+
<item name="upsell" xsi:type="string">upsell</item>
82+
<item name="crosssell" xsi:type="string">crosssell</item>
83+
</argument>
84+
</arguments>
85+
</type>
7686
</config>

app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@
4444
<!-- ko if: Array.isArray(option.value) -->
4545
<span data-bind="html: option.value.join('<br>')"></span>
4646
<!-- /ko -->
47-
<!-- ko if: (!Array.isArray(option.value) && option.option_type == 'file') -->
47+
<!-- ko if: (!Array.isArray(option.value) && ['file', 'html'].includes(option.option_type)) -->
4848
<span data-bind="html: option.value"></span>
4949
<!-- /ko -->
50-
<!-- ko if: (!Array.isArray(option.value) && option.option_type != 'file') -->
51-
<span data-bind="text: option.value"></span>
50+
<!-- ko if: (!Array.isArray(option.value) && !['file', 'html'].includes(option.option_type)) -->
51+
<span data-bind="text: option.value"></span>
5252
<!-- /ko -->
5353
</dd>
5454
<!-- /ko -->

app/code/Magento/Config/Model/Config.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ public function save()
208208
);
209209

210210
$groupChangedPaths = $this->getChangedPaths($sectionId, $groupId, $groupData, $oldConfig, $extraOldGroups);
211+
// phpcs:ignore Magento2.Performance.ForeachArrayMerge
211212
$changedPaths = \array_merge($changedPaths, $groupChangedPaths);
212213
}
213214

@@ -370,6 +371,7 @@ private function getChangedPaths(
370371
$oldConfig,
371372
$extraOldGroups
372373
);
374+
// phpcs:ignore Magento2.Performance.ForeachArrayMerge
373375
$changedPaths = \array_merge($changedPaths, $subGroupChangedPaths);
374376
}
375377
}
@@ -435,11 +437,11 @@ protected function _processGroup(
435437
if (!isset($fieldData['value'])) {
436438
$fieldData['value'] = null;
437439
}
438-
440+
439441
if ($field->getType() == 'multiline' && is_array($fieldData['value'])) {
440442
$fieldData['value'] = trim(implode(PHP_EOL, $fieldData['value']));
441443
}
442-
444+
443445
$data = [
444446
'field' => $fieldId,
445447
'groups' => $groups,
@@ -453,7 +455,7 @@ protected function _processGroup(
453455
$backendModel->addData($data);
454456
$this->_checkSingleStoreMode($field, $backendModel);
455457

456-
$path = $this->getFieldPath($field, $fieldId, $extraOldGroups, $oldConfig);
458+
$path = $this->getFieldPath($field, $fieldId, $oldConfig, $extraOldGroups);
457459
$backendModel->setPath($path)->setValue($fieldData['value']);
458460

459461
$inherit = !empty($fieldData['inherit']);

0 commit comments

Comments
 (0)