Skip to content

Commit bf77de0

Browse files
committed
Merge branch '2.4-develop' of github.com:magento/magento2 into 1703-deleted-tags-not-removed
2 parents 3b350fd + 7198c76 commit bf77de0

File tree

125 files changed

+4670
-1722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+4670
-1722
lines changed

app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteABundleProductTest.xml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,9 @@
6868
<actionGroup ref="FilterProductGridByNameActionGroup" stepKey="filterBundleProductOptionsDownToName">
6969
<argument name="product" value="BundleProduct"/>
7070
</actionGroup>
71-
<click selector="{{AdminProductFiltersSection.allCheckbox}}" stepKey="SelectAllOnly1"/>
72-
<waitForPageLoad stepKey="loading2"/>
7371

7472
<!--Delete-->
75-
<click selector="{{AdminProductFiltersSection.actions}}" stepKey="ClickOnActionsChangingView"/>
76-
<click selector="{{AdminProductFiltersSection.delete}}" stepKey="ClickDelete"/>
77-
<click selector="//button[@class='action-primary action-accept']" stepKey="ConfirmDelete"/>
78-
<waitForPageLoad stepKey="loading3"/>
73+
<actionGroup ref="AdminDeleteAllProductsFromGridActionGroup" stepKey="selectAndDeleteProducts"/>
7974

8075
<!--Locating delete message-->
8176
<seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="deleteMessage"/>

app/code/Magento/Bundle/Test/Mftf/Test/AdminMassDeleteBundleProductsTest.xml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,7 @@
118118
<actionGroup ref="BundleProductFilter" stepKey="FilterForOnlyBundleProducts"/>
119119

120120
<!--Delete-->
121-
<click selector="{{AdminProductFiltersSection.allCheckbox}}" stepKey="SelectAllOnly1"/>
122-
<waitForPageLoad stepKey="loading"/>
123-
<click selector="{{AdminProductFiltersSection.actions}}" stepKey="ClickOnActionsChangingView"/>
124-
<click selector="{{AdminProductFiltersSection.delete}}" stepKey="ClickDelete"/>
125-
<click selector="//button[@class='action-primary action-accept']" stepKey="ConfirmDelete"/>
126-
<waitForPageLoad stepKey="loading3"/>
121+
<actionGroup ref="AdminDeleteAllProductsFromGridActionGroup" stepKey="selectAndDeleteProducts"/>
127122

128123
<!--Locating delete message-->
129124
<seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="deleteMessage"/>

app/code/Magento/CacheInvalidate/Model/PurgeCache.php

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,24 @@
66
namespace Magento\CacheInvalidate\Model;
77

88
use Magento\Framework\Cache\InvalidateLogger;
9+
use Magento\PageCache\Model\Cache\Server;
10+
use Laminas\Http\Client\Adapter\Socket;
11+
use Laminas\Uri\Uri;
912

1013
/**
11-
* PurgeCache model
14+
* Invalidate external HTTP cache(s) based on tag pattern
1215
*/
1316
class PurgeCache
1417
{
1518
const HEADER_X_MAGENTO_TAGS_PATTERN = 'X-Magento-Tags-Pattern';
1619

1720
/**
18-
* @var \Magento\PageCache\Model\Cache\Server
21+
* @var Server
1922
*/
2023
protected $cacheServer;
2124

2225
/**
23-
* @var \Magento\CacheInvalidate\Model\SocketFactory
26+
* @var SocketFactory
2427
*/
2528
protected $socketAdapterFactory;
2629

@@ -39,39 +42,46 @@ class PurgeCache
3942
*
4043
* @var int
4144
*/
42-
private $requestSize = 7680;
45+
private $maxHeaderSize;
4346

4447
/**
4548
* Constructor
4649
*
47-
* @param \Magento\PageCache\Model\Cache\Server $cacheServer
48-
* @param \Magento\CacheInvalidate\Model\SocketFactory $socketAdapterFactory
50+
* @param Server $cacheServer
51+
* @param SocketFactory $socketAdapterFactory
4952
* @param InvalidateLogger $logger
53+
* @param int $maxHeaderSize
5054
*/
5155
public function __construct(
52-
\Magento\PageCache\Model\Cache\Server $cacheServer,
53-
\Magento\CacheInvalidate\Model\SocketFactory $socketAdapterFactory,
54-
InvalidateLogger $logger
56+
Server $cacheServer,
57+
SocketFactory $socketAdapterFactory,
58+
InvalidateLogger $logger,
59+
int $maxHeaderSize = 7680
5560
) {
5661
$this->cacheServer = $cacheServer;
5762
$this->socketAdapterFactory = $socketAdapterFactory;
5863
$this->logger = $logger;
64+
$this->maxHeaderSize = $maxHeaderSize;
5965
}
6066

6167
/**
6268
* Send curl purge request to invalidate cache by tags pattern
6369
*
64-
* @param string $tagsPattern
70+
* @param array|string $tags
6571
* @return bool Return true if successful; otherwise return false
6672
*/
67-
public function sendPurgeRequest($tagsPattern)
73+
public function sendPurgeRequest($tags)
6874
{
75+
if (is_string($tags)) {
76+
$tags = [$tags];
77+
}
78+
6979
$successful = true;
7080
$socketAdapter = $this->socketAdapterFactory->create();
7181
$servers = $this->cacheServer->getUris();
7282
$socketAdapter->setOptions(['timeout' => 10]);
7383

74-
$formattedTagsChunks = $this->splitTags($tagsPattern);
84+
$formattedTagsChunks = $this->chunkTags($tags);
7585
foreach ($formattedTagsChunks as $formattedTagsChunk) {
7686
if (!$this->sendPurgeRequestToServers($socketAdapter, $servers, $formattedTagsChunk)) {
7787
$successful = false;
@@ -82,24 +92,24 @@ public function sendPurgeRequest($tagsPattern)
8292
}
8393

8494
/**
85-
* Split tags by batches
95+
* Split tags into batches to suit Varnish max. header size
8696
*
87-
* @param string $tagsPattern
97+
* @param array $tags
8898
* @return \Generator
8999
*/
90-
private function splitTags($tagsPattern)
100+
private function chunkTags(array $tags): \Generator
91101
{
92-
$tagsBatchSize = 0;
102+
$currentBatchSize = 0;
93103
$formattedTagsChunk = [];
94-
$formattedTags = explode('|', $tagsPattern);
95-
foreach ($formattedTags as $formattedTag) {
96-
if ($tagsBatchSize + strlen($formattedTag) > $this->requestSize - count($formattedTagsChunk) - 1) {
104+
foreach ($tags as $formattedTag) {
105+
// Check if (currentBatchSize + length of next tag + number of pipe delimiters) would exceed header size.
106+
if ($currentBatchSize + strlen($formattedTag) + count($formattedTagsChunk) > $this->maxHeaderSize) {
97107
yield implode('|', $formattedTagsChunk);
98108
$formattedTagsChunk = [];
99-
$tagsBatchSize = 0;
109+
$currentBatchSize = 0;
100110
}
101111

102-
$tagsBatchSize += strlen($formattedTag);
112+
$currentBatchSize += strlen($formattedTag);
103113
$formattedTagsChunk[] = $formattedTag;
104114
}
105115
if (!empty($formattedTagsChunk)) {
@@ -110,12 +120,12 @@ private function splitTags($tagsPattern)
110120
/**
111121
* Send curl purge request to servers to invalidate cache by tags pattern
112122
*
113-
* @param \Laminas\Http\Client\Adapter\Socket $socketAdapter
114-
* @param \Laminas\Uri\Uri[] $servers
123+
* @param Socket $socketAdapter
124+
* @param Uri[] $servers
115125
* @param string $formattedTagsChunk
116126
* @return bool Return true if successful; otherwise return false
117127
*/
118-
private function sendPurgeRequestToServers($socketAdapter, $servers, $formattedTagsChunk)
128+
private function sendPurgeRequestToServers(Socket $socketAdapter, array $servers, string $formattedTagsChunk): bool
119129
{
120130
$headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $formattedTagsChunk];
121131
$unresponsiveServerError = [];
@@ -145,14 +155,14 @@ private function sendPurgeRequestToServers($socketAdapter, $servers, $formattedT
145155
if ($errorCount == count($servers)) {
146156
$this->logger->critical(
147157
'No cache server(s) could be purged ' . $loggerMessage,
148-
compact('server', 'formattedTagsChunk')
158+
compact('servers', 'formattedTagsChunk')
149159
);
150160
return false;
151161
}
152162

153163
$this->logger->warning(
154164
'Unresponsive cache server(s) hit' . $loggerMessage,
155-
compact('server', 'formattedTagsChunk')
165+
compact('servers', 'formattedTagsChunk')
156166
);
157167
}
158168

app/code/Magento/CacheInvalidate/Observer/FlushAllCacheObserver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
use Magento\Framework\Event\ObserverInterface;
99

10+
/**
11+
* Clear configured Varnish hosts when triggering a full cache flush (e.g. from the Cache Management admin dashboard)
12+
*/
1013
class FlushAllCacheObserver implements ObserverInterface
1114
{
1215
/**
@@ -43,7 +46,7 @@ public function __construct(
4346
public function execute(\Magento\Framework\Event\Observer $observer)
4447
{
4548
if ($this->config->getType() == \Magento\PageCache\Model\Config::VARNISH && $this->config->isEnabled()) {
46-
$this->purgeCache->sendPurgeRequest('.*');
49+
$this->purgeCache->sendPurgeRequest(['.*']);
4750
}
4851
}
4952
}

app/code/Magento/CacheInvalidate/Observer/InvalidateVarnishObserver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function execute(Observer $observer)
7777
$tags[] = sprintf($pattern, $tag);
7878
}
7979
if (!empty($tags)) {
80-
$this->purgeCache->sendPurgeRequest(implode('|', array_unique($tags)));
80+
$this->purgeCache->sendPurgeRequest(array_unique($tags));
8181
}
8282
}
8383
}

app/code/Magento/CacheInvalidate/Test/Unit/Model/PurgeCacheTest.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ protected function setUp(): void
5353
'cacheServer' => $this->cacheServer,
5454
'socketAdapterFactory' => $socketFactoryMock,
5555
'logger' => $this->loggerMock,
56+
'maxHeaderSize' => 256
5657
]
5758
);
5859
}
@@ -64,6 +65,7 @@ protected function setUp(): void
6465
public function testSendPurgeRequest($hosts)
6566
{
6667
$uris = [];
68+
/** @var array $host */
6769
foreach ($hosts as $host) {
6870
$port = isset($host['port']) ? $host['port'] : Server::DEFAULT_PORT;
6971
$uris[] = UriFactory::factory('')->setHost($host['host'])
@@ -92,7 +94,50 @@ public function testSendPurgeRequest($hosts)
9294
$this->loggerMock->expects($this->once())
9395
->method('execute');
9496

95-
$this->assertTrue($this->model->sendPurgeRequest('tags'));
97+
$this->assertTrue($this->model->sendPurgeRequest(['tags']));
98+
}
99+
100+
public function testSendMultiPurgeRequest()
101+
{
102+
$tags = [
103+
'(^|,)cat_p_95(,|$)', '(^|,)cat_p_96(,|$)', '(^|,)cat_p_97(,|$)', '(^|,)cat_p_98(,|$)',
104+
'(^|,)cat_p_99(,|$)', '(^|,)cat_p_100(,|$)', '(^|,)cat_p_10038(,|$)', '(^|,)cat_p_142985(,|$)',
105+
'(^|,)cat_p_199(,|$)', '(^|,)cat_p_300(,|$)', '(^|,)cat_p_12038(,|$)', '(^|,)cat_p_152985(,|$)',
106+
'(^|,)cat_p_299(,|$)', '(^|,)cat_p_400(,|$)', '(^|,)cat_p_13038(,|$)', '(^|,)cat_p_162985(,|$)',
107+
];
108+
109+
$tagsSplitA = array_slice($tags, 0, 12);
110+
$tagsSplitB = array_slice($tags, 12, 4);
111+
112+
$uri = UriFactory::factory('')->setHost('localhost')
113+
->setPort(80)
114+
->setScheme('http');
115+
116+
$this->cacheServer->expects($this->once())
117+
->method('getUris')
118+
->willReturn([$uri]);
119+
120+
$this->socketAdapterMock->expects($this->exactly(2))
121+
->method('connect')
122+
->with($uri->getHost(), $uri->getPort());
123+
124+
$this->socketAdapterMock->expects($this->exactly(2))
125+
->method('write')
126+
->withConsecutive(
127+
[
128+
'PURGE', $uri, '1.1',
129+
['X-Magento-Tags-Pattern' => implode('|', $tagsSplitA), 'Host' => $uri->getHost()]
130+
],
131+
[
132+
'PURGE', $uri, '1.1',
133+
['X-Magento-Tags-Pattern' => implode('|', $tagsSplitB), 'Host' => $uri->getHost()]
134+
]
135+
);
136+
137+
$this->socketAdapterMock->expects($this->exactly(2))
138+
->method('close');
139+
140+
$this->assertTrue($this->model->sendPurgeRequest($tags));
96141
}
97142

98143
/**
@@ -130,6 +175,6 @@ public function testSendPurgeRequestWithException()
130175
$this->loggerMock->expects($this->once())
131176
->method('critical');
132177

133-
$this->assertFalse($this->model->sendPurgeRequest('tags'));
178+
$this->assertFalse($this->model->sendPurgeRequest(['tags']));
134179
}
135180
}

app/code/Magento/CacheInvalidate/Test/Unit/Observer/FlushAllCacheObserverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function testFlushAllCache()
5656
Config::VARNISH
5757
);
5858

59-
$this->purgeCache->expects($this->once())->method('sendPurgeRequest')->with('.*');
59+
$this->purgeCache->expects($this->once())->method('sendPurgeRequest')->with(['.*']);
6060
$this->model->execute($this->observerMock);
6161
}
6262
}

app/code/Magento/CacheInvalidate/Test/Unit/Observer/InvalidateVarnishObserverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected function setUp(): void
8282
public function testInvalidateVarnish()
8383
{
8484
$tags = ['cache_1', 'cache_group'];
85-
$pattern = '((^|,)cache_1(,|$))|((^|,)cache_group(,|$))';
85+
$pattern = ['((^|,)cache_1(,|$))', '((^|,)cache_group(,|$))'];
8686

8787
$this->configMock->expects($this->once())->method('isEnabled')->willReturn(true);
8888
$this->configMock->expects(
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminDeleteAllProductsFromGridActionGroup">
12+
<annotations>
13+
<description>Select and delete products in product grid.</description>
14+
</annotations>
15+
<click selector="{{AdminProductFiltersSection.allCheckbox}}" stepKey="selectAllProducts"/>
16+
<click selector="{{AdminProductFiltersSection.actions}}" stepKey="clickOnActionsChangingView"/>
17+
<click selector="{{AdminProductFiltersSection.delete}}" stepKey="clickDelete"/>
18+
<click selector="//button[@class='action-primary action-accept']" stepKey="confirmDelete"/>
19+
<waitForPageLoad stepKey="waitingProductGridLoad"/>
20+
</actionGroup>
21+
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridUrlFilterApplierTest.xml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,24 @@
1818
<testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4931106"/>
1919
<group value="product"/>
2020
</annotations>
21+
2122
<before>
2223
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
23-
<createData entity="simpleProductWithShortNameAndSku" stepKey="createSimpleProduct"/>
24+
<createData entity="SimpleProduct2" stepKey="createSimpleProduct"/>
2425
</before>
26+
2527
<after>
26-
<actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/>
2728
<deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/>
29+
<actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndex"/>
30+
<actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/>
2831
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/>
2932
</after>
30-
<amOnPage url="{{AdminProductIndexPage.url}}?filters[name]=$$createSimpleProduct.name$$" stepKey="navigateToProductGridWithFilters"/>
33+
34+
<amOnPage url="{{AdminProductIndexPage.url}}?filters[name]=$createSimpleProduct.name$" stepKey="navigateToProductGridWithFilters"/>
3135
<waitForPageLoad stepKey="waitForProductGrid"/>
32-
<see selector="{{AdminProductGridSection.productGridNameProduct($$createSimpleProduct.name$$)}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct"/>
36+
<see selector="{{AdminProductGridSection.productGridNameProduct($createSimpleProduct.name$)}}" userInput="$createSimpleProduct.name$" stepKey="seeProduct"/>
37+
<waitForElementVisible selector="{{AdminProductGridFilterSection.enabledFilters}}" stepKey="waitForEnabledFilters"/>
3338
<seeElement selector="{{AdminProductGridFilterSection.enabledFilters}}" stepKey="seeEnabledFilters"/>
34-
<see selector="{{AdminProductGridFilterSection.enabledFilters}}" userInput="Name: $$createSimpleProduct.name$$" stepKey="seeProductNameFilter"/>
39+
<see selector="{{AdminProductGridFilterSection.enabledFilters}}" userInput="Name: $createSimpleProduct.name$" stepKey="seeProductNameFilter"/>
3540
</test>
3641
</tests>

app/code/Magento/CatalogImportExport/Test/Unit/Model/Export/ProductTest.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
namespace Magento\CatalogImportExport\Test\Unit\Model\Export;
99

1010
use Magento\Catalog\Model\Product\LinkTypeProvider;
11+
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
1112
use Magento\CatalogImportExport\Model\Export\Product;
1213
use Magento\CatalogImportExport\Model\Export\Product\Type\Factory;
1314
use Magento\CatalogImportExport\Model\Export\RowCustomizer\Composite;
1415
use Magento\Eav\Model\Config;
1516
use Magento\Eav\Model\Entity\Collection\AbstractCollection;
1617
use Magento\Eav\Model\Entity\Type;
18+
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory as AttributeSetCollectionFactory;
1719
use Magento\Framework\App\ResourceConnection;
1820
use Magento\Framework\EntityManager\MetadataPool;
1921
use Magento\Framework\Logger\Monolog;
@@ -83,7 +85,7 @@ class ProductTest extends TestCase
8385
protected $attrSetColFactory;
8486

8587
/**
86-
* @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory|MockObject
88+
* @var CategoryCollectionFactory|MockObject
8789
*/
8890
protected $categoryColFactory;
8991

@@ -174,15 +176,14 @@ protected function setUp(): void
174176
->onlyMethods(['create'])
175177
->getMock();
176178

177-
$this->attrSetColFactory = $this->getMockBuilder(
178-
\Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory::class
179-
)->addMethods(['setEntityTypeFilter'])
179+
$this->attrSetColFactory = $this->getMockBuilder(AttributeSetCollectionFactory::class)
180+
->disableOriginalConstructor()
181+
->addMethods(['setEntityTypeFilter'])
180182
->onlyMethods(['create'])
181183
->getMock();
182184

183-
$this->categoryColFactory = $this->getMockBuilder(
184-
\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory::class
185-
)->addMethods(['addNameToResult'])
185+
$this->categoryColFactory = $this->getMockBuilder(CategoryCollectionFactory::class)
186+
->disableOriginalConstructor()->addMethods(['addNameToResult'])
186187
->onlyMethods(['create'])
187188
->getMock();
188189

0 commit comments

Comments
 (0)