Skip to content

Commit a61172a

Browse files
committed
Merge remote-tracking branch 'origin/MC-33107' into 2.4-develop-pr24
2 parents 593edf7 + 0ee0d92 commit a61172a

File tree

9 files changed

+135
-71
lines changed

9 files changed

+135
-71
lines changed

app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@
66

77
namespace Magento\CatalogInventory\Model\ResourceModel;
88

9+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
910
use Magento\CatalogInventory\Api\StockConfigurationInterface;
11+
use Magento\CatalogInventory\Model\Configuration;
12+
use Magento\Framework\App\Config\ScopeConfigInterface;
13+
use Magento\Framework\DB\Select;
14+
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
15+
use Magento\Framework\Model\ResourceModel\Db\Context;
16+
use Magento\Framework\Stdlib\DateTime\DateTime;
17+
use Magento\Store\Model\ScopeInterface;
1018
use Magento\Store\Model\StoreManagerInterface;
1119

1220
/**
1321
* Stock resource model
1422
*/
15-
class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb implements QtyCounterInterface
23+
class Stock extends AbstractDb implements QtyCounterInterface
1624
{
1725
/**
1826
* @var StockConfigurationInterface
@@ -64,12 +72,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
6472
/**
6573
* Core store config
6674
*
67-
* @var \Magento\Framework\App\Config\ScopeConfigInterface
75+
* @var ScopeConfigInterface
6876
*/
6977
protected $_scopeConfig;
7078

7179
/**
72-
* @var \Magento\Framework\Stdlib\DateTime\DateTime
80+
* @var DateTime
7381
*/
7482
protected $dateTime;
7583

@@ -80,17 +88,17 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
8088
protected $storeManager;
8189

8290
/**
83-
* @param \Magento\Framework\Model\ResourceModel\Db\Context $context
84-
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
85-
* @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime
91+
* @param Context $context
92+
* @param ScopeConfigInterface $scopeConfig
93+
* @param DateTime $dateTime
8694
* @param StockConfigurationInterface $stockConfiguration
8795
* @param StoreManagerInterface $storeManager
8896
* @param string $connectionName
8997
*/
9098
public function __construct(
91-
\Magento\Framework\Model\ResourceModel\Db\Context $context,
92-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
93-
\Magento\Framework\Stdlib\DateTime\DateTime $dateTime,
99+
Context $context,
100+
ScopeConfigInterface $scopeConfig,
101+
DateTime $dateTime,
94102
StockConfigurationInterface $stockConfiguration,
95103
StoreManagerInterface $storeManager,
96104
$connectionName = null
@@ -125,9 +133,18 @@ public function lockProductsStock(array $productIds, $websiteId)
125133
return [];
126134
}
127135
$itemTable = $this->getTable('cataloginventory_stock_item');
128-
$select = $this->getConnection()->select()->from(['si' => $itemTable])
136+
137+
//get indexed entries for row level lock instead of table lock
138+
$itemIds = [];
139+
$preSelect = $this->getConnection()->select()->from($itemTable, 'item_id')
129140
->where('website_id = ?', $websiteId)
130-
->where('product_id IN(?)', $productIds)
141+
->where('product_id IN(?)', $productIds);
142+
foreach ($this->getConnection()->query($preSelect)->fetchAll() as $item) {
143+
$itemIds[] = (int)$item['item_id'];
144+
}
145+
146+
$select = $this->getConnection()->select()->from(['si' => $itemTable])
147+
->where('item_id IN (?)', $itemIds)
131148
->forUpdate(true);
132149

133150
$productTable = $this->getTable('catalog_product_entity');
@@ -147,12 +164,12 @@ public function lockProductsStock(array $productIds, $websiteId)
147164
foreach ($this->getConnection()->fetchAll($selectProducts) as $p) {
148165
$items[$p['product_id']]['type_id'] = $p['type_id'];
149166
}
150-
167+
151168
return $items;
152169
}
153170

154171
/**
155-
* {@inheritdoc}
172+
* @inheritdoc
156173
*/
157174
public function correctItemsQty(array $items, $websiteId, $operator)
158175
{
@@ -185,16 +202,16 @@ protected function _initConfig()
185202
{
186203
if (!$this->_isConfig) {
187204
$configMap = [
188-
'_isConfigManageStock' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_MANAGE_STOCK,
189-
'_isConfigBackorders' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_BACKORDERS,
190-
'_configMinQty' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_MIN_QTY,
191-
'_configNotifyStockQty' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_NOTIFY_STOCK_QTY,
205+
'_isConfigManageStock' => Configuration::XML_PATH_MANAGE_STOCK,
206+
'_isConfigBackorders' => Configuration::XML_PATH_BACKORDERS,
207+
'_configMinQty' => Configuration::XML_PATH_MIN_QTY,
208+
'_configNotifyStockQty' => Configuration::XML_PATH_NOTIFY_STOCK_QTY,
192209
];
193210

194211
foreach ($configMap as $field => $const) {
195212
$this->{$field} = (int) $this->_scopeConfig->getValue(
196213
$const,
197-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
214+
ScopeInterface::SCOPE_STORE
198215
);
199216
}
200217

@@ -317,11 +334,11 @@ public function updateLowStockDate($website)
317334
/**
318335
* Add low stock filter to product collection
319336
*
320-
* @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
337+
* @param Collection $collection
321338
* @param array $fields
322339
* @return $this
323340
*/
324-
public function addLowStockFilter(\Magento\Catalog\Model\ResourceModel\Product\Collection $collection, $fields)
341+
public function addLowStockFilter(Collection $collection, $fields)
325342
{
326343
$this->_initConfig();
327344
$connection = $collection->getSelect()->getConnection();
@@ -344,14 +361,14 @@ public function addLowStockFilter(\Magento\Catalog\Model\ResourceModel\Product\C
344361

345362
$where = [];
346363
foreach ($conditions as $k => $part) {
347-
$where[$k] = join(' ' . \Magento\Framework\DB\Select::SQL_AND . ' ', $part);
364+
$where[$k] = join(' ' . Select::SQL_AND . ' ', $part);
348365
}
349366

350367
$where = $connection->prepareSqlCondition(
351368
'invtr.low_stock_date',
352369
['notnull' => true]
353-
) . ' ' . \Magento\Framework\DB\Select::SQL_AND . ' ((' . join(
354-
') ' . \Magento\Framework\DB\Select::SQL_OR . ' (',
370+
) . ' ' . Select::SQL_AND . ' ((' . join(
371+
') ' . Select::SQL_OR . ' (',
355372
$where
356373
) . '))';
357374

app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/StockTest.php

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,73 +7,78 @@
77

88
namespace Magento\CatalogInventory\Test\Unit\Model\ResourceModel;
99

10-
use Magento\Catalog\Model\ResourceModel\Product\Collection;
1110
use Magento\CatalogInventory\Model\Configuration as StockConfiguration;
1211
use Magento\CatalogInventory\Model\ResourceModel\Stock;
1312
use Magento\Framework\App\Config;
1413
use Magento\Framework\DB\Adapter\Pdo\Mysql;
14+
use Magento\Framework\DB\Select;
1515
use Magento\Framework\Model\ResourceModel\Db\Context;
1616
use Magento\Framework\Stdlib\DateTime\DateTime;
1717
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1818
use Magento\Store\Model\StoreManagerInterface;
19+
use PHPUnit\Framework\MockObject\MockObject;
20+
use PHPUnit\Framework\TestCase;
1921

2022
/**
2123
* Test for \Magento\CatalogInventory\Model\ResourceModel\Stock
2224
*/
23-
class StockTest extends \PHPUnit\Framework\TestCase
25+
class StockTest extends TestCase
2426
{
2527
const PRODUCT_TABLE = 'testProductTable';
2628
const ITEM_TABLE = 'testItemTableName';
2729

2830
/**
29-
* @var Stock|\PHPUnit_Framework_MockObject_MockObject
31+
* @var Stock|MockObject
3032
*/
3133
private $stock;
3234

3335
/**
34-
* @var Mysql|\PHPUnit_Framework_MockObject_MockObject
36+
* @var Mysql|MockObject
3537
*/
3638
private $connectionMock;
3739

3840
/**
39-
* @var Config|\PHPUnit_Framework_MockObject_MockObject
41+
* @var Config|MockObject
4042
*/
4143
private $scopeConfigMock;
4244

4345
/**
44-
* @var DateTime|\PHPUnit_Framework_MockObject_MockObject
46+
* @var DateTime|MockObject
4547
*/
4648
private $dateTimeMock;
4749

4850
/**
49-
* @var StockConfiguration|\PHPUnit_Framework_MockObject_MockObject
51+
* @var StockConfiguration|MockObject
5052
*/
5153
private $stockConfigurationMock;
5254

5355
/**
54-
* @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
56+
* @var StoreManagerInterface|MockObject
5557
*/
5658
private $storeManagerMock;
5759

5860
/**
59-
* @var Context|\PHPUnit_Framework_MockObject_MockObject
61+
* @var Context|MockObject
6062
*/
6163
private $contextMock;
6264

6365
/**
64-
* @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
66+
* @var Select|MockObject
6567
*/
6668
private $selectMock;
6769

6870
/**
69-
* @var \Zend_Db_Statement_Interface|\PHPUnit_Framework_MockObject_MockObject
71+
* @var \Zend_Db_Statement_Interface|MockObject
7072
*/
7173
private $statementMock;
72-
74+
75+
/**
76+
* @inheritdoc
77+
*/
7378
protected function setUp()
7479
{
7580
$objectManager = new ObjectManager($this);
76-
$this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
81+
$this->selectMock = $this->getMockBuilder(Select::class)
7782
->disableOriginalConstructor()
7883
->getMock();
7984
$this->contextMock = $objectManager->getObject(Context::class);
@@ -115,23 +120,35 @@ protected function setUp()
115120
* @param array $productIds
116121
* @param array $products
117122
* @param array $result
123+
* @param array $items
118124
*
119125
* @return void
120126
*/
121-
public function testLockProductsStock(int $websiteId, array $productIds, array $products, array $result)
122-
{
123-
$this->selectMock->expects($this->exactly(2))
127+
public function testLockProductsStock(
128+
int $websiteId,
129+
array $productIds,
130+
array $products,
131+
array $result,
132+
array $items
133+
) {
134+
$itemIds = [];
135+
foreach ($items as $item) {
136+
$itemIds[] = $item['item_id'];
137+
}
138+
$this->selectMock->expects($this->exactly(3))
124139
->method('from')
125140
->withConsecutive(
141+
[$this->identicalTo(self::ITEM_TABLE)],
126142
[$this->identicalTo(['si' => self::ITEM_TABLE])],
127143
[$this->identicalTo(['p' => self::PRODUCT_TABLE]), $this->identicalTo([])]
128144
)
129145
->willReturnSelf();
130-
$this->selectMock->expects($this->exactly(3))
146+
$this->selectMock->expects($this->exactly(4))
131147
->method('where')
132148
->withConsecutive(
133149
[$this->identicalTo('website_id = ?'), $this->identicalTo($websiteId)],
134150
[$this->identicalTo('product_id IN(?)'), $this->identicalTo($productIds)],
151+
[$this->identicalTo('item_id IN (?)'), $this->identicalTo($itemIds)],
135152
[$this->identicalTo('entity_id IN (?)'), $this->identicalTo($productIds)]
136153
)
137154
->willReturnSelf();
@@ -143,14 +160,17 @@ public function testLockProductsStock(int $websiteId, array $productIds, array $
143160
->method('columns')
144161
->with($this->identicalTo(['product_id' => 'entity_id', 'type_id' => 'type_id']))
145162
->willReturnSelf();
146-
$this->connectionMock->expects($this->exactly(2))
163+
$this->connectionMock->expects($this->exactly(3))
147164
->method('select')
148165
->willReturn($this->selectMock);
149-
$this->connectionMock->expects($this->once())
166+
$this->connectionMock->expects($this->exactly(2))
150167
->method('query')
151168
->with($this->identicalTo($this->selectMock))
152169
->willReturn($this->statementMock);
153-
$this->statementMock->expects($this->once())
170+
$this->statementMock->expects($this->at(0))
171+
->method('fetchAll')
172+
->willReturn($items);
173+
$this->statementMock->expects($this->at(1))
154174
->method('fetchAll')
155175
->willReturn($products);
156176
$this->connectionMock->expects($this->once())
@@ -166,7 +186,7 @@ public function testLockProductsStock(int $websiteId, array $productIds, array $
166186
self::ITEM_TABLE,
167187
self::PRODUCT_TABLE
168188
));
169-
$this->stock->expects($this->exactly(4))
189+
$this->stock->expects($this->exactly(6))
170190
->method('getConnection')
171191
->willReturn($this->connectionMock);
172192

@@ -203,6 +223,7 @@ public function productsDataProvider(): array
203223
'type_id' => 'simple',
204224
],
205225
],
226+
[['item_id' => 1], ['item_id' => 2], ['item_id' => 3]]
206227
],
207228
];
208229
}

app/code/Magento/CatalogInventory/etc/db_schema.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@
8787
<index referenceId="CATALOGINVENTORY_STOCK_ITEM_WEBSITE_ID" indexType="btree">
8888
<column name="website_id"/>
8989
</index>
90+
<index referenceId="CATALOGINVENTORY_STOCK_ITEM_WEBSITE_ID_PRODUCT_ID" indexType="btree">
91+
<column name="website_id"/>
92+
<column name="product_id"/>
93+
</index>
9094
<index referenceId="CATALOGINVENTORY_STOCK_ITEM_STOCK_ID" indexType="btree">
9195
<column name="stock_id"/>
9296
</index>

app/code/Magento/CatalogInventory/etc/db_schema_whitelist.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
},
4444
"index": {
4545
"CATALOGINVENTORY_STOCK_ITEM_WEBSITE_ID": true,
46+
"CATALOGINVENTORY_STOCK_ITEM_WEBSITE_ID_PRODUCT_ID": true,
4647
"CATALOGINVENTORY_STOCK_ITEM_STOCK_ID": true
4748
},
4849
"constraint": {
@@ -123,4 +124,4 @@
123124
"PRIMARY": true
124125
}
125126
}
126-
}
127+
}

app/code/Magento/Customer/etc/db_schema.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@
457457
<constraint xsi:type="foreign" referenceId="CUSTOMER_EAV_ATTRIBUTE_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID"
458458
table="customer_eav_attribute" column="attribute_id" referenceTable="eav_attribute"
459459
referenceColumn="attribute_id" onDelete="CASCADE"/>
460+
<index referenceId="CUSTOMER_EAV_ATTRIBUTE_SORT_ORDER" indexType="btree">
461+
<column name="sort_order"/>
462+
</index>
460463
</table>
461464
<table name="customer_form_attribute" resource="default" engine="innodb" comment="Customer Form Attribute">
462465
<column xsi:type="varchar" name="form_code" nullable="false" length="32" comment="Form Code"/>

app/code/Magento/Customer/etc/db_schema_whitelist.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@
284284
"is_filterable_in_grid": true,
285285
"is_searchable_in_grid": true
286286
},
287+
"index": {
288+
"CUSTOMER_EAV_ATTRIBUTE_SORT_ORDER": true
289+
},
287290
"constraint": {
288291
"PRIMARY": true,
289292
"CUSTOMER_EAV_ATTRIBUTE_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID": true
@@ -347,4 +350,4 @@
347350
"CUSTOMER_LOG_CUSTOMER_ID": true
348351
}
349352
}
350-
}
353+
}

0 commit comments

Comments
 (0)