Skip to content

Commit c656811

Browse files
committed
Merge branch '2.4-develop' into ACP2E-10
2 parents 56cec9e + 1807f70 commit c656811

File tree

24 files changed

+943
-313
lines changed

24 files changed

+943
-313
lines changed

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

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Magento\Catalog\Model\ResourceModel\Product\Indexer\AbstractIndexer;
1010
use Magento\CatalogInventory\Model\Stock;
11+
use Magento\Framework\App\ObjectManager;
1112
use Magento\Framework\DB\Adapter\AdapterInterface;
1213
use Magento\CatalogInventory\Api\StockConfigurationInterface;
1314
use Magento\CatalogInventory\Model\Indexer\Stock\Action\Full;
@@ -26,22 +27,16 @@
2627
class DefaultStock extends AbstractIndexer implements StockInterface
2728
{
2829
/**
29-
* Current Product Type Id
30-
*
3130
* @var string
3231
*/
3332
protected $_typeId;
3433

3534
/**
36-
* Product Type is composite flag
37-
*
3835
* @var bool
3936
*/
4037
protected $_isComposite = false;
4138

4239
/**
43-
* Core store config
44-
*
4540
* @var \Magento\Framework\App\Config\ScopeConfigInterface
4641
*/
4742
protected $_scopeConfig;
@@ -58,12 +53,15 @@ class DefaultStock extends AbstractIndexer implements StockInterface
5853
protected $stockConfiguration;
5954

6055
/**
61-
* Param for switching logic which depends on action type (full reindex or partial)
62-
*
6356
* @var string
6457
*/
6558
private $actionType;
6659

60+
/**
61+
* @var GetStatusExpression
62+
*/
63+
private $getStatusExpression;
64+
6765
/**
6866
* Class constructor
6967
*
@@ -72,16 +70,21 @@ class DefaultStock extends AbstractIndexer implements StockInterface
7270
* @param \Magento\Eav\Model\Config $eavConfig
7371
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
7472
* @param string $connectionName
73+
* @param \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression|null $getStatusExpression
7574
*/
7675
public function __construct(
7776
\Magento\Framework\Model\ResourceModel\Db\Context $context,
7877
\Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
7978
\Magento\Eav\Model\Config $eavConfig,
8079
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
81-
$connectionName = null
80+
$connectionName = null,
81+
\Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression $getStatusExpression = null
8282
) {
8383
$this->_scopeConfig = $scopeConfig;
8484
parent::__construct($context, $tableStrategy, $eavConfig, $connectionName);
85+
$this->getStatusExpression = $getStatusExpression ?: ObjectManager::getInstance()->get(
86+
\Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression::class
87+
);
8588
}
8689

8790
/**
@@ -251,6 +254,10 @@ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = f
251254
. ' AND mcpei.attribute_id = ' . $this->_getAttribute('status')->getId()
252255
. ' AND mcpei.value = ' . ProductStatus::STATUS_ENABLED,
253256
[]
257+
)->joinLeft(
258+
['css' => 'cataloginventory_stock_status'],
259+
'css.product_id = e.entity_id',
260+
[]
254261
)->columns(
255262
['qty' => $qtyExpr]
256263
)->where(
@@ -292,14 +299,14 @@ protected function _prepareIndexTable($entityIds = null)
292299
*/
293300
protected function _updateIndex($entityIds)
294301
{
295-
$this->deleteOldRecords($entityIds);
296302
$connection = $this->getConnection();
297303
$select = $this->_getStockStatusSelect($entityIds, true);
298304
$select = $this->getQueryProcessorComposite()->processQuery($select, $entityIds, true);
299305
$query = $connection->query($select);
300306

301307
$i = 0;
302308
$data = [];
309+
$savedEntityIds = [];
303310
while ($row = $query->fetch(\PDO::FETCH_ASSOC)) {
304311
$i++;
305312
$data[] = [
@@ -309,6 +316,7 @@ protected function _updateIndex($entityIds)
309316
'qty' => (double)$row['qty'],
310317
'stock_status' => (int)$row['status'],
311318
];
319+
$savedEntityIds[] = (int)$row['entity_id'];
312320
if ($i % 1000 == 0) {
313321
$this->_updateIndexTable($data);
314322
$data = [];
@@ -317,6 +325,7 @@ protected function _updateIndex($entityIds)
317325

318326
$this->_updateIndexTable($data);
319327

328+
$this->deleteOldRecords(array_diff($entityIds, $savedEntityIds));
320329
return $this;
321330
}
322331

@@ -376,21 +385,7 @@ public function getIdxTable($table = null)
376385
*/
377386
protected function getStatusExpression(AdapterInterface $connection, $isAggregate = false)
378387
{
379-
$isInStockExpression = $isAggregate ? 'MAX(cisi.is_in_stock)' : 'cisi.is_in_stock';
380-
if ($this->_isManageStock()) {
381-
$statusExpr = $connection->getCheckSql(
382-
'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0',
383-
1,
384-
$isInStockExpression
385-
);
386-
} else {
387-
$statusExpr = $connection->getCheckSql(
388-
'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1',
389-
$isInStockExpression,
390-
1
391-
);
392-
}
393-
return $statusExpr;
388+
return $this->getStatusExpression->execute($this->getTypeId(), $connection, $isAggregate);
394389
}
395390

396391
/**
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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\CatalogInventory\Model\ResourceModel\Indexer\Stock;
9+
10+
use InvalidArgumentException;
11+
use Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\ExpressionInterface;
12+
use Magento\Framework\DB\Adapter\AdapterInterface;
13+
use Zend_Db_Expr;
14+
15+
class GetStatusExpression
16+
{
17+
/**
18+
* @var array
19+
*/
20+
private $statusExpressions;
21+
22+
/**
23+
* @param array $statusExpressions
24+
*/
25+
public function __construct(array $statusExpressions = [])
26+
{
27+
foreach ($statusExpressions as $expression) {
28+
if (!($expression instanceof ExpressionInterface)) {
29+
throw new InvalidArgumentException(
30+
'Expressions must implement '
31+
.'\Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\ExpressionInterface'
32+
.' interface'
33+
);
34+
}
35+
}
36+
$this->statusExpressions = $statusExpressions;
37+
}
38+
39+
/**
40+
* Returns stock status expression for MySQL query.
41+
*
42+
* @param string $productType
43+
* @param AdapterInterface $connection
44+
* @param bool $isAggregate
45+
* @return Zend_Db_Expr|null
46+
*/
47+
public function execute(string $productType, AdapterInterface $connection, bool $isAggregate): ?Zend_Db_Expr
48+
{
49+
$expression = $this->statusExpressions[$productType] ?? $this->statusExpressions['default'];
50+
return $expression->getExpression($connection, $isAggregate);
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression;
8+
9+
use Magento\CatalogInventory\Model\Configuration;
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\DB\Adapter\AdapterInterface;
12+
use Magento\Store\Model\ScopeInterface;
13+
use Zend_Db_Expr;
14+
15+
class DefaultExpression implements ExpressionInterface
16+
{
17+
/**
18+
* @var ScopeConfigInterface
19+
*/
20+
private $scopeConfig;
21+
22+
/**
23+
* @param ScopeConfigInterface $scopeConfig
24+
*/
25+
public function __construct(ScopeConfigInterface $scopeConfig)
26+
{
27+
$this->scopeConfig = $scopeConfig;
28+
}
29+
30+
/**
31+
* Returns status expressions for MySQL query
32+
*
33+
* @ingeritdoc
34+
* @param AdapterInterface $connection
35+
* @param bool $isAggregate
36+
* @return Zend_Db_Expr
37+
*/
38+
public function getExpression(AdapterInterface $connection, bool $isAggregate): Zend_Db_Expr
39+
{
40+
$isManageStock = $this->scopeConfig->isSetFlag(
41+
Configuration::XML_PATH_MANAGE_STOCK,
42+
ScopeInterface::SCOPE_STORE
43+
);
44+
45+
$isInStockExpression = $isAggregate ? 'MAX(cisi.is_in_stock)' : 'cisi.is_in_stock';
46+
if ($isManageStock) {
47+
$statusExpr = $connection->getCheckSql(
48+
'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0',
49+
1,
50+
$isInStockExpression
51+
);
52+
} else {
53+
$statusExpr = $connection->getCheckSql(
54+
'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1',
55+
$isInStockExpression,
56+
1
57+
);
58+
}
59+
return $statusExpr;
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression;
8+
9+
use Magento\Framework\DB\Adapter\AdapterInterface;
10+
use Zend_Db_Expr;
11+
12+
/**
13+
* Interface for composite status expressions for MySQL query.
14+
*/
15+
interface ExpressionInterface
16+
{
17+
/**
18+
* Returns status expressions for MySQL query
19+
*
20+
* @param AdapterInterface $connection
21+
* @param bool $isAggregate
22+
* @return Zend_Db_Expr
23+
*/
24+
public function getExpression(AdapterInterface $connection, bool $isAggregate): Zend_Db_Expr;
25+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,11 @@
133133
<type name="Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save">
134134
<plugin name="massAction" type="Magento\CatalogInventory\Plugin\MassUpdateProductAttribute" />
135135
</type>
136+
<type name="Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression">
137+
<arguments>
138+
<argument name="statusExpressions" xsi:type="array">
139+
<item name="default" xsi:type="object">Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\DefaultExpression</item>
140+
</argument>
141+
</arguments>
142+
</type>
136143
</config>

app/code/Magento/PageCache/etc/varnish4.vcl

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,16 @@ sub vcl_recv {
108108
#unset req.http.Cookie;
109109
}
110110

111-
# Authenticated GraphQL requests should not be cached by default
112-
if (req.url ~ "/graphql" && req.http.Authorization ~ "^Bearer") {
111+
# Bypass authenticated GraphQL requests without a X-Magento-Cache-Id
112+
if (req.url ~ "/graphql" && !req.http.X-Magento-Cache-Id && req.http.Authorization ~ "^Bearer") {
113113
return (pass);
114114
}
115115

116116
return (hash);
117117
}
118118

119119
sub vcl_hash {
120-
if (req.http.cookie ~ "X-Magento-Vary=") {
120+
if ((req.url !~ "/graphql" || !req.http.X-Magento-Cache-Id) && req.http.cookie ~ "X-Magento-Vary=") {
121121
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
122122
}
123123

@@ -133,9 +133,19 @@ sub vcl_hash {
133133
}
134134

135135
sub process_graphql_headers {
136+
if (req.http.X-Magento-Cache-Id) {
137+
hash_data(req.http.X-Magento-Cache-Id);
138+
139+
# When the frontend stops sending the auth token, make sure users stop getting results cached for logged-in users
140+
if (req.http.Authorization ~ "^Bearer") {
141+
hash_data("Authorized");
142+
}
143+
}
144+
136145
if (req.http.Store) {
137146
hash_data(req.http.Store);
138147
}
148+
139149
if (req.http.Content-Currency) {
140150
hash_data(req.http.Content-Currency);
141151
}
@@ -184,19 +194,21 @@ sub vcl_backend_response {
184194
set beresp.uncacheable = true;
185195
}
186196

197+
# If the cache key in the Magento response doesn't match the one that was sent in the request, don't cache under the request's key
198+
if (bereq.url ~ "/graphql" && bereq.http.X-Magento-Cache-Id && bereq.http.X-Magento-Cache-Id != beresp.http.X-Magento-Cache-Id) {
199+
set beresp.ttl = 0s;
200+
set beresp.uncacheable = true;
201+
}
202+
187203
return (deliver);
188204
}
189205

190206
sub vcl_deliver {
191-
if (resp.http.X-Magento-Debug) {
192-
if (resp.http.x-varnish ~ " ") {
193-
set resp.http.X-Magento-Cache-Debug = "HIT";
194-
set resp.http.Grace = req.http.grace;
195-
} else {
196-
set resp.http.X-Magento-Cache-Debug = "MISS";
197-
}
207+
if (resp.http.x-varnish ~ " ") {
208+
set resp.http.X-Magento-Cache-Debug = "HIT";
209+
set resp.http.Grace = req.http.grace;
198210
} else {
199-
unset resp.http.Age;
211+
set resp.http.X-Magento-Cache-Debug = "MISS";
200212
}
201213

202214
# Not letting browser to cache non-static files.
@@ -206,6 +218,9 @@ sub vcl_deliver {
206218
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
207219
}
208220

221+
if (!resp.http.X-Magento-Debug) {
222+
unset resp.http.Age;
223+
}
209224
unset resp.http.X-Magento-Debug;
210225
unset resp.http.X-Magento-Tags;
211226
unset resp.http.X-Powered-By;

0 commit comments

Comments
 (0)