Skip to content

Commit

Permalink
Merge branch '2.4-develop' into fix-for-issue-38059
Browse files Browse the repository at this point in the history
  • Loading branch information
engcom-Bravo authored May 14, 2024
2 parents 6643e15 + 49cc612 commit 0ed44a8
Show file tree
Hide file tree
Showing 2,506 changed files with 56,630 additions and 27,458 deletions.
12 changes: 6 additions & 6 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

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.
Expand All @@ -19,11 +19,11 @@ For more detailed information on contribution please read our [beginners guide](
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.
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.
4. PRs which include bug fixes must be accompanied with a step-by-step description of how to reproduce the bug.
3. PRs which include new logic or new features must be submitted along with:
* Unit/integration test coverage
* Proposed [documentation](https://devdocs.magento.com) updates. Documentation contributions can be submitted via the [devdocs GitHub](https://github.com/magento/devdocs).
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.
5. All automated tests must pass.
5. PRs which include new logic or new features must be submitted along with:
* Unit/integration test coverage
* 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.
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.
7. All automated tests must pass.

## Contribution process

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ However, for those who need a full-featured eCommerce solution, we recommend [Ad

## Contribute

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.
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.

- [Contribute to the code](https://developer.adobe.com/commerce/contributor/guides/code-contributions/)
- [Report an issue](https://developer.adobe.com/commerce/contributor/guides/code-contributions/#report)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private function markUserNotified(): ResultInterface
public function execute()
{
$this->enableAdminUsage();
$this->markUserNotified();
return $this->markUserNotified();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CloseAllDialogBoxes
SelectAdminUsageSetting
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdminAnalytics\Test\Unit\Controller\Adminhtml\Config;

use Magento\AdminAnalytics\Controller\Adminhtml\Config\EnableAdminUsage;
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger as NotificationLogger;
use Magento\Config\Model\Config;
use Magento\Config\Model\Config\Factory as ConfigFactory;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\Controller\Result\Json as JsonResult;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\MockObject\MockObject;

/**
* @covers \Magento\AdminAnalytics\Controller\Adminhtml\Config\EnableAdminUsage
*/
class EnableAdminUsageTest extends \PHPUnit\Framework\TestCase
{
private const STUB_PRODUCT_VERSION = 'Product Version';

/** @var EnableAdminUsage */
private $controller;

/** @var MockObject|Config */
private $configMock;

/** @var MockObject|ProductMetadataInterface */
private $productMetadataMock;

/** @var MockObject|NotificationLogger */
private $notificationLoggerMock;

/** @var MockObject|ResultFactory */
private $resultFactoryMock;

/** @var JsonResult|MockObject */
private $resultMock;

protected function setUp(): void
{
$objectManager = new ObjectManager($this);

$this->configMock = $this->getMockBuilder(Config::class)
->disableOriginalConstructor()
->onlyMethods(['setDataByPath', 'save'])
->getMock();

$configFactory = $this->getMockBuilder(ConfigFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->getMock();

$configFactory->method('create')
->willReturn($this->configMock);

$this->productMetadataMock = $this->getMockBuilder(ProductMetadataInterface::class)
->onlyMethods(['getVersion'])
->getMockForAbstractClass();

$this->productMetadataMock->method('getVersion')
->willReturn(self::STUB_PRODUCT_VERSION);

$this->notificationLoggerMock = $this->getMockBuilder(NotificationLogger::class)
->disableOriginalConstructor()
->onlyMethods(['log'])
->getMock();

$this->resultFactoryMock = $this->getMockBuilder(ResultFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->getMock();

$this->resultMock = $this->getMockBuilder(JsonResult::class)
->disableOriginalConstructor()
->onlyMethods(['setData'])
->getMock();

$this->resultFactoryMock->method('create')
->with(ResultFactory::TYPE_JSON)
->willReturn($this->resultMock);

$this->controller = $objectManager->getObject(EnableAdminUsage::class, [
'configFactory' => $configFactory,
'productMetadata' => $this->productMetadataMock,
'notificationLogger' => $this->notificationLoggerMock,
'resultFactory' => $this->resultFactoryMock
]);
}

/**
* If Controller returns `null`, no data is passed to the browser
*/
public function testResponseAfterAdminUsageChange()
{
// Given
$this->resultMock->method('setData')->willReturnSelf();

// When
$response = $this->controller->execute();

// Then
$this->assertInstanceOf(ResultInterface::class, $response);
}

public function testResponseWhenExceptionThrown()
{
$this->markTestSkipped('magento/magento2#31393 Lack of exception handling');

$this->configMock->method('setDataByPath')
->willThrowException(
new \Exception('System Exception')
);

// When
$response = $this->controller->execute();

// Then
$this->assertInstanceOf(ResultInterface::class, $response);
}
}
30 changes: 29 additions & 1 deletion app/code/Magento/AdminAnalytics/ViewModel/Metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
namespace Magento\AdminAnalytics\ViewModel;

use Magento\Config\Model\Config\Backend\Admin\Custom;
use Magento\Csp\Helper\CspNonceProvider;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Backend\Model\Auth\Session;
use Magento\Framework\App\State;
Expand All @@ -21,6 +23,11 @@
*/
class Metadata implements ArgumentInterface
{
/**
* @var string
*/
private $nonce;

/**
* @var State
*/
Expand All @@ -41,22 +48,33 @@ class Metadata implements ArgumentInterface
*/
private $config;

/**
* @var CspNonceProvider
*/
private $nonceProvider;

/**
* @param ProductMetadataInterface $productMetadata
* @param Session $authSession
* @param State $appState
* @param ScopeConfigInterface $config
* @param CspNonceProvider|null $nonceProvider
*/
public function __construct(
ProductMetadataInterface $productMetadata,
Session $authSession,
State $appState,
ScopeConfigInterface $config
ScopeConfigInterface $config,
CspNonceProvider $nonceProvider = null
) {
$this->productMetadata = $productMetadata;
$this->authSession = $authSession;
$this->appState = $appState;
$this->config = $config;

$this->nonceProvider = $nonceProvider ?: ObjectManager::getInstance()->get(CspNonceProvider::class);

$this->nonce = $this->nonceProvider->generateNonce();
}

/**
Expand Down Expand Up @@ -156,4 +174,14 @@ public function getCurrentUserRoleName(): string
{
return $this->authSession->getUser()->getRole()->getRoleName();
}

/**
* Get a random nonce for each request.
*
* @return string
*/
public function getNonce(): string
{
return $this->nonce;
}
}
5 changes: 3 additions & 2 deletions app/code/Magento/AdminAnalytics/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
"sort-packages": true
},
"require": {
"php": "~8.1.0||~8.2.0",
"php": "~8.1.0||~8.2.0||~8.3.0",
"magento/framework": "*",
"magento/module-backend": "*",
"magento/module-config": "*",
"magento/module-store": "*",
"magento/module-ui": "*",
"magento/module-release-notification": "*"
"magento/module-release-notification": "*",
"magento/module-csp": "*"
},
"type": "magento2-module",
"license": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

/**
* @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
* @var \Magento\Framework\Escaper $escaper
*/
?>

Expand All @@ -22,18 +23,25 @@
<?php
/** @var \Magento\AdminAnalytics\ViewModel\Metadata $metadata */
$metadata = $block->getMetadata();
$nonce = $escaper->escapeJs($metadata->getNonce());
$scriptString = '
var adminAnalyticsMetadata = {
"secure_base_url": "' . $block->escapeJs($metadata->getSecureBaseUrlForScope()) . '",
"version": "' . $block->escapeJs($metadata->getMagentoVersion()) . '",
"product_edition": "' . $block->escapeJs($metadata->getProductEdition()) . '",
"user": "' . $block->escapeJs($metadata->getCurrentUser()) . '",
"mode": "' . $block->escapeJs($metadata->getMode()) . '",
"store_name_default": "' . $block->escapeJs($metadata->getStoreNameForScope()) . '",
"admin_user_created": "' . $block->escapeJs($metadata->getCurrentUserCreatedDate()) . '",
"admin_user_logdate": "' . $block->escapeJs($metadata->getCurrentUserLogDate()) . '",
"admin_user_role_name": "' . $block->escapeJs($metadata->getCurrentUserRoleName()) . '"
"secure_base_url": "' . $escaper->escapeJs($metadata->getSecureBaseUrlForScope()) . '",
"version": "' . $escaper->escapeJs($metadata->getMagentoVersion()) . '",
"product_edition": "' . $escaper->escapeJs($metadata->getProductEdition()) . '",
"user": "' . $escaper->escapeJs($metadata->getCurrentUser()) . '",
"mode": "' . $escaper->escapeJs($metadata->getMode()) . '",
"store_name_default": "' . $escaper->escapeJs($metadata->getStoreNameForScope()) . '",
"admin_user_created": "' . $escaper->escapeJs($metadata->getCurrentUserCreatedDate()) . '",
"admin_user_logdate": "' . $escaper->escapeJs($metadata->getCurrentUserLogDate()) . '",
"admin_user_role_name": "' . $escaper->escapeJs($metadata->getCurrentUserRoleName()) . '"
};
var digitalData = {
"nonce": "' . $nonce . '"
};
var cspNonce = "' . $nonce . '";
';
?>
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function testShouldRenderSeverity() : void
/** @var Column|MockObject $columnMock */
$columnMock = $this->getMockBuilder(Column::class)
->disableOriginalConstructor()
->setMethods(['getIndex'])
->addMethods(['getIndex'])
->getMock();
$columnMock->expects($this->exactly(5))->method('getIndex')->willReturn('index');
$this->sut->setColumn($columnMock);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

use Magento\AdminNotification\Block\ToolbarEntry;
use Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Unread;
use Magento\Directory\Helper\Data as DirectoryHelper;
use Magento\Framework\Json\Helper\Data as JsonHelper;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\TestCase;

Expand All @@ -26,6 +28,17 @@ class ToolbarEntryTest extends TestCase
protected function _getBlockInstance($unreadNotifications)
{
$objectManagerHelper = new ObjectManager($this);
$objects = [
[
JsonHelper::class,
$this->createMock(JsonHelper::class)
],
[
DirectoryHelper::class,
$this->createMock(DirectoryHelper::class)
]
];
$objectManagerHelper->prepareObjectManager($objects);
// mock collection of unread notifications
$notificationList = $this->createPartialMock(
Unread::class,
Expand All @@ -52,6 +65,18 @@ public function testGetLatestUnreadNotifications()
{
$helper = new ObjectManager($this);

$objects = [
[
JsonHelper::class,
$this->createMock(JsonHelper::class)
],
[
DirectoryHelper::class,
$this->createMock(DirectoryHelper::class)
]
];
$helper->prepareObjectManager($objects);

// 1. Create mocks
$notificationList = $this->createMock(Unread::class);

Expand Down
2 changes: 1 addition & 1 deletion app/code/Magento/AdminNotification/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"sort-packages": true
},
"require": {
"php": "~8.1.0||~8.2.0",
"php": "~8.1.0||~8.2.0||~8.3.0",
"lib-libxml": "*",
"magento/framework": "*",
"magento/module-backend": "*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,15 @@ protected function setUp(): void
'initWebsites',
'initCategories'
];
$mockAddMethods = [
'_headerColumns'
];
$mockMethods = array_merge($constructorMethods, [
'_customHeadersMapping',
'_prepareEntityCollection',
'_getEntityCollection',
'getWriter',
'getExportData',
'_headerColumns',
'_customFieldsMapping',
'getItemsPerPage',
'paginateCollection',
Expand All @@ -243,7 +245,8 @@ protected function setUp(): void
$this->advancedPricing = $this->getMockBuilder(
AdvancedPricing::class
)
->setMethods($mockMethods)
->addMethods($mockAddMethods)
->onlyMethods($mockMethods)
->disableOriginalConstructor()
->getMock();
foreach ($constructorMethods as $method) {
Expand Down
Loading

0 comments on commit 0ed44a8

Please sign in to comment.