Skip to content

Commit 7a02116

Browse files
committed
magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes"
- allow "out of stock" items to be used for price determination of configurable product ONLY in case all child products are "out of stock". (cherry picked from commit 80f6a36) magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes" - add strict types. (cherry picked from commit b786871) magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes" - refactor variable names. (cherry picked from commit d009296) magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes" - add blank space. (cherry picked from commit 0b19e04) magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes" - remove unneeded usage of the variable. (cherry picked from commit 207e2e1) magento#16069: Configurable product price is not displayed if all children are out of stock and even if Display Out of Stock Products is set to "yes" (cherry picked from commit f4ec67e) magento#16069: Configurable product price is not displayed if all children are out of stock - change request magento#16069: Configurable product price is not displayed if all children are out of stock - change request magento#16069: Configurable product price is not displayed if all children are out of stock - change request magento#16069: Configurable product price is not displayed if all children are out of stock - change request
1 parent 287a5dc commit 7a02116

File tree

13 files changed

+717
-4
lines changed

13 files changed

+717
-4
lines changed

app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Catalog\Pricing\Render;
89

@@ -64,7 +65,9 @@ public function __construct(
6465
*/
6566
protected function _toHtml()
6667
{
67-
if (!$this->salableResolver->isSalable($this->getSaleableItem())) {
68+
if ($this->isApplySalableCheck($this->getSaleableItem()) &&
69+
!$this->salableResolver->isSalable($this->getSaleableItem())
70+
) {
6871
return '';
6972
}
7073

@@ -86,6 +89,16 @@ protected function _toHtml()
8689
return $this->wrapResult($result);
8790
}
8891

92+
/**
93+
* @param SaleableInterface $salableItem
94+
* @return bool
95+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
96+
*/
97+
protected function isApplySalableCheck(SaleableInterface $salableItem): bool
98+
{
99+
return true;
100+
}
101+
89102
/**
90103
* Check is MSRP applicable for the current product.
91104
*

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/LinkedProductSelectBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
*
1414
* Extends functionality of the linked product select builder to allow perform
1515
* some additional processing of built Select objects.
16+
*
17+
* @deprecated
18+
* @see \Magento\ConfigurableProduct\Model\ResourceModel\Product\LinkedSelectByParent\Builder
1619
*/
1720
class LinkedProductSelectBuilder implements LinkedProductSelectBuilderInterface
1821
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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\ConfigurableProduct\Model\ResourceModel\Product\LinkedSelectByParent;
9+
10+
use Magento\Framework\DB\Select;
11+
12+
/**
13+
* Interface BaseSelectProcessorInterface
14+
*/
15+
interface BaseSelectProcessorInterface
16+
{
17+
/**
18+
* Product table alias
19+
*/
20+
const PRODUCT_TABLE_ALIAS = 'child';
21+
22+
/**
23+
* @param Select $select
24+
* @param int $productId
25+
* @return Select
26+
*/
27+
public function process(Select $select, int $productId): Select;
28+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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\ConfigurableProduct\Model\ResourceModel\Product\LinkedSelectByParent;
9+
10+
use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface;
11+
12+
/**
13+
* A decorator for a linked product select builder by parent product.
14+
*
15+
* Extends functionality of the linked product select builder to allow perform
16+
* some additional processing of built Select objects.
17+
*/
18+
class Builder implements LinkedProductSelectBuilderInterface
19+
{
20+
/**
21+
* @var BaseSelectProcessorInterface
22+
*/
23+
private $baseSelectProcessor;
24+
25+
/**
26+
* @var LinkedProductSelectBuilderInterface
27+
*/
28+
private $linkedProductSelectBuilder;
29+
30+
/**
31+
* @param BaseSelectProcessorInterface $baseSelectProcessor
32+
* @param LinkedProductSelectBuilderInterface $linkedProductSelectBuilder
33+
*/
34+
public function __construct(
35+
BaseSelectProcessorInterface $baseSelectProcessor,
36+
LinkedProductSelectBuilderInterface $linkedProductSelectBuilder
37+
) {
38+
$this->baseSelectProcessor = $baseSelectProcessor;
39+
$this->linkedProductSelectBuilder = $linkedProductSelectBuilder;
40+
}
41+
42+
/**
43+
* @inheritdoc
44+
*/
45+
public function build($productId): array
46+
{
47+
$selects = $this->linkedProductSelectBuilder->build($productId);
48+
49+
foreach ($selects as $select) {
50+
$this->baseSelectProcessor->process($select, (int)$productId);
51+
}
52+
53+
return $selects;
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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\ConfigurableProduct\Model\ResourceModel\Product\LinkedSelectByParent;
9+
10+
use Magento\Framework\DB\Select;
11+
use Magento\Framework\App\ObjectManager;
12+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
13+
use Magento\CatalogInventory\Model\Stock\Status as StockStatus;
14+
use Magento\CatalogInventory\Model\ResourceModel\Stock\Status as StockStatusResource;
15+
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\StockStatusInterface
16+
as StockStatusConfigurableInterface;
17+
18+
/**
19+
* A Select object processor.
20+
*
21+
* Adds stock status limitations to a given Select object.
22+
*/
23+
class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface
24+
{
25+
/**
26+
* @var StockConfigurationInterface
27+
*/
28+
private $stockConfig;
29+
30+
/**
31+
* @var StockStatusResource
32+
*/
33+
private $stockStatusResource;
34+
35+
/**
36+
* @var StockStatusConfigurableInterface
37+
*/
38+
private $stockConfigurable;
39+
40+
/**
41+
* @param StockConfigurationInterface $stockConfig
42+
* @param StockStatusResource $stockStatusResource
43+
* @param StockStatusConfigurableInterface $stockConfigurable
44+
*/
45+
public function __construct(
46+
StockConfigurationInterface $stockConfig,
47+
StockStatusResource $stockStatusResource,
48+
StockStatusConfigurableInterface $stockConfigurable = null
49+
) {
50+
$this->stockConfig = $stockConfig;
51+
$this->stockStatusResource = $stockStatusResource;
52+
$this->stockConfigurable = $stockConfigurable ?:
53+
ObjectManager::getInstance()->get(StockStatusConfigurableInterface::class);
54+
}
55+
56+
/**
57+
* @inheritdoc
58+
*/
59+
public function process(Select $select, int $productId): Select
60+
{
61+
if ($this->stockConfig->isShowOutOfStock() &&
62+
!$this->isAllChildOutOfStock($productId)
63+
) {
64+
$select->joinInner(
65+
['stock' => $this->stockStatusResource->getMainTable()],
66+
sprintf(
67+
'stock.product_id = %s.entity_id',
68+
BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS
69+
),
70+
[]
71+
)->where(
72+
'stock.stock_status = ?',
73+
StockStatus::STATUS_IN_STOCK
74+
);
75+
}
76+
77+
return $select;
78+
}
79+
80+
/**
81+
* @param int $productId
82+
* @return bool
83+
* @throws \Exception
84+
*/
85+
private function isAllChildOutOfStock(int $productId): bool
86+
{
87+
return $this->stockConfigurable->isAllChildOutOfStock($productId);
88+
}
89+
}

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
* A Select object processor.
1616
*
1717
* Adds stock status limitations to a given Select object.
18+
*
19+
* @deprecated
20+
* @see \Magento\ConfigurableProduct\Model\ResourceModel\Product\LinkedSelectByParent\StockStatusBaseSelectProcessor
1821
*/
1922
class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface
2023
{
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable;
9+
10+
use Magento\Framework\EntityManager\MetadataPool;
11+
use Magento\Framework\App\ResourceConnection;
12+
use Magento\Catalog\Api\Data\ProductInterface;
13+
use Magento\CatalogInventory\Api\Data\StockStatusInterface as CatalogInventoryStockStatusInterface;
14+
use Magento\Framework\DB\Adapter\AdapterInterface;
15+
16+
class StockStatus implements StockStatusInterface
17+
{
18+
/**
19+
* @var ResourceConnection
20+
*/
21+
private $resource;
22+
23+
/**
24+
* @var MetadataPool
25+
*/
26+
private $metadataPool;
27+
28+
/**
29+
* StockStatus constructor.
30+
* @param ResourceConnection $resource
31+
* @param MetadataPool $metadataPool
32+
*/
33+
public function __construct(ResourceConnection $resource, MetadataPool $metadataPool)
34+
{
35+
$this->resource = $resource;
36+
$this->metadataPool = $metadataPool;
37+
}
38+
39+
/**
40+
* @var array
41+
*/
42+
private $allChildOutOfStockInfo = [];
43+
44+
/**
45+
* @inheritdoc
46+
*/
47+
public function isAllChildOutOfStock(int $productId): bool
48+
{
49+
if (isset($this->allChildOutOfStockInfo[$productId])) {
50+
return $this->allChildOutOfStockInfo[$productId];
51+
}
52+
53+
$statuses = $this->getAllChildStockInfo($productId);
54+
$isAllChildOutOfStock = true;
55+
foreach ($statuses as $status) {
56+
if ($status == CatalogInventoryStockStatusInterface::STATUS_IN_STOCK) {
57+
$isAllChildOutOfStock = false;
58+
break;
59+
}
60+
}
61+
62+
$this->allChildOutOfStockInfo[$productId] = $isAllChildOutOfStock;
63+
64+
return $this->allChildOutOfStockInfo[$productId];
65+
}
66+
67+
/**
68+
* @return AdapterInterface
69+
*/
70+
protected function getConnection(): AdapterInterface
71+
{
72+
return $this->resource->getConnection();
73+
}
74+
75+
/**
76+
* @param int $productId
77+
* @return array
78+
* @throws \Exception
79+
*/
80+
private function getAllChildStockInfo(int $productId): array
81+
{
82+
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
83+
$productTable = $this->resource->getTableName('catalog_product_entity');
84+
$productRelationTable = $this->resource->getTableName('catalog_product_relation');
85+
86+
$select = $this->getConnection()->select()
87+
->from(['parent' => $productTable], '', [])
88+
->joinInner(
89+
['link' => $productRelationTable],
90+
"link.parent_id = parent.$linkField",
91+
['id' => 'child_id']
92+
)->joinInner(
93+
['stock' => $this->resource->getTableName('cataloginventory_stock_status')],
94+
'stock.product_id = link.child_id',
95+
['stock_status']
96+
)->where(sprintf('parent.%s = ?', $linkField), $productId);
97+
98+
return $this->getConnection()->fetchPairs($select);
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable;
9+
10+
/**
11+
* Interface StockStatusInterface
12+
*/
13+
interface StockStatusInterface
14+
{
15+
/**
16+
* @param int $productId
17+
* @return bool
18+
* @throws \Exception
19+
*/
20+
public function isAllChildOutOfStock(int $productId): bool;
21+
}

0 commit comments

Comments
 (0)