Skip to content

Commit b8c2e7e

Browse files
Merge branch '2.4-develop' into 2.4.8-graphql-api-enhancements
2 parents e1d238a + ba1598a commit b8c2e7e

File tree

101 files changed

+1028
-779
lines changed

Some content is hidden

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

101 files changed

+1028
-779
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\AdminNotification\Block\Grid\MassAction;
9+
10+
use Magento\AdminNotification\Controller\Adminhtml\Notification\MarkAsRead;
11+
use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface;
12+
use Magento\Framework\AuthorizationInterface;
13+
14+
/**
15+
* Class checks if mark as read action can be displayed on massaction list
16+
*/
17+
class MarkAsReadVisibility implements VisibilityCheckerInterface
18+
{
19+
/**
20+
* @var AuthorizationInterface
21+
*/
22+
private $authorization;
23+
24+
/**
25+
* @param AuthorizationInterface $authorizationInterface
26+
*/
27+
public function __construct(AuthorizationInterface $authorizationInterface)
28+
{
29+
$this->authorization = $authorizationInterface;
30+
}
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function isVisible()
36+
{
37+
return $this->authorization->isAllowed(MarkAsRead::ADMIN_RESOURCE);
38+
}
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\AdminNotification\Block\Grid\MassAction;
9+
10+
use Magento\AdminNotification\Controller\Adminhtml\Notification\Remove;
11+
use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface;
12+
use Magento\Framework\AuthorizationInterface;
13+
14+
/**
15+
* Class checks if remove action can be displayed on massaction list
16+
*/
17+
class RemoveVisibility implements VisibilityCheckerInterface
18+
{
19+
/**
20+
* @var AuthorizationInterface
21+
*/
22+
private $authorization;
23+
24+
/**
25+
* @param AuthorizationInterface $authorizationInterface
26+
*/
27+
public function __construct(AuthorizationInterface $authorizationInterface)
28+
{
29+
$this->authorization = $authorizationInterface;
30+
}
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function isVisible()
36+
{
37+
return $this->authorization->isAllowed(Remove::ADMIN_RESOURCE);
38+
}
39+
}

app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<?php
2-
declare(strict_types=1);
3-
42
/**
5-
* Adminhtml AdminNotification Severity Renderer
6-
*
73
* Copyright © Magento, Inc. All rights reserved.
84
* See COPYING.txt for license details.
95
*/
6+
declare(strict_types=1);
107

118
namespace Magento\AdminNotification\Block\Grid\Renderer;
129

10+
use Magento\AdminNotification\Controller\Adminhtml\Notification\MarkAsRead;
11+
use Magento\AdminNotification\Controller\Adminhtml\Notification\Remove;
1312
use Magento\Backend\Block\Context;
1413
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
1514
use Magento\Framework\App\ActionInterface;
@@ -45,33 +44,41 @@ public function __construct(Context $context, Data $urlHelper, array $data = [])
4544
*/
4645
public function render(DataObject $row)
4746
{
48-
$readDetailsHtml = $row->getUrl() ? '<a class="action-details" target="_blank" href="' .
47+
$readDetailsHtml = $row->getUrl() ?
48+
'<a class="action-details" target="_blank" href="' .
4949
$this->escapeUrl($row->getUrl())
5050
. '">' .
5151
__('Read Details') . '</a>' : '';
5252

53-
$markAsReadHtml = !$row->getIsRead() ? '<a class="action-mark" href="' . $this->getUrl(
54-
'*/*/markAsRead/',
55-
['_current' => true, 'id' => $row->getNotificationId()]
56-
) . '">' . __(
57-
'Mark as Read'
58-
) . '</a>' : '';
53+
$markAsReadHtml = !$row->getIsRead()
54+
&& $this->_authorization->isAllowed(MarkAsRead::ADMIN_RESOURCE) ?
55+
'<a class="action-mark" href="' . $this->escapeUrl($this->getUrl(
56+
'*/*/markAsRead/',
57+
['_current' => true, 'id' => $row->getNotificationId()]
58+
)) . '">' . __(
59+
'Mark as Read'
60+
) . '</a>' : '';
61+
62+
$removeUrl = $this->getUrl(
63+
'*/*/remove/',
64+
[
65+
'_current' => true,
66+
'id' => $row->getNotificationId(),
67+
ActionInterface::PARAM_NAME_URL_ENCODED => $this->_urlHelper->getEncodedUrl()
68+
]
69+
);
70+
71+
$removeHtml = $this->_authorization->isAllowed(Remove::ADMIN_RESOURCE) ?
72+
'<a class="action-delete" href="'
73+
. $this->escapeUrl($removeUrl)
74+
.'" onClick="deleteConfirm('. __('\'Are you sure?\'') .', this.href); return false;">'
75+
. __('Remove') . '</a>' : '';
5976

60-
$encodedUrl = $this->_urlHelper->getEncodedUrl();
6177
return sprintf(
62-
'%s%s<a class="action-delete" href="%s" onClick="deleteConfirm(\'%s\', this.href); return false;">%s</a>',
78+
'%s%s%s',
6379
$readDetailsHtml,
6480
$markAsReadHtml,
65-
$this->getUrl(
66-
'*/*/remove/',
67-
[
68-
'_current' => true,
69-
'id' => $row->getNotificationId(),
70-
ActionInterface::PARAM_NAME_URL_ENCODED => $encodedUrl
71-
]
72-
),
73-
__('Are you sure?'),
74-
__('Remove')
81+
$removeHtml,
7582
);
7683
}
7784
}

app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/AjaxMarkAsRead.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
79

810
use Magento\AdminNotification\Controller\Adminhtml\Notification;
@@ -16,6 +18,13 @@
1618
*/
1719
class AjaxMarkAsRead extends Notification implements HttpPostActionInterface
1820
{
21+
/**
22+
* Authorization level of a basic admin session
23+
*
24+
* @see _isAllowed()
25+
*/
26+
public const ADMIN_RESOURCE = 'Magento_AdminNotification::mark_as_read';
27+
1928
/**
2029
* @var NotificationService
2130
*/

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Magento\AdminNotification\Block\Grid\Renderer\Actions;
1616
use Magento\Backend\Block\Context;
1717
use Magento\Framework\DataObject;
18+
use Magento\Framework\AuthorizationInterface;
1819
use Magento\Framework\Escaper;
1920
use Magento\Framework\Url\Helper\Data;
2021
use Magento\Framework\UrlInterface;
@@ -35,16 +36,23 @@ protected function setUp(): void
3536

3637
/** @var Escaper|MockObject $escaperMock */
3738
$escaperMock = $this->createMock(Escaper::class);
38-
$escaperMock->expects($this->once())->method('escapeUrl')->willReturn('https://magento.com');
39+
$escaperMock->expects($this->atLeastOnce())->method('escapeUrl')->willReturn('https://magento.com');
40+
41+
/** @var AuthorizationInterface|MockObject $authorizationMock */
42+
$authorizationMock = $this->getMockForAbstractClass(AuthorizationInterface::class);
43+
$authorizationMock->expects($this->atLeastOnce())
44+
->method('isAllowed')
45+
->willReturn(true);
3946

4047
/** @var UrlInterface|MockObject $urlBuilder */
4148
$urlBuilder = $this->getMockForAbstractClass(UrlInterface::class);
4249
$urlBuilder->expects($this->once())->method('getUrl')->willReturn('http://magento.com');
4350

4451
/** @var Context|MockObject $contextMock */
4552
$contextMock = $this->createMock(Context::class);
46-
$contextMock->expects($this->once())->method('getEscaper')->willReturn($escaperMock);
53+
$contextMock->expects($this->atLeastOnce())->method('getEscaper')->willReturn($escaperMock);
4754
$contextMock->expects($this->once())->method('getUrlBuilder')->willReturn($urlBuilder);
55+
$contextMock->expects($this->once())->method('getAuthorization')->willReturn($authorizationMock);
4856

4957
/** @var Data|MockObject $urlHelperMock */
5058
$urlHelperMock = $this->createMock(Data::class);
@@ -65,7 +73,7 @@ public function testShouldRenderMessageWhenUrlIsGiven() : void
6573
// Ignoring Code Style at this point due to the long HEREDOC
6674
// phpcs:disable
6775
$expected = <<<HTML
68-
<a class="action-details" target="_blank" href="https://magento.com">Read Details</a><a class="action-delete" href="http://magento.com" onClick="deleteConfirm('Are you sure?', this.href); return false;">Remove</a>
76+
<a class="action-details" target="_blank" href="https://magento.com">Read Details</a><a class="action-delete" href="https://magento.com" onClick="deleteConfirm('Are you sure?', this.href); return false;">Remove</a>
6977
HTML;
7078
// phpcs:enable
7179

app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_block.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@
6161
<item name="mark_as_read" xsi:type="array">
6262
<item name="label" xsi:type="string" translate="true">Mark as Read</item>
6363
<item name="url" xsi:type="string">*/*/massMarkAsRead</item>
64+
<item name="visible" xsi:type="object">Magento\AdminNotification\Block\Grid\MassAction\MarkAsReadVisibility</item>
6465
</item>
6566
<item name="remove" xsi:type="array">
6667
<item name="label" xsi:type="string" translate="true">Remove</item>
6768
<item name="url" xsi:type="string">*/*/massRemove</item>
6869
<item name="confirm" xsi:type="string" translate="true">Are you sure?</item>
70+
<item name="visible" xsi:type="object">Magento\AdminNotification\Block\Grid\MassAction\RemoveVisibility</item>
6971
</item>
7072
</argument>
7173
</arguments>

app/code/Magento/AdvancedSearch/Controller/Adminhtml/Search/System/Config/TestConnection.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,27 @@
44
* Copyright © Magento, Inc. All rights reserved.
55
* See COPYING.txt for license details.
66
*/
7+
declare(strict_types=1);
8+
79
namespace Magento\AdvancedSearch\Controller\Adminhtml\Search\System\Config;
810

911
use Magento\Backend\App\Action;
1012
use Magento\Backend\App\Action\Context;
1113
use Magento\AdvancedSearch\Model\Client\ClientResolver;
14+
use Magento\Framework\App\Action\HttpPostActionInterface;
15+
use Magento\Framework\Controller\Result\Json;
1216
use Magento\Framework\Controller\Result\JsonFactory;
17+
use Magento\Framework\Exception\LocalizedException;
1318
use Magento\Framework\Filter\StripTags;
1419

15-
class TestConnection extends Action
20+
class TestConnection extends Action implements HttpPostActionInterface
1621
{
1722
/**
1823
* Authorization level of a basic admin session.
1924
*
2025
* @see _isAllowed()
2126
*/
22-
const ADMIN_RESOURCE = 'Magento_CatalogSearch::config_catalog_search';
27+
public const ADMIN_RESOURCE = 'Magento_Catalog::config_catalog';
2328

2429
/**
2530
* @var ClientResolver
@@ -57,7 +62,7 @@ public function __construct(
5762
/**
5863
* Check for connection to server
5964
*
60-
* @return \Magento\Framework\Controller\Result\Json
65+
* @return Json
6166
*/
6267
public function execute()
6368
{
@@ -69,22 +74,22 @@ public function execute()
6974

7075
try {
7176
if (empty($options['engine'])) {
72-
throw new \Magento\Framework\Exception\LocalizedException(
77+
throw new LocalizedException(
7378
__('Missing search engine parameter.')
7479
);
7580
}
7681
$response = $this->clientResolver->create($options['engine'], $options)->testConnection();
7782
if ($response) {
7883
$result['success'] = true;
7984
}
80-
} catch (\Magento\Framework\Exception\LocalizedException $e) {
85+
} catch (LocalizedException $e) {
8186
$result['errorMessage'] = $e->getMessage();
8287
} catch (\Exception $e) {
8388
$message = __($e->getMessage());
8489
$result['errorMessage'] = $this->tagFilter->filter($message);
8590
}
8691

87-
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
92+
/** @var Json $resultJson */
8893
$resultJson = $this->resultJsonFactory->create();
8994
return $resultJson->setData($result);
9095
}

app/code/Magento/Backend/Controller/Adminhtml/System/Design.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ abstract class Design extends Action
1414
*
1515
* @see _isAllowed()
1616
*/
17-
const ADMIN_RESOURCE = 'Magento_Backend::design';
17+
public const ADMIN_RESOURCE = 'Magento_Backend::schedule';
1818

1919
/**
20-
* Core registry
20+
* Core registry instance
2121
*
2222
* @var \Magento\Framework\Registry
2323
*/

app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ValidatorInfo extends Validator
4949
* @var IoFile
5050
*/
5151
private $ioFile;
52+
5253
/**
5354
* @var NotProtectedExtension
5455
*/
@@ -147,12 +148,14 @@ private function validatePath(array $optionValuePath): bool
147148
{
148149
foreach ([$optionValuePath['quote_path'], $optionValuePath['order_path']] as $path) {
149150
$pathInfo = $this->ioFile->getPathInfo($path);
150-
if (isset($pathInfo['extension'])) {
151-
if (!$this->fileValidator->isValid($pathInfo['extension'])) {
152-
return false;
153-
}
151+
152+
if (isset($pathInfo['extension'])
153+
&& (empty($pathInfo['extension']) || !$this->fileValidator->isValid($pathInfo['extension']))
154+
) {
155+
return false;
154156
}
155157
}
158+
156159
return true;
157160
}
158161

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class Product extends AbstractEntity
5656
private const COL_NAME_FORMAT = '/[\x00-\x1F\x7F]/';
5757
public const CONFIG_KEY_PRODUCT_TYPES = 'global/importexport/import_product_types';
5858

59+
/**
60+
* Filter chain const
61+
*/
62+
private const FILTER_CHAIN = "php://filter";
63+
5964
/**
6065
* Size of bunch - part of products to save in one step.
6166
*/
@@ -775,6 +780,11 @@ class Product extends AbstractEntity
775780
*/
776781
private ?SkuStorage $skuStorage;
777782

783+
/**
784+
* @var File|null
785+
*/
786+
private ?File $fileDriver;
787+
778788
/**
779789
* @param \Magento\Framework\Json\Helper\Data $jsonHelper
780790
* @param \Magento\ImportExport\Helper\Data $importExportData
@@ -950,6 +960,8 @@ public function __construct(
950960
->get(ProductRepositoryInterface::class);
951961
$this->stockItemProcessor = $stockItemProcessor ?? ObjectManager::getInstance()
952962
->get(StockItemProcessorInterface::class);
963+
$this->fileDriver = $fileDriver ?? ObjectManager::getInstance()
964+
->get(File::class);
953965
}
954966

955967
/**
@@ -2126,7 +2138,10 @@ private function getRemoteFileContent(string $filename): string
21262138
{
21272139
try {
21282140
// phpcs:ignore Magento2.Functions.DiscouragedFunction
2129-
$content = file_get_contents($filename);
2141+
if (stripos($filename, self::FILTER_CHAIN) !== false) {
2142+
return '';
2143+
}
2144+
$content = $this->fileDriver->fileGetContents($filename);
21302145
} catch (\Exception $e) {
21312146
$content = false;
21322147
}

0 commit comments

Comments
 (0)