Skip to content

Commit 9f17b1e

Browse files
Merge branch '2.4-develop' into 32368-qraphql-get-cart-type
2 parents 3e710f2 + d290f35 commit 9f17b1e

File tree

6,260 files changed

+155760
-110138
lines changed

Some content is hidden

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

6,260 files changed

+155760
-110138
lines changed

.editorconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trim_trailing_whitespace = false
1414
[*.{yml,yaml,json}]
1515
indent_size = 2
1616

17-
[{composer, auth}.json]
17+
[{composer,auth}.json]
1818
indent_size = 4
1919

2020
[db_schema_whitelist.json]

.github/CONTRIBUTING.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Contributions to the Magento 2 codebase are done using the fork & pull model.
44
This contribution model has contributors maintaining their own fork of the Magento 2 repository.
5-
The forked repository is then used to submit a request to the base repository to pull a set of changes.
5+
The forked repository is then used to submit a request to the base repository to "pull" a set of changes.
66
For more information on pull requests please refer to [GitHub Help](https://help.github.com/articles/about-pull-requests/).
77

88
Contributions can take the form of new components or features, changes to existing features, tests, documentation (such as developer guides, user guides, examples, or specifications), bug fixes or optimizations.
@@ -19,11 +19,11 @@ For more detailed information on contribution please read our [beginners guide](
1919
2. Pull requests (PRs) must be accompanied by a meaningful description of their purpose. Comprehensive descriptions increase the chances of a pull request being merged quickly and without additional clarification requests.
2020
3. Commits must be accompanied by meaningful commit messages. Please see the [Magento Pull Request Template](https://github.com/magento/magento2/blob/HEAD/.github/PULL_REQUEST_TEMPLATE.md) for more information.
2121
4. PRs which include bug fixes must be accompanied with a step-by-step description of how to reproduce the bug.
22-
3. PRs which include new logic or new features must be submitted along with:
23-
* Unit/integration test coverage
24-
* Proposed [documentation](https://devdocs.magento.com) updates. Documentation contributions can be submitted via the [devdocs GitHub](https://github.com/magento/devdocs).
25-
4. For larger features or changes, please [open an issue](https://github.com/magento/magento2/issues) to discuss the proposed changes prior to development. This may prevent duplicate or unnecessary effort and allow other contributors to provide input.
26-
5. All automated tests must pass.
22+
5. PRs which include new logic or new features must be submitted along with:
23+
* Unit/integration test coverage
24+
* Proposed [documentation](https://developer.adobe.com/commerce) updates. Use feedback buttons __Edit in GitHub__ and __Log an issue__ at the top of a relevant topic.
25+
6. For larger features or changes, please [open an issue](https://github.com/magento/magento2/issues) to discuss the proposed changes prior to development. This may prevent duplicate or unnecessary effort and allow other contributors to provide input.
26+
7. All automated tests must pass.
2727

2828
## Contribution process
2929

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ However, for those who need a full-featured eCommerce solution, we recommend [Ad
2626

2727
## Contribute
2828

29-
Our [Community](https://opensource.magento.com/) is large and diverse, and our project is enormous. As a contributor, you have countless opportunities to impact product development and delivery by introducing new features or improving existing ones, enhancing test coverage, updating documentation for [developers](https://developer.adobe.com/commerce/docs/) and [end-users](https://docs.magento.com/user-guide/), catching and fixing code bugs, suggesting points for optimization, and sharing your great ideas.
29+
Our [Community](https://opensource.magento.com/) is large and diverse, and our project is enormous. As a contributor, you have countless opportunities to impact product development and delivery by introducing new features or improving existing ones, enhancing test coverage, updating documentation for [developers](https://developer.adobe.com/commerce/docs/) and [end-users](https://experienceleague.adobe.com/docs/commerce-admin/user-guides/home.html), catching and fixing code bugs, suggesting points for optimization, and sharing your great ideas.
3030

3131
- [Contribute to the code](https://developer.adobe.com/commerce/contributor/guides/code-contributions/)
3232
- [Report an issue](https://developer.adobe.com/commerce/contributor/guides/code-contributions/#report)

app/code/Magento/AdminAnalytics/Controller/Adminhtml/Config/EnableAdminUsage.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private function markUserNotified(): ResultInterface
8989
public function execute()
9090
{
9191
$this->enableAdminUsage();
92-
$this->markUserNotified();
92+
return $this->markUserNotified();
9393
}
9494

9595
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CloseAllDialogBoxes
2+
SelectAdminUsageSetting
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Magento\AdminAnalytics\Test\Unit\Controller\Adminhtml\Config;
10+
11+
use Magento\AdminAnalytics\Controller\Adminhtml\Config\EnableAdminUsage;
12+
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger as NotificationLogger;
13+
use Magento\Config\Model\Config;
14+
use Magento\Config\Model\Config\Factory as ConfigFactory;
15+
use Magento\Framework\App\ProductMetadataInterface;
16+
use Magento\Framework\Controller\Result\Json as JsonResult;
17+
use Magento\Framework\Controller\ResultFactory;
18+
use Magento\Framework\Controller\ResultInterface;
19+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
22+
/**
23+
* @covers \Magento\AdminAnalytics\Controller\Adminhtml\Config\EnableAdminUsage
24+
*/
25+
class EnableAdminUsageTest extends \PHPUnit\Framework\TestCase
26+
{
27+
private const STUB_PRODUCT_VERSION = 'Product Version';
28+
29+
/** @var EnableAdminUsage */
30+
private $controller;
31+
32+
/** @var MockObject|Config */
33+
private $configMock;
34+
35+
/** @var MockObject|ProductMetadataInterface */
36+
private $productMetadataMock;
37+
38+
/** @var MockObject|NotificationLogger */
39+
private $notificationLoggerMock;
40+
41+
/** @var MockObject|ResultFactory */
42+
private $resultFactoryMock;
43+
44+
/** @var JsonResult|MockObject */
45+
private $resultMock;
46+
47+
protected function setUp(): void
48+
{
49+
$objectManager = new ObjectManager($this);
50+
51+
$this->configMock = $this->getMockBuilder(Config::class)
52+
->disableOriginalConstructor()
53+
->onlyMethods(['setDataByPath', 'save'])
54+
->getMock();
55+
56+
$configFactory = $this->getMockBuilder(ConfigFactory::class)
57+
->disableOriginalConstructor()
58+
->onlyMethods(['create'])
59+
->getMock();
60+
61+
$configFactory->method('create')
62+
->willReturn($this->configMock);
63+
64+
$this->productMetadataMock = $this->getMockBuilder(ProductMetadataInterface::class)
65+
->onlyMethods(['getVersion'])
66+
->getMockForAbstractClass();
67+
68+
$this->productMetadataMock->method('getVersion')
69+
->willReturn(self::STUB_PRODUCT_VERSION);
70+
71+
$this->notificationLoggerMock = $this->getMockBuilder(NotificationLogger::class)
72+
->disableOriginalConstructor()
73+
->onlyMethods(['log'])
74+
->getMock();
75+
76+
$this->resultFactoryMock = $this->getMockBuilder(ResultFactory::class)
77+
->disableOriginalConstructor()
78+
->onlyMethods(['create'])
79+
->getMock();
80+
81+
$this->resultMock = $this->getMockBuilder(JsonResult::class)
82+
->disableOriginalConstructor()
83+
->onlyMethods(['setData'])
84+
->getMock();
85+
86+
$this->resultFactoryMock->method('create')
87+
->with(ResultFactory::TYPE_JSON)
88+
->willReturn($this->resultMock);
89+
90+
$this->controller = $objectManager->getObject(EnableAdminUsage::class, [
91+
'configFactory' => $configFactory,
92+
'productMetadata' => $this->productMetadataMock,
93+
'notificationLogger' => $this->notificationLoggerMock,
94+
'resultFactory' => $this->resultFactoryMock
95+
]);
96+
}
97+
98+
/**
99+
* If Controller returns `null`, no data is passed to the browser
100+
*/
101+
public function testResponseAfterAdminUsageChange()
102+
{
103+
// Given
104+
$this->resultMock->method('setData')->willReturnSelf();
105+
106+
// When
107+
$response = $this->controller->execute();
108+
109+
// Then
110+
$this->assertInstanceOf(ResultInterface::class, $response);
111+
}
112+
113+
public function testResponseWhenExceptionThrown()
114+
{
115+
$this->markTestSkipped('magento/magento2#31393 Lack of exception handling');
116+
117+
$this->configMock->method('setDataByPath')
118+
->willThrowException(
119+
new \Exception('System Exception')
120+
);
121+
122+
// When
123+
$response = $this->controller->execute();
124+
125+
// Then
126+
$this->assertInstanceOf(ResultInterface::class, $response);
127+
}
128+
}

app/code/Magento/AdminAnalytics/ViewModel/Metadata.php

+29-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
namespace Magento\AdminAnalytics\ViewModel;
1010

1111
use Magento\Config\Model\Config\Backend\Admin\Custom;
12+
use Magento\Csp\Helper\CspNonceProvider;
1213
use Magento\Framework\App\Config\ScopeConfigInterface;
14+
use Magento\Framework\App\ObjectManager;
1315
use Magento\Framework\App\ProductMetadataInterface;
1416
use Magento\Backend\Model\Auth\Session;
1517
use Magento\Framework\App\State;
@@ -21,6 +23,11 @@
2123
*/
2224
class Metadata implements ArgumentInterface
2325
{
26+
/**
27+
* @var string
28+
*/
29+
private $nonce;
30+
2431
/**
2532
* @var State
2633
*/
@@ -41,22 +48,33 @@ class Metadata implements ArgumentInterface
4148
*/
4249
private $config;
4350

51+
/**
52+
* @var CspNonceProvider
53+
*/
54+
private $nonceProvider;
55+
4456
/**
4557
* @param ProductMetadataInterface $productMetadata
4658
* @param Session $authSession
4759
* @param State $appState
4860
* @param ScopeConfigInterface $config
61+
* @param CspNonceProvider|null $nonceProvider
4962
*/
5063
public function __construct(
5164
ProductMetadataInterface $productMetadata,
5265
Session $authSession,
5366
State $appState,
54-
ScopeConfigInterface $config
67+
ScopeConfigInterface $config,
68+
CspNonceProvider $nonceProvider = null
5569
) {
5670
$this->productMetadata = $productMetadata;
5771
$this->authSession = $authSession;
5872
$this->appState = $appState;
5973
$this->config = $config;
74+
75+
$this->nonceProvider = $nonceProvider ?: ObjectManager::getInstance()->get(CspNonceProvider::class);
76+
77+
$this->nonce = $this->nonceProvider->generateNonce();
6078
}
6179

6280
/**
@@ -156,4 +174,14 @@ public function getCurrentUserRoleName(): string
156174
{
157175
return $this->authSession->getUser()->getRole()->getRoleName();
158176
}
177+
178+
/**
179+
* Get a random nonce for each request.
180+
*
181+
* @return string
182+
*/
183+
public function getNonce(): string
184+
{
185+
return $this->nonce;
186+
}
159187
}

app/code/Magento/AdminAnalytics/composer.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
"sort-packages": true
66
},
77
"require": {
8-
"php": "~8.1.0||~8.2.0",
8+
"php": "~8.1.0||~8.2.0||~8.3.0",
99
"magento/framework": "*",
1010
"magento/module-backend": "*",
1111
"magento/module-config": "*",
1212
"magento/module-store": "*",
1313
"magento/module-ui": "*",
14-
"magento/module-release-notification": "*"
14+
"magento/module-release-notification": "*",
15+
"magento/module-csp": "*"
1516
},
1617
"type": "magento2-module",
1718
"license": [

app/code/Magento/AdminAnalytics/view/adminhtml/templates/tracking.phtml

+17-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/**
88
* @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
9+
* @var \Magento\Framework\Escaper $escaper
910
*/
1011
?>
1112

@@ -22,18 +23,25 @@
2223
<?php
2324
/** @var \Magento\AdminAnalytics\ViewModel\Metadata $metadata */
2425
$metadata = $block->getMetadata();
26+
$nonce = $escaper->escapeJs($metadata->getNonce());
2527
$scriptString = '
2628
var adminAnalyticsMetadata = {
27-
"secure_base_url": "' . $block->escapeJs($metadata->getSecureBaseUrlForScope()) . '",
28-
"version": "' . $block->escapeJs($metadata->getMagentoVersion()) . '",
29-
"product_edition": "' . $block->escapeJs($metadata->getProductEdition()) . '",
30-
"user": "' . $block->escapeJs($metadata->getCurrentUser()) . '",
31-
"mode": "' . $block->escapeJs($metadata->getMode()) . '",
32-
"store_name_default": "' . $block->escapeJs($metadata->getStoreNameForScope()) . '",
33-
"admin_user_created": "' . $block->escapeJs($metadata->getCurrentUserCreatedDate()) . '",
34-
"admin_user_logdate": "' . $block->escapeJs($metadata->getCurrentUserLogDate()) . '",
35-
"admin_user_role_name": "' . $block->escapeJs($metadata->getCurrentUserRoleName()) . '"
29+
"secure_base_url": "' . $escaper->escapeJs($metadata->getSecureBaseUrlForScope()) . '",
30+
"version": "' . $escaper->escapeJs($metadata->getMagentoVersion()) . '",
31+
"product_edition": "' . $escaper->escapeJs($metadata->getProductEdition()) . '",
32+
"user": "' . $escaper->escapeJs($metadata->getCurrentUser()) . '",
33+
"mode": "' . $escaper->escapeJs($metadata->getMode()) . '",
34+
"store_name_default": "' . $escaper->escapeJs($metadata->getStoreNameForScope()) . '",
35+
"admin_user_created": "' . $escaper->escapeJs($metadata->getCurrentUserCreatedDate()) . '",
36+
"admin_user_logdate": "' . $escaper->escapeJs($metadata->getCurrentUserLogDate()) . '",
37+
"admin_user_role_name": "' . $escaper->escapeJs($metadata->getCurrentUserRoleName()) . '"
3638
};
39+
40+
var digitalData = {
41+
"nonce": "' . $nonce . '"
42+
};
43+
44+
var cspNonce = "' . $nonce . '";
3745
';
3846
?>
3947
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>

app/code/Magento/AdminNotification/Test/Unit/Block/Grid/Renderer/SeverityTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function testShouldRenderSeverity() : void
4646
/** @var Column|MockObject $columnMock */
4747
$columnMock = $this->getMockBuilder(Column::class)
4848
->disableOriginalConstructor()
49-
->setMethods(['getIndex'])
49+
->addMethods(['getIndex'])
5050
->getMock();
5151
$columnMock->expects($this->exactly(5))->method('getIndex')->willReturn('index');
5252
$this->sut->setColumn($columnMock);

app/code/Magento/AdminNotification/Test/Unit/Block/ToolbarEntryTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
use Magento\AdminNotification\Block\ToolbarEntry;
1414
use Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Unread;
15+
use Magento\Directory\Helper\Data as DirectoryHelper;
16+
use Magento\Framework\Json\Helper\Data as JsonHelper;
1517
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1618
use PHPUnit\Framework\TestCase;
1719

@@ -26,6 +28,17 @@ class ToolbarEntryTest extends TestCase
2628
protected function _getBlockInstance($unreadNotifications)
2729
{
2830
$objectManagerHelper = new ObjectManager($this);
31+
$objects = [
32+
[
33+
JsonHelper::class,
34+
$this->createMock(JsonHelper::class)
35+
],
36+
[
37+
DirectoryHelper::class,
38+
$this->createMock(DirectoryHelper::class)
39+
]
40+
];
41+
$objectManagerHelper->prepareObjectManager($objects);
2942
// mock collection of unread notifications
3043
$notificationList = $this->createPartialMock(
3144
Unread::class,
@@ -52,6 +65,18 @@ public function testGetLatestUnreadNotifications()
5265
{
5366
$helper = new ObjectManager($this);
5467

68+
$objects = [
69+
[
70+
JsonHelper::class,
71+
$this->createMock(JsonHelper::class)
72+
],
73+
[
74+
DirectoryHelper::class,
75+
$this->createMock(DirectoryHelper::class)
76+
]
77+
];
78+
$helper->prepareObjectManager($objects);
79+
5580
// 1. Create mocks
5681
$notificationList = $this->createMock(Unread::class);
5782

app/code/Magento/AdminNotification/Test/Unit/Observer/PredispatchAdminActionControllerObserverTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@ protected function setUp(): void
6868

6969
$this->backendAuthSessionMock = $this->getMockBuilder(Session::class)
7070
->disableOriginalConstructor()
71-
->setMethods(['isLoggedIn'])
71+
->onlyMethods(['isLoggedIn'])
7272
->getMock();
7373

7474
$this->feedMock = $this->getMockBuilder(Feed::class)
7575
->disableOriginalConstructor()
76-
->setMethods(['checkUpdate'])
76+
->onlyMethods(['checkUpdate'])
7777
->getMock();
7878

7979
$this->feedFactoryMock = $this->getMockBuilder(FeedFactory::class)
8080
->disableOriginalConstructor()
81-
->setMethods(['create'])
81+
->onlyMethods(['create'])
8282
->getMock();
8383

8484
$this->observer = $this->objectManager->getObject(

0 commit comments

Comments
 (0)