Skip to content

Commit b365145

Browse files
committed
ACP2E-531: [Magento Cloud] Filtering with multiple categories sorting by position not working as expected
1 parent 438545d commit b365145

File tree

6 files changed

+138
-235
lines changed

6 files changed

+138
-235
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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\Catalog\Model\ResourceModel\Product\Collection;
9+
10+
use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
12+
use Magento\Framework\DB\Select;
13+
14+
class JoinMinimalPosition
15+
{
16+
/**
17+
* @var TableMaintainer
18+
*/
19+
private $tableMaintainer;
20+
21+
/**
22+
* @param TableMaintainer $tableMaintainer
23+
*/
24+
public function __construct(
25+
TableMaintainer $tableMaintainer
26+
) {
27+
$this->tableMaintainer = $tableMaintainer;
28+
}
29+
30+
/**
31+
* Add minimal position to the collection select
32+
*
33+
* @param Collection $collection
34+
* @param array $categoryIds
35+
* @return void
36+
* @throws \Magento\Framework\Exception\LocalizedException
37+
* @throws \Zend_Db_Select_Exception
38+
*/
39+
public function execute(Collection $collection, array $categoryIds): void
40+
{
41+
$positions = [];
42+
$connection = $collection->getConnection();
43+
$select = $collection->getSelect();
44+
45+
foreach ($categoryIds as $categoryId) {
46+
$table = 'cat_index_' . $categoryId;
47+
$conditions = [
48+
$table . '.product_id=e.entity_id',
49+
$connection->quoteInto(
50+
$table . '.store_id=?',
51+
$collection->getStoreId(),
52+
'int'
53+
),
54+
$connection->quoteInto(
55+
$table . '.category_id=?',
56+
$categoryId,
57+
'int'
58+
)
59+
];
60+
61+
$joinCond = implode(' AND ', $conditions);
62+
$fromPart = $select->getPart(Select::FROM);
63+
if (isset($fromPart[$table])) {
64+
$fromPart[$table]['joinCondition'] = $joinCond;
65+
$select->setPart(Select::FROM, $fromPart);
66+
} else {
67+
$select->joinLeft(
68+
[$table => $this->tableMaintainer->getMainTable($collection->getStoreId())],
69+
$joinCond,
70+
[]
71+
);
72+
}
73+
$positions[] = $connection->getIfNullSql($table . '.position', '~0');
74+
}
75+
76+
// Ensures that position attribute is registered in _joinFields
77+
// in order for sort by position to use cat_index_position field
78+
$collection->addExpressionAttributeToSelect('position', 'cat_index_position', 'entity_id');
79+
80+
$columns = $select->getPart(Select::COLUMNS);
81+
$preparedColumns = [];
82+
$columnFound = false;
83+
$minPos = $connection->getLeastSql($positions);
84+
85+
// Remove columns with alias cat_index_position
86+
// Find column entry that was added in addExpressionAttributeToSelect. Expected [, cat_index_position, position]
87+
// and replace it with [, LEAST(...), cat_index_position]
88+
foreach ($columns as $columnEntry) {
89+
if ($columnEntry[2] !== 'cat_index_position') {
90+
if ($columnEntry[2] === 'position' && $columnEntry[1] === 'cat_index_position') {
91+
if (!$columnFound) {
92+
$columnEntry[1] = $minPos;
93+
$columnEntry[2] = 'cat_index_position';
94+
$columnFound = true;
95+
} else {
96+
continue;
97+
}
98+
}
99+
$preparedColumns[] = $columnEntry;
100+
}
101+
}
102+
103+
$select->setPart(Select::COLUMNS, $preparedColumns);
104+
105+
if (!$columnFound) {
106+
$select->columns(['cat_index_position' => $minPos]);
107+
}
108+
}
109+
}

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
use Magento\Catalog\Model\CategoryFactory;
1111
use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel;
1212
use Magento\Catalog\Model\ResourceModel\Product\Collection;
13-
use Magento\CatalogGraphQl\Model\ResourceModel\Product\Collection as GraphQLProductsCollection;
13+
use Magento\Catalog\Model\ResourceModel\Product\Collection\JoinMinimalPosition;
1414
use Magento\Framework\Api\Filter;
1515
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\FilterProcessor\CustomFilterInterface;
16+
use Magento\Framework\App\ObjectManager;
1617
use Magento\Framework\Data\Collection\AbstractDb;
1718

1819
/**
@@ -60,16 +61,25 @@ class CategoryFilter implements CustomFilterInterface
6061
*/
6162
private $categoryResourceModel;
6263

64+
/**
65+
* @var JoinMinimalPosition
66+
*/
67+
private $joinMinimalPosition;
68+
6369
/**
6470
* @param CategoryFactory $categoryFactory
6571
* @param CategoryResourceModel $categoryResourceModel
72+
* @param JoinMinimalPosition|null $joinMinimalPosition
6673
*/
6774
public function __construct(
6875
CategoryFactory $categoryFactory,
69-
CategoryResourceModel $categoryResourceModel
76+
CategoryResourceModel $categoryResourceModel,
77+
?JoinMinimalPosition $joinMinimalPosition = null
7078
) {
7179
$this->categoryFactory = $categoryFactory;
7280
$this->categoryResourceModel = $categoryResourceModel;
81+
$this->joinMinimalPosition = $joinMinimalPosition
82+
?? ObjectManager::getInstance()->get(JoinMinimalPosition::class);
7383
}
7484

7585
/**
@@ -92,8 +102,8 @@ public function apply(Filter $filter, AbstractDb $collection)
92102
$category = $this->getCategory((int) reset($ids));
93103
/** This filter adds ability to sort by position*/
94104
$collection->addCategoryFilter($category);
95-
} elseif ($conditionType === self::CONDITION_TYPE_IN && $collection instanceof GraphQLProductsCollection) {
96-
$collection->joinMinimalPosition($ids);
105+
} elseif ($conditionType === self::CONDITION_TYPE_IN) {
106+
$this->joinMinimalPosition->execute($collection, $ids);
97107
}
98108
/** Prevent filtering duplication as the filter should be already applied to the search result */
99109
if (!$collection->getFlag('search_resut_applied')) {

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

Lines changed: 0 additions & 215 deletions
This file was deleted.

0 commit comments

Comments
 (0)