Skip to content

Commit d4d381b

Browse files
committed
Merge branch 'ACP2E-1992' of https://github.com/magento-l3/magento2-page-builder into L3-PR-2023-09-13
2 parents 96f1d71 + f488dc3 commit d4d381b

File tree

4 files changed

+225
-6
lines changed

4 files changed

+225
-6
lines changed

app/code/Magento/PageBuilder/Model/Catalog/ProductTotals.php

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
use Magento\Catalog\Model\ResourceModel\Product\Collection;
1515
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
1616
use Magento\CatalogWidget\Model\Rule;
17+
use Magento\Framework\App\ObjectManager;
18+
use Magento\Framework\App\ResourceConnection;
19+
use Magento\Framework\EntityManager\MetadataPool;
1720
use Magento\Framework\Exception\LocalizedException;
1821
use Magento\Framework\Exception\NoSuchEntityException;
1922
use Magento\Rule\Model\Condition\Combine;
@@ -53,25 +56,41 @@ class ProductTotals
5356
*/
5457
private $categoryRepository;
5558

59+
/**
60+
* @var MetadataPool
61+
*/
62+
private MetadataPool $metadataPool;
63+
64+
/**
65+
* @var ResourceConnection
66+
*/
67+
private ResourceConnection $resource;
68+
5669
/**
5770
* @param CollectionFactory $productCollectionFactory
5871
* @param Builder $sqlBuilder
5972
* @param Rule $rule
6073
* @param Conditions $conditionsHelper
6174
* @param CategoryRepositoryInterface $categoryRepository
75+
* @param MetadataPool|null $metadataPool
76+
* @param ResourceConnection|null $resource
6277
*/
6378
public function __construct(
6479
CollectionFactory $productCollectionFactory,
6580
Builder $sqlBuilder,
6681
Rule $rule,
6782
Conditions $conditionsHelper,
68-
CategoryRepositoryInterface $categoryRepository
83+
CategoryRepositoryInterface $categoryRepository,
84+
?MetadataPool $metadataPool = null,
85+
?ResourceConnection $resource = null
6986
) {
7087
$this->productCollectionFactory = $productCollectionFactory;
7188
$this->sqlBuilder = $sqlBuilder;
7289
$this->rule = $rule;
7390
$this->conditionsHelper = $conditionsHelper;
7491
$this->categoryRepository = $categoryRepository;
92+
$this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class);
93+
$this->resource = $resource ?: ObjectManager::getInstance()->get(ResourceConnection::class);
7594
}
7695

7796
/**
@@ -159,37 +178,85 @@ private function getProductCollection(string $conditions, bool $usePriceIndex =
159178
return $collection;
160179
}
161180

181+
/**
182+
* Get parent products that don't have stand-alone properties (e.g. price or special price)
183+
*
184+
* @param Collection $collection
185+
* @return Collection|null
186+
* @throws \Exception
187+
*/
188+
private function getParentProductsCollection(Collection $collection): ?Collection
189+
{
190+
$parentProducts = $this->productCollectionFactory->create();
191+
$linkField = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
192+
->getLinkField();
193+
$connection = $this->resource->getConnection();
194+
$productIds = $connection->fetchCol(
195+
$connection
196+
->select()
197+
->from(['e' => $collection->getTable('catalog_product_entity')], ['link_table.parent_id'])
198+
->joinInner(
199+
['link_table' => $collection->getTable('catalog_product_super_link')],
200+
'link_table.product_id = e.' . $linkField,
201+
[]
202+
)
203+
->where('link_table.product_id IN (?)', $collection->getAllIds())
204+
);
205+
if ($productIds) {
206+
$parentProducts->addIdFilter($productIds);
207+
return $parentProducts;
208+
}
209+
210+
return null;
211+
}
212+
162213
/**
163214
* Retrieve count of all enabled products
164215
*
165216
* @param string $conditions
166217
* @return int number of enabled products
218+
* @throws LocalizedException
219+
* @throws \Exception
167220
*/
168221
private function getEnabledCount(string $conditions): int
169222
{
170223
$collection = $this->getProductCollection($conditions, true);
171224
$collection->addAttributeToFilter('status', Status::STATUS_ENABLED);
172-
return $collection->getSize();
225+
$count = $collection->getSize();
226+
if ($collection->getSize() && $parentProducts = $this->getParentProductsCollection($collection)) {
227+
$parentProducts->addAttributeToFilter('status', Status::STATUS_ENABLED);
228+
$count += $parentProducts->getSize();
229+
}
230+
231+
return $count;
173232
}
174233

175234
/**
176235
* Retrieve count of all disabled products
177236
*
178237
* @param string $conditions
179238
* @return int number of disabled products
239+
* @throws \Exception
180240
*/
181241
private function getDisabledCount(string $conditions): int
182242
{
183243
$collection = $this->getProductCollection($conditions, false);
184244
$collection->addAttributeToFilter('status', Status::STATUS_DISABLED);
185-
return $collection->getSize();
245+
$count = $collection->getSize();
246+
if ($count && $parentProducts = $this->getParentProductsCollection($collection)) {
247+
$parentProducts->addAttributeToFilter('status', Status::STATUS_DISABLED);
248+
$count += $parentProducts->getSize();
249+
}
250+
251+
return $count;
186252
}
187253

188254
/**
189255
* Retrieve count of all not visible individually products
190256
*
191257
* @param string $conditions
192258
* @return int number of products not visible individually
259+
* @throws \Exception
193260
*/
194261
private function getNotVisibleCount(string $conditions): int
195262
{
@@ -202,7 +269,20 @@ private function getNotVisibleCount(string $conditions): int
202269
Visibility::VISIBILITY_IN_SEARCH
203270
]
204271
);
205-
return $collection->getSize();
272+
$count = $collection->getSize();
273+
if ($count && $parentProducts = $this->getParentProductsCollection($collection)) {
274+
$parentProducts->addAttributeToFilter('status', Status::STATUS_ENABLED);
275+
$parentProducts->addAttributeToFilter(
276+
'visibility',
277+
[
278+
Visibility::VISIBILITY_NOT_VISIBLE,
279+
Visibility::VISIBILITY_IN_SEARCH
280+
]
281+
);
282+
$count += $parentProducts->getSize();
283+
}
284+
285+
return $count;
206286
}
207287

208288
/**
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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\Test\Unit\Model\Catalog;
9+
10+
use Magento\Catalog\Api\CategoryRepositoryInterface;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
12+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
13+
use Magento\CatalogWidget\Model\Rule;
14+
use Magento\Framework\App\ResourceConnection;
15+
use Magento\Framework\DB\Adapter\AdapterInterface;
16+
use Magento\Framework\DB\Select;
17+
use Magento\Framework\EntityManager\EntityMetadataInterface;
18+
use Magento\Framework\EntityManager\MetadataPool;
19+
use Magento\PageBuilder\Model\Catalog\ProductTotals;
20+
use Magento\Rule\Model\Condition\Combine;
21+
use Magento\Rule\Model\Condition\Sql\Builder;
22+
use Magento\Widget\Helper\Conditions;
23+
use PHPUnit\Framework\MockObject\MockObject;
24+
use PHPUnit\Framework\TestCase;
25+
26+
/**
27+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
28+
*/
29+
class ProductTotalsTest extends TestCase
30+
{
31+
/**
32+
* @var CollectionFactory|MockObject
33+
*/
34+
private CollectionFactory $productCollectionFactory;
35+
36+
/**
37+
* @var Builder|MockObject
38+
*/
39+
private Builder $sqlBuilder;
40+
41+
/**
42+
* @var Rule|MockObject
43+
*/
44+
private Rule $rule;
45+
46+
/**
47+
* @var Conditions|MockObject
48+
*/
49+
private Conditions $conditionsHelper;
50+
51+
/**
52+
* @var CategoryRepositoryInterface|MockObject
53+
*/
54+
private CategoryRepositoryInterface $categoryRepository;
55+
56+
/**
57+
* @var MetadataPool|MockObject
58+
*/
59+
private MetadataPool $metadataPool;
60+
61+
/**
62+
* @var ResourceConnection|MockObject
63+
*/
64+
private ResourceConnection $resource;
65+
66+
/**
67+
* @var ProductTotals|MockObject
68+
*/
69+
private ProductTotals $productTotals;
70+
71+
/**
72+
* @inheritdoc
73+
*/
74+
protected function setUp(): void
75+
{
76+
$this->productCollectionFactory = $this->createMock(CollectionFactory::class);
77+
$this->sqlBuilder = $this->createMock(Builder::class);
78+
$this->rule = $this->createMock(Rule::class);
79+
$this->conditionsHelper = $this->createMock(Conditions::class);
80+
$this->categoryRepository = $this->createMock(CategoryRepositoryInterface::class);
81+
$this->metadataPool = $this->createMock(MetadataPool::class);
82+
$this->resource = $this->createMock(ResourceConnection::class);
83+
84+
$this->productTotals = new ProductTotals(
85+
$this->productCollectionFactory,
86+
$this->sqlBuilder,
87+
$this->rule,
88+
$this->conditionsHelper,
89+
$this->categoryRepository,
90+
$this->metadataPool,
91+
$this->resource
92+
);
93+
94+
parent::setUp();
95+
}
96+
97+
/**
98+
* @return void
99+
* @throws \Magento\Framework\Exception\LocalizedException
100+
* @throws \Zend_Db_Select_Exception
101+
*/
102+
public function testGetProductTotals(): void
103+
{
104+
$collection = $this->createMock(Collection::class);
105+
$collection->expects($this->exactly(3))->method('distinct');
106+
$collection->expects($this->any())->method('addAttributeToFilter');
107+
$collection->expects($this->exactly(3))->method('getAllIds');
108+
$collection->expects($this->any())->method('getSize')->willReturn(1);
109+
$select = $this->createMock(Select::class);
110+
$select->expects($this->any())->method('joinLeft')->willReturn($select);
111+
112+
$collection->expects($this->exactly(3))->method('getSelect')->willReturn($select);
113+
$this->productCollectionFactory->expects($this->any())
114+
->method('create')
115+
->willReturn($collection);
116+
117+
$entityMeta = $this->createMock(EntityMetadataInterface::class);
118+
$entityMeta->expects($this->exactly(3))->method('getLinkField')->willReturn('row_id');
119+
$this->metadataPool->expects($this->exactly(3))
120+
->method('getMetadata')
121+
->with(\Magento\Catalog\Api\Data\ProductInterface::class)
122+
->willReturn($entityMeta);
123+
124+
$parentSelect = $this->createMock(Select::class);
125+
$parentSelect->expects($this->any())->method('from')->willReturn($parentSelect);
126+
$parentSelect->expects($this->any())->method('joinInner')->willReturn($parentSelect);
127+
$db = $this->createMock(AdapterInterface::class);
128+
$db->expects($this->exactly(3))->method('select')->willReturn($parentSelect);
129+
$db->expects($this->exactly(3))->method('fetchCol')->willReturn([1]);
130+
$this->resource->expects($this->exactly(3))->method('getConnection')->willReturn($db);
131+
132+
$this->conditionsHelper->expects($this->exactly(3))->method('decode')->willReturn([]);
133+
$this->rule->expects($this->exactly(3))->method('loadPost');
134+
$combine = $this->createMock(Combine::class);
135+
$this->rule->expects($this->exactly(3))->method('getConditions')->willReturn($combine);
136+
137+
$this->productTotals->getProductTotals('{conditions}');
138+
}
139+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
<arguments>
185185
<argument name="productCollectionFactory" xsi:type="object">pageBuilderProductCollectionFactory</argument>
186186
</arguments>
187-
<plugin name="pagebuilder_product_list" type="Magento\PageBuilder\Plugin\Catalog\Block\Product\ProductsListPlugin" />
187+
<plugin name="pagebuilder_product_list" type="Magento\PageBuilder\Plugin\Catalog\Block\Product\ProductsListPlugin" sortOrder="1"/>
188188
</type>
189189
<type name="Magento\Catalog\Helper\Output">
190190
<arguments>

app/code/Magento/PageBuilder/view/frontend/templates/catalog/product/widget/content/carousel.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use Magento\Framework\App\Action\Action;
1717
* @var \Magento\Framework\Escaper $escaper
1818
*/
1919
?>
20-
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())): ?>
20+
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->count())): ?>
2121
<?php
2222
$type = 'widget-product-carousel';
2323

0 commit comments

Comments
 (0)