Skip to content

Commit 1983122

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into MCP-826
2 parents dba4d1a + 73714d5 commit 1983122

File tree

20 files changed

+539
-67
lines changed

20 files changed

+539
-67
lines changed

app/bootstrap.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
#ini_set('display_errors', 1);
1515

1616
/* PHP version validation */
17-
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70300) {
17+
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70400) {
1818
if (PHP_SAPI == 'cli') {
19-
echo 'Magento supports PHP 7.3.0 or later. ' .
19+
echo 'Magento supports PHP 7.4.0 or later. ' .
2020
'Please read https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements-tech.html';
2121
} else {
2222
echo <<<HTML
2323
<div style="font:12px/1.35em arial, helvetica, sans-serif;">
24-
<p>Magento supports PHP 7.3.0 or later. Please read
24+
<p>Magento supports PHP 7.4.0 or later. Please read
2525
<a target="_blank" href="https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements-tech.html">
2626
Magento System Requirements</a>.
2727
</div>

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
/**
3737
* @inheritdoc
3838
*
39+
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
3940
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
4041
* @SuppressWarnings(PHPMD.TooManyFields)
4142
*/
@@ -280,7 +281,7 @@ public function __construct(
280281
*/
281282
public function get($sku, $editMode = false, $storeId = null, $forceReload = false)
282283
{
283-
$cacheKey = $this->getCacheKey([$editMode, $storeId]);
284+
$cacheKey = $this->getCacheKey([$editMode, $storeId === null ? $storeId : (int) $storeId]);
284285
$cachedProduct = $this->getProductFromLocalCache($sku, $cacheKey);
285286
if ($cachedProduct === null || $forceReload) {
286287
$product = $this->productFactory->create();
@@ -295,7 +296,7 @@ public function get($sku, $editMode = false, $storeId = null, $forceReload = fal
295296
$product->setData('_edit_mode', true);
296297
}
297298
if ($storeId !== null) {
298-
$product->setData('store_id', $storeId);
299+
$product->setData('store_id', (int) $storeId);
299300
}
300301
$product->load($productId);
301302
$this->cacheProduct($cacheKey, $product);
@@ -522,6 +523,7 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
522523
* @inheritdoc
523524
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
524525
* @SuppressWarnings(PHPMD.NPathComplexity)
526+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
525527
*/
526528
public function save(ProductInterface $product, $saveOptions = false)
527529
{

app/code/Magento/CatalogInventoryGraphQl/Model/Resolver/OnlyXLeftInStockResolver.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,8 @@ private function getOnlyXLeftQty(ProductInterface $product): ?float
8686

8787
$stockLeft = $stockCurrentQty - $stockItem->getMinQty();
8888

89-
$thresholdQty = (float)$this->scopeConfig->getValue(
90-
Configuration::XML_PATH_STOCK_THRESHOLD_QTY,
91-
ScopeInterface::SCOPE_STORE
92-
);
93-
94-
if ($stockCurrentQty > 0 && $stockLeft <= $thresholdQty) {
95-
return (float)$stockLeft;
89+
if ($stockCurrentQty >= 0 && $stockLeft <= $thresholdQty) {
90+
return (float)$stockCurrentQty;
9691
}
9792

9893
return null;
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
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\CatalogInventoryGraphQl\Test\Unit\Model\Resolver;
9+
10+
use PHPUnit\Framework\TestCase;
11+
use Magento\CatalogInventoryGraphQl\Model\Resolver\OnlyXLeftInStockResolver;
12+
use Magento\Framework\App\Config\ScopeConfigInterface;
13+
use Magento\Framework\GraphQl\Config\Element\Field;
14+
use Magento\GraphQl\Model\Query\ContextInterface;
15+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
16+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17+
use Magento\CatalogInventory\Api\StockRegistryInterface;
18+
use Magento\Catalog\Model\Product;
19+
use Magento\Store\Api\Data\StoreInterface;
20+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
21+
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
22+
23+
/**
24+
* Test class for \Magento\CatalogInventoryGraphQl\Model\Resolver\OnlyXLeftInStockResolver
25+
*/
26+
class OnlyXLeftInStockResolverTest extends TestCase
27+
{
28+
/**
29+
* Object Manager Instance
30+
*
31+
* @var ObjectManager
32+
*/
33+
private $objectManager;
34+
35+
/**
36+
* Testable Object
37+
*
38+
* @var RevokeCustomerToken
39+
*/
40+
private $resolver;
41+
42+
/**
43+
* @var ContextInterface|MockObject
44+
*/
45+
private $contextMock;
46+
47+
/**
48+
* @var Field|MockObject
49+
*/
50+
private $fieldMock;
51+
52+
/**
53+
* @var ResolveInfo|MockObject
54+
*/
55+
private $resolveInfoMock;
56+
57+
/**
58+
* @var ScopeConfigInterface|MockObject
59+
*/
60+
private $scopeConfigMock;
61+
62+
/**
63+
* @var StockRegistryInterface|MockObject
64+
*/
65+
private $stockRegistryMock;
66+
67+
/**
68+
* @var Product|MockObject
69+
*/
70+
private $productModelMock;
71+
72+
/**
73+
* @var StoreInterface|MockObject
74+
*/
75+
private $storeMock;
76+
77+
/**
78+
* @var StockItemInterface|MockObject
79+
*/
80+
private $stockItemMock;
81+
82+
/**
83+
* @var StockStatusInterface|MockObject
84+
*/
85+
private $stockStatusMock;
86+
87+
/**
88+
* @inheritdoc
89+
*/
90+
91+
protected function setUp(): void
92+
{
93+
$this->objectManager = new ObjectManager($this);
94+
95+
$this->contextMock = $this->getMockBuilder(ContextInterface::class)
96+
->disableOriginalConstructor()
97+
->getMockForAbstractClass();
98+
99+
$this->fieldMock = $this->getMockBuilder(Field::class)
100+
->disableOriginalConstructor()
101+
->getMock();
102+
103+
$this->resolveInfoMock = $this->getMockBuilder(ResolveInfo::class)
104+
->disableOriginalConstructor()
105+
->getMock();
106+
107+
$this->productModelMock = $this->getMockBuilder(Product::class)
108+
->disableOriginalConstructor()
109+
->getMock();
110+
111+
$this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class)->getMock();
112+
$this->stockRegistryMock = $this->getMockBuilder(StockRegistryInterface::class)->getMock();
113+
$this->storeMock = $this->getMockBuilder(StoreInterface::class)->getMock();
114+
$this->stockItemMock = $this->getMockBuilder(StockItemInterface::class)->getMock();
115+
$this->stockStatusMock = $this->getMockBuilder(StockStatusInterface::class)->getMock();
116+
$this->productModelMock->expects($this->any())->method('getId')
117+
->willReturn(1);
118+
$this->productModelMock->expects($this->once())->method('getStore')
119+
->willReturn($this->storeMock);
120+
$this->stockRegistryMock->expects($this->once())->method('getStockStatus')
121+
->willReturn($this->stockStatusMock);
122+
$this->storeMock->expects($this->once())->method('getWebsiteId')->willReturn(1);
123+
124+
$this->resolver = $this->objectManager->getObject(
125+
OnlyXLeftInStockResolver::class,
126+
[
127+
'scopeConfig' => $this->scopeConfigMock,
128+
'stockRegistry' => $this->stockRegistryMock
129+
]
130+
);
131+
}
132+
133+
public function testResolve()
134+
{
135+
$stockCurrentQty = 3;
136+
$minQty = 2;
137+
$thresholdQty = 1;
138+
139+
$this->stockItemMock->expects($this->once())->method('getMinQty')
140+
->willReturn($minQty);
141+
$this->stockStatusMock->expects($this->once())->method('getQty')
142+
->willReturn($stockCurrentQty);
143+
$this->stockRegistryMock->expects($this->once())->method('getStockItem')
144+
->willReturn($this->stockItemMock);
145+
$this->scopeConfigMock->method('getValue')->willReturn($thresholdQty);
146+
147+
$this->assertEquals(
148+
$stockCurrentQty,
149+
$this->resolver->resolve(
150+
$this->fieldMock,
151+
$this->contextMock,
152+
$this->resolveInfoMock,
153+
['model' => $this->productModelMock]
154+
)
155+
);
156+
}
157+
158+
public function testResolveOutStock()
159+
{
160+
$stockCurrentQty = 0;
161+
$minQty = 2;
162+
$thresholdQty = 1;
163+
$this->stockItemMock->expects($this->once())->method('getMinQty')
164+
->willReturn($minQty);
165+
$this->stockStatusMock->expects($this->once())->method('getQty')
166+
->willReturn($stockCurrentQty);
167+
$this->stockRegistryMock->expects($this->once())->method('getStockItem')
168+
->willReturn($this->stockItemMock);
169+
$this->scopeConfigMock->method('getValue')->willReturn($thresholdQty);
170+
171+
$this->assertEquals(
172+
0,
173+
$this->resolver->resolve(
174+
$this->fieldMock,
175+
$this->contextMock,
176+
$this->resolveInfoMock,
177+
['model' => $this->productModelMock]
178+
)
179+
);
180+
}
181+
182+
public function testResolveNoThresholdQty()
183+
{
184+
$stockCurrentQty = 3;
185+
$minQty = 2;
186+
$thresholdQty = null;
187+
$this->stockItemMock->expects($this->once())->method('getMinQty')
188+
->willReturn($minQty);
189+
$this->stockStatusMock->expects($this->once())->method('getQty')
190+
->willReturn($stockCurrentQty);
191+
$this->stockRegistryMock->expects($this->once())->method('getStockItem')
192+
->willReturn($this->stockItemMock);
193+
$this->scopeConfigMock->method('getValue')->willReturn($thresholdQty);
194+
195+
$this->assertEquals(
196+
null,
197+
$this->resolver->resolve(
198+
$this->fieldMock,
199+
$this->contextMock,
200+
$this->resolveInfoMock,
201+
['model' => $this->productModelMock]
202+
)
203+
);
204+
}
205+
}

app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ public function add($entityType, $attributeCode, $option)
6060
{
6161
$attribute = $this->loadAttribute($entityType, (string)$attributeCode);
6262

63-
$label = trim($option->getLabel() ?: '');
64-
if (empty($label)) {
63+
$label = trim((string)$option->getLabel());
64+
if ($label === '') {
6565
throw new InputException(__('The attribute option label is empty. Enter the value and try again.'));
6666
}
6767

@@ -93,8 +93,8 @@ public function update(
9393
if (empty($optionId)) {
9494
throw new InputException(__('The option id is empty. Enter the value and try again.'));
9595
}
96-
$label = trim($option->getLabel() ?: '');
97-
if (empty($label)) {
96+
$label = trim((string)$option->getLabel());
97+
if ($label === '') {
9898
throw new InputException(__('The attribute option label is empty. Enter the value and try again.'));
9999
}
100100
if ($attribute->getSource()->getOptionText($optionId) === false) {

0 commit comments

Comments
 (0)