Skip to content

Commit 3bb2d19

Browse files
committed
Merge branch 'MC-41478' of https://github.com/magento-l3/magento2-page-builder into PR-20210423
2 parents 98e7166 + 9274f0f commit 3bb2d19

File tree

4 files changed

+241
-1
lines changed

4 files changed

+241
-1
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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\PageBuilder\Model\Catalog\Sorting\Category;
9+
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
11+
use Magento\Framework\DB\Select;
12+
use Magento\Framework\Phrase;
13+
use Magento\PageBuilder\Model\Catalog\Sorting\OptionInterface;
14+
use Magento\Store\Model\Store;
15+
16+
/**
17+
* Sort catalog products by their positions in the category
18+
*/
19+
class Position implements OptionInterface
20+
{
21+
/**
22+
* @var string
23+
*/
24+
private $label;
25+
26+
/**
27+
* @var string
28+
*/
29+
private $sortDirection;
30+
31+
/**
32+
* @var string
33+
*/
34+
private $secondarySortDirection;
35+
36+
/**
37+
* @param string $label
38+
* @param string $sortDirection
39+
* @param string|null $secondarySortDirection
40+
*/
41+
public function __construct(
42+
string $label,
43+
string $sortDirection = Select::SQL_ASC,
44+
?string $secondarySortDirection = null
45+
) {
46+
$this->label = $label;
47+
$this->sortDirection = $sortDirection;
48+
$this->secondarySortDirection = $secondarySortDirection ?? $sortDirection;
49+
}
50+
51+
/**
52+
* @inheritDoc
53+
*/
54+
public function sort(Collection $collection): Collection
55+
{
56+
$collection->getSelect()->reset(Select::ORDER);
57+
$filters = $collection->getLimitationFilters();
58+
if ($collection->getStoreId() === Store::DEFAULT_STORE_ID && isset($filters['category_id'])) {
59+
$collection->getSelect()->order("cat_index_position $this->sortDirection");
60+
} else {
61+
$collection->addAttributeToSort('position', $this->sortDirection);
62+
}
63+
if ($this->secondarySortDirection) {
64+
$collection->addAttributeToSort('entity_id', $this->secondarySortDirection);
65+
}
66+
return $collection;
67+
}
68+
69+
/**
70+
* @inheritdoc
71+
*/
72+
public function getLabel(): Phrase
73+
{
74+
return __($this->label);
75+
}
76+
}

app/code/Magento/PageBuilder/Ui/DataProvider/Product/ProductCollection.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,34 @@ protected function _productLimitationJoinPrice()
3838
$this->_productLimitationFilters->setUsePriceIndex($this->getStoreId() !== Store::DEFAULT_STORE_ID);
3939
return $this->_productLimitationPrice(false);
4040
}
41+
42+
/**
43+
* @inheritdoc
44+
*/
45+
protected function _applyZeroStoreProductLimitations()
46+
{
47+
$conditions = [
48+
'cat_pro.product_id=e.entity_id',
49+
$this->getConnection()->quoteInto(
50+
'cat_pro.category_id = ?',
51+
$this->_productLimitationFilters['category_id'],
52+
\Zend_Db::INT_TYPE
53+
),
54+
];
55+
$joinCond = join(' AND ', $conditions);
56+
$fromPart = $this->getSelect()->getPart(\Magento\Framework\DB\Select::FROM);
57+
if (isset($fromPart['cat_pro'])) {
58+
$fromPart['cat_pro']['joinCondition'] = $joinCond;
59+
$this->getSelect()->setPart(\Magento\Framework\DB\Select::FROM, $fromPart);
60+
} else {
61+
$this->getSelect()->joinLeft(
62+
['cat_pro' => $this->getTable('catalog_category_product')],
63+
$joinCond,
64+
['cat_index_position' => $this->getConnection()->getIfNullSql('position', '~0')]
65+
);
66+
}
67+
$this->_joinFields['position'] = ['table' => 'cat_pro', 'field' => 'position'];
68+
69+
return $this;
70+
}
4171
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@
265265
<argument name="sortDirection" xsi:type="const">\Magento\Framework\DB\Select::SQL_ASC</argument>
266266
</arguments>
267267
</virtualType>
268+
<!-- @deprecated no longer used -->
268269
<virtualType name="Magento\PageBuilder\Model\Catalog\Sorting\Position" type="Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption">
269270
<arguments>
270271
<argument name="label" xsi:type="string">Position</argument>
@@ -290,10 +291,17 @@
290291
<argument name="sortDirection" xsi:type="const">\Magento\Framework\DB\Select::SQL_ASC</argument>
291292
</arguments>
292293
</virtualType>
294+
<virtualType name="Magento\PageBuilder\Model\Catalog\Sorting\Position\Ascending" type="Magento\PageBuilder\Model\Catalog\Sorting\Category\Position">
295+
<arguments>
296+
<argument name="label" xsi:type="string">Position</argument>
297+
<argument name="sortDirection" xsi:type="const">\Magento\Framework\DB\Select::SQL_ASC</argument>
298+
<argument name="secondarySortDirection" xsi:type="const">\Magento\Framework\DB\Select::SQL_DESC</argument>
299+
</arguments>
300+
</virtualType>
293301
<type name="Magento\PageBuilder\Model\Catalog\Sorting">
294302
<arguments>
295303
<argument name="sortClasses" xsi:type="array">
296-
<item name="position" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Position</item>
304+
<item name="position" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Position\Ascending</item>
297305
<item name="position_by_sku" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\PositionBySku</item>
298306
<item name="date_newest_top" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Date\NewestTop</item>
299307
<item name="date_oldest_top" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Date\OldestTop</item>

dev/tests/integration/testsuite/Magento/PageBuilder/CatalogWidget/Block/Product/ProductListTest.php

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77

88
namespace Magento\PageBuilder\CatalogWidget\Block\Product;
99

10+
use Magento\Catalog\Api\Data\CategoryInterface;
1011
use Magento\CatalogWidget\Block\Product\ProductsList;
1112
use Magento\Store\Model\Store;
1213
use Magento\TestFramework\Helper\Bootstrap;
1314
use PHPUnit\Framework\TestCase;
1415

1516
/**
1617
* Test catalog products list widget block with page builder
18+
*
19+
* @magentoAppArea adminhtml
20+
* @magentoAppIsolation enabled
1721
*/
1822
class ProductListTest extends TestCase
1923
{
@@ -106,6 +110,45 @@ public function testProductWithDifferentPriceOnEachWebsite(): void
106110
$this->assertEquals([$sku], $productCollection->getColumnValues('sku'));
107111
}
108112

113+
/**
114+
* Test that filtering by category works correctly together with sorting
115+
*
116+
* @magentoDataFixture Magento/Catalog/_files/multiple_products.php
117+
* @magentoDataFixture Magento/Catalog/_files/products_list.php
118+
* @magentoDataFixture Magento/Catalog/_files/categories_no_products.php
119+
* @param array $categories
120+
* @param int $categoryId
121+
* @param string $order
122+
* @param array $skus
123+
* @dataProvider categoryFilterAndSortDataProvider
124+
*/
125+
public function testCategoryFilterAndSort(array $categories, int $categoryId, string $order, array $skus): void
126+
{
127+
$objectManager = Bootstrap::getObjectManager();
128+
foreach ($categories as $id => $data) {
129+
/** @var CategoryInterface $categoryAnchor */
130+
$category = $objectManager->create(CategoryInterface::class);
131+
$category->load($id);
132+
$category->setIsAnchor($data['is_anchor']);
133+
$category->setPostedProducts($data['products']);
134+
$category->save();
135+
}
136+
137+
$encodedConditions = '^[`1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Combine`,
138+
`aggregator`:`all`,`value`:`1`,`new_child`:``^],
139+
`1--1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Product`,
140+
`attribute`:`category_ids`,`operator`:`==`,`value`:`' . $categoryId . '`^]^]';
141+
142+
$this->block->setData('sort_order', $order);
143+
$this->block->setData('condition_option', 'category_ids');
144+
$this->block->setData('condition_option_value', $categoryId);
145+
$this->block->setData('conditions_encoded', $encodedConditions);
146+
$this->block->setStoreId(Store::DEFAULT_STORE_ID);
147+
$productCollection = $this->block->createCollection();
148+
$productCollection->load();
149+
$this->assertEquals($skus, $productCollection->getColumnValues('sku'));
150+
}
151+
109152
/**
110153
* @return array
111154
*/
@@ -164,4 +207,87 @@ public function priceSortDataProvider(): array
164207
],
165208
];
166209
}
210+
211+
/**
212+
* @return array
213+
*/
214+
public function categoryFilterAndSortDataProvider(): array
215+
{
216+
$categories = [
217+
//Category 1
218+
3 => [
219+
'is_anchor' => true,
220+
'products' => [
221+
//simple-249
222+
153 => 0,
223+
//simple-156
224+
156 => 1,
225+
]
226+
],
227+
//Category 1.1
228+
4 => [
229+
'is_anchor' => false,
230+
'products' => [
231+
//simple-156
232+
156 => 0,
233+
//simple2
234+
11 => 1,
235+
//simple-249
236+
153 => 2,
237+
]
238+
],
239+
//Category 1.1.1
240+
5 => [
241+
'is_anchor' => false,
242+
'products' => [
243+
//simple1
244+
10 => 1,
245+
]
246+
]
247+
];
248+
return [
249+
[
250+
$categories,
251+
3,
252+
'position',
253+
[
254+
'simple-249',
255+
'simple-156',
256+
'simple2',
257+
'simple1',
258+
]
259+
],
260+
[
261+
$categories,
262+
4,
263+
'position',
264+
[
265+
'simple-156',
266+
'simple2',
267+
'simple-249',
268+
]
269+
],
270+
[
271+
$categories,
272+
3,
273+
'date_newest_top',
274+
[
275+
'simple-156',
276+
'simple-249',
277+
'simple2',
278+
'simple1',
279+
]
280+
],
281+
[
282+
$categories,
283+
4,
284+
'date_newest_top',
285+
[
286+
'simple-156',
287+
'simple-249',
288+
'simple2',
289+
]
290+
]
291+
];
292+
}
167293
}

0 commit comments

Comments
 (0)