Skip to content

Commit d103017

Browse files
authored
Merge branch '2.4-develop' into 2.4-develop-express-lane-prs
2 parents 4005ad3 + 5f76c92 commit d103017

File tree

74 files changed

+5323
-2262
lines changed

Some content is hidden

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

74 files changed

+5323
-2262
lines changed

app/code/Magento/AwsS3/Driver/AwsS3.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* Driver for AWS S3 IO operations.
2626
*
2727
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
28+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2829
*/
2930
class AwsS3 implements RemoteDriverInterface
3031
{
@@ -258,6 +259,7 @@ public function filePutContents($path, $content, $mode = null): int
258259
$path = $this->normalizeRelativePath($path, true);
259260
$config = self::CONFIG;
260261

262+
// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
261263
if (false !== ($imageSize = @getimagesizefromstring($content))) {
262264
$config['Metadata'] = [
263265
'image-width' => $imageSize[0],
@@ -295,19 +297,20 @@ public function readDirectory($path): array
295297
*/
296298
public function getRealPathSafety($path)
297299
{
300+
//Removing redundant directory separators
301+
$path = preg_replace(
302+
'~(?<!:)\/\/+~',
303+
'/',
304+
$path
305+
);
306+
298307
if (strpos($path, '/.') === false) {
299308
return $path;
300309
}
301310

302311
$isAbsolute = strpos($path, $this->normalizeAbsolutePath('')) === 0;
303312
$path = $this->normalizeRelativePath($path);
304313

305-
//Removing redundant directory separators.
306-
$path = preg_replace(
307-
'/\\/\\/+/',
308-
'/',
309-
$path
310-
);
311314
$pathParts = explode('/', $path);
312315
if (end($pathParts) === '.') {
313316
$pathParts[count($pathParts) - 1] = '';
@@ -488,8 +491,7 @@ public function getRelativePath($basePath, $path = null): string
488491
$basePath = (string)$basePath;
489492
$path = (string)$path;
490493

491-
if (
492-
($basePath && $path)
494+
if ($basePath && $path
493495
&& ($basePath === $path . '/' || strpos($path, $basePath) === 0)
494496
) {
495497
$result = substr($path, strlen($basePath));
@@ -722,6 +724,7 @@ public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure
722724
*/
723725
public function fileTell($resource): int
724726
{
727+
// phpcs:ignore Magento2.Functions.DiscouragedFunction, Generic.PHP.NoSilencedErrors.Discouraged
725728
$result = @ftell($resource);
726729
if ($result === null) {
727730
throw new FileSystemException(
@@ -737,6 +740,7 @@ public function fileTell($resource): int
737740
*/
738741
public function fileSeek($resource, $offset, $whence = SEEK_SET): int
739742
{
743+
// phpcs:ignore Magento2.Functions.DiscouragedFunction, Generic.PHP.NoSilencedErrors.Discouraged
740744
$result = @fseek($resource, $offset, $whence);
741745
if ($result === -1) {
742746
throw new FileSystemException(
@@ -755,6 +759,7 @@ public function fileSeek($resource, $offset, $whence = SEEK_SET): int
755759
*/
756760
public function endOfFile($resource): bool
757761
{
762+
// phpcs:ignore Magento2.Functions.DiscouragedFunction.DiscouragedWithAlternative
758763
return feof($resource);
759764
}
760765

@@ -772,6 +777,7 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure
772777
*/
773778
public function fileFlush($resource): bool
774779
{
780+
// phpcs:ignore Magento2.Functions.DiscouragedFunction, Generic.PHP.NoSilencedErrors.Discouraged
775781
$result = @fflush($resource);
776782
if (!$result) {
777783
throw new FileSystemException(
@@ -790,6 +796,7 @@ public function fileFlush($resource): bool
790796
*/
791797
public function fileLock($resource, $lockMode = LOCK_EX): bool
792798
{
799+
// phpcs:ignore Magento2.Functions.DiscouragedFunction, Generic.PHP.NoSilencedErrors.Discouraged
793800
$result = @flock($resource, $lockMode);
794801
if (!$result) {
795802
throw new FileSystemException(
@@ -808,6 +815,7 @@ public function fileLock($resource, $lockMode = LOCK_EX): bool
808815
*/
809816
public function fileUnlock($resource): bool
810817
{
818+
// phpcs:ignore Magento2.Functions.DiscouragedFunction, Generic.PHP.NoSilencedErrors.Discouraged
811819
$result = @flock($resource, LOCK_UN);
812820
if (!$result) {
813821
throw new FileSystemException(
@@ -851,13 +859,14 @@ public function fileClose($resource): bool
851859
//phpcs:enable
852860

853861
foreach ($this->streams as $path => $stream) {
854-
// phpcs:ignore Magento2.Functions.DiscouragedFunction
862+
// phpcs:ignore
855863
if (stream_get_meta_data($stream)['uri'] === $resourcePath) {
856864
$this->adapter->writeStream($path, $resource, new Config(self::CONFIG));
857865

858866
// Remove path from streams after
859867
unset($this->streams[$path]);
860868

869+
// phpcs:ignore Magento2.Functions.DiscouragedFunction.DiscouragedWithAlternative
861870
return fclose($stream);
862871
}
863872
}
@@ -931,6 +940,7 @@ private function readPath(string $path, $isRecursive = false): array
931940
if (!empty($path)
932941
&& $path !== $relativePath
933942
&& (!$relativePath || strpos($path, $relativePath) === 0)) {
943+
//phpcs:ignore Magento2.Functions.DiscouragedFunction
934944
$itemsList[] = $this->getAbsolutePath(dirname($path), $path);
935945
}
936946
}

app/code/Magento/AwsS3/Test/Unit/Driver/AwsS3Test.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public function testGetAbsolutePath($basePath, $path, string $expected): void
6464

6565
/**
6666
* @return array
67+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
6768
*/
6869
public function getAbsolutePathDataProvider(): array
6970
{
@@ -407,6 +408,18 @@ public function getRealPathSafetyDataProvider(): array
407408
[
408409
'test/test/../test.txt',
409410
'test/test.txt'
411+
],
412+
[
413+
'test//test/../test.txt',
414+
'test/test.txt'
415+
],
416+
[
417+
'test1///test2/..//test3//test.txt',
418+
'test1/test3/test.txt'
419+
],
420+
[
421+
self::URL . '/test1///test2/..//test3//test.txt',
422+
self::URL . 'test1/test3/test.txt'
410423
]
411424
];
412425
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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="AdminFillCaptchaOnResetPasswordFormActionGroup">
12+
<arguments>
13+
<argument name="captcha" type="string"/>
14+
</arguments>
15+
<fillField userInput="{{captcha}}" selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="fillCaptchaField"/>
16+
</actionGroup>
17+
</actionGroups>
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="AssertCaptchaVisibleOnAdminResetPasswordFormActionGroup">
12+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="waitToSeeCaptchaField"/>
13+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImage"/>
14+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButton"/>
15+
<reloadPage stepKey="refreshPage"/>
16+
<waitForPageLoad stepKey="waitForPageReloaded"/>
17+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="waitToSeeCaptchaFieldAfterPageReload"/>
18+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImageAfterPageReload"/>
19+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButtonAfterPageReload"/>
20+
</actionGroup>
21+
</actionGroups>

app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,33 @@
163163
<data key="label">ABCDEFGHJKMnpqrstuvwxyz23456789</data>
164164
<data key="value">ABCDEFGHJKMnpqrstuvwxyz23456789</data>
165165
</entity>
166+
<entity name="AdminCaptchaForgotPasswordFormConfigData">
167+
<!-- Magento default value -->
168+
<data key="path">admin/captcha/forms</data>
169+
<data key="scope_id">1</data>
170+
<data key="label">Admin Forgot Password</data>
171+
<data key="value">backend_forgotpassword</data>
172+
</entity>
173+
<entity name="AdminCaptchaDisplayModeConfigData">
174+
<data key="path">admin/captcha/mode</data>
175+
<data key="scope_id">1</data>
176+
<data key="label">Always</data>
177+
<data key="value">always</data>
178+
</entity>
179+
<entity name="AdminCaptchaDefaultDisplayModeConfigData">
180+
<!-- Magento default value -->
181+
<data key="path">admin/captcha/mode</data>
182+
<data key="scope_id">0</data>
183+
<data key="label">After number of attempts to login</data>
184+
<data key="value">after_fail</data>
185+
</entity>
186+
<entity name="AdminCaptchaAdminLoginFormConfigData">
187+
<!-- Magento default value -->
188+
<data key="path">admin/captcha/forms</data>
189+
<data key="scope_id">1</data>
190+
<data key="label">AdminLogin</data>
191+
<data key="value">backend_login</data>
192+
</entity>
166193
<entity name="StorefrontCaptchaOnCheckoutConfigData">
167194
<data key="path">customer/captcha/forms</data>
168195
<data key="scope_id">0</data>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
11+
<section name="AdminResetPasswordFormSection">
12+
<element name="captchaField" type="input" selector="#login-form input[name='captcha[backend_forgotpassword]']"/>
13+
<element name="captchaImg" type="block" selector="#login-form img#backend_forgotpassword"/>
14+
<element name="captchaReload" type="block" selector="#login-form img#captcha-reload.captcha-reload"/>
15+
</section>
16+
</sections>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminResetUserPasswordWithEnabledCaptchaTest">
12+
<annotations>
13+
<features value="captcha"/>
14+
<stories value="Password Reset procedure for Admin Panel"/>
15+
<title value="Admin user reset password with enabled captcha "/>
16+
<description value="Admin user should be able reset the password with enabled captcha"/>
17+
<severity value="MAJOR"/>
18+
<group value="captcha"/>
19+
</annotations>
20+
<before>
21+
<magentoCLI command="config:set {{AdminCaptchaLength3ConfigData.path}} {{AdminCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength"/>
22+
<magentoCLI command="config:set {{AdminCaptchaSymbols1ConfigData.path}} {{AdminCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols"/>
23+
<magentoCLI command="config:set {{AdminCaptchaForgotPasswordFormConfigData.path}} {{AdminCaptchaForgotPasswordFormConfigData.value}}" stepKey="enableResetPasswordCaptcha"/>
24+
<magentoCLI command="config:set {{AdminCaptchaDisplayModeConfigData.path}} {{AdminCaptchaDisplayModeConfigData.value}}" stepKey="setCaptchaAlwaysVisible"/>
25+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
26+
<argument name="tags" value="config full_page"/>
27+
</actionGroup>
28+
</before>
29+
30+
<after>
31+
<magentoCLI command="config:set {{AdminCaptchaDefaultLengthConfigData.path}} {{AdminCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength"/>
32+
<magentoCLI command="config:set {{AdminCaptchaDefaultSymbolsConfigData.path}} {{AdminCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols"/>
33+
<magentoCLI command="config:set {{AdminCaptchaDefaultDisplayModeConfigData.path}} {{AdminCaptchaDefaultDisplayModeConfigData.value}}" stepKey="setCaptchaDefaultVisibility"/>
34+
<magentoCLI command="config:set {{AdminCaptchaForgotPasswordFormConfigData.path}} {{AdminCaptchaForgotPasswordFormConfigData.value}},{{AdminCaptchaAdminLoginFormConfigData.value}}" stepKey="setDefaultCaptchaValuesOnForms"/>
35+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
36+
<argument name="tags" value="config full_page"/>
37+
</actionGroup>
38+
</after>
39+
40+
<actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage"/>
41+
<actionGroup ref="AssertCaptchaVisibleOnAdminResetPasswordFormActionGroup" stepKey="assertCaptchaVisible"/>
42+
<actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm">
43+
<argument name="email" value="{{inactiveAdmin.email}}"/>
44+
</actionGroup>
45+
<actionGroup ref="AdminFillCaptchaOnResetPasswordFormActionGroup" stepKey="fillCaptchaWithInvalidValues">
46+
<argument name="captcha" value="{{WrongCaptcha.value}}"/>
47+
</actionGroup>
48+
<actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm"/>
49+
<actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorMessage">
50+
<argument name="messageType" value="error"/>
51+
<argument name="message" value="Incorrect CAPTCHA"/>
52+
</actionGroup>
53+
<actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillEmailOnAdminForgotPasswordForm">
54+
<argument name="email" value="{{inactiveAdmin.email}}"/>
55+
</actionGroup>
56+
<actionGroup ref="AdminFillCaptchaOnResetPasswordFormActionGroup" stepKey="fillCaptchaWithCorrectValues">
57+
<argument name="captcha" value="{{PreconfiguredCaptcha.value}}"/>
58+
</actionGroup>
59+
<actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordFormWithCorrectCaptcha"/>
60+
<actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeSuccessMessage">
61+
<argument name="messageType" value="success"/>
62+
<argument name="message" value="We'll email you a link to reset your password."/>
63+
</actionGroup>
64+
</test>
65+
</tests>

app/code/Magento/Catalog/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,72 @@
1+
#Magento_Catalog
12
Magento_Catalog module functionality is represented by the following sub-systems:
23
- Products Management. It includes CRUD operation of product, product media, product attributes, etc...
34
- Category Management. It includes CRUD operation of category, category attributes
45

56
Catalog module provides mechanism for creating new product type in the system.
67
Catalog module provides API filtering that allows to limit product selection with advanced filters.
8+
9+
## Structure
10+
11+
[Learn about a typical file structure for a Magento 2 module]
12+
(https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html).
13+
14+
## Observer
15+
This module observes the following events:
16+
`etc/events.xml`
17+
`magento_catalog_api_data_productinterface_save_before` event in
18+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
19+
`magento_catalog_api_data_productinterface_save_after` event in
20+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
21+
`magento_catalog_api_data_productinterface_delete_before` event in
22+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
23+
`magento_catalog_api_data_productinterface_delete_after` event in
24+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
25+
`magento_catalog_api_data_productinterface_load_after` event in
26+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
27+
`magento_catalog_api_data_categoryinterface_save_before` event in
28+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
29+
`magento_catalog_api_data_categoryinterface_save_after` event in
30+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
31+
`magento_catalog_api_data_categoryinterface_save_after` event in
32+
`Magento\Catalog\Observer\InvalidateCacheOnCategoryDesignChange` file.
33+
`magento_catalog_api_data_categoryinterface_delete_before` event in
34+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
35+
`magento_catalog_api_data_categoryinterface_delete_after` event in
36+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
37+
`magento_catalog_api_data_categoryinterface_load_after` event in
38+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
39+
`magento_catalog_api_data_categorytreeinterface_save_before` event in
40+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
41+
`magento_catalog_api_data_categorytreeinterface_save_after` event in
42+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
43+
`magento_catalog_api_data_categorytreeinterface_delete_before` event in
44+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
45+
`magento_catalog_api_data_categorytreeinterface_delete_after` event in
46+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
47+
`magento_catalog_api_data_categorytreeinterface_load_after` event in
48+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
49+
`admin_system_config_changed_section_catalog` event in
50+
`Magento\Catalog\Observer\SwitchPriceAttributeScopeOnConfigChange` file.
51+
`catalog_product_save_before` event in
52+
`Magento\Catalog\Observer\SetSpecialPriceStartDate` file.
53+
`store_save_after` event in
54+
`Magento\Catalog\Observer\SynchronizeWebsiteAttributesOnStoreChange` file.
55+
`catalog_product_save_commit_after` event in
56+
`Magento\Catalog\Observer\ImageResizeAfterProductSave` file.
57+
`catalog_category_prepare_save` event in
58+
`Magento\Catalog\Observer\CategoryDesignAuthorization` file.
59+
60+
`/etc/frontend/events.xml`
61+
`customer_login` event in
62+
`Magento\Catalog\Observer\Compare\BindCustomerLoginObserver` file.
63+
`customer_logout` event in
64+
`Magento\Catalog\Observer\Compare\BindCustomerLogoutObserver` file.
65+
66+
`/etc/adminhtml/events.xml`
67+
`cms_wysiwyg_images_static_urls_allowed` event in
68+
`Magento\Catalog\Observer\CatalogCheckIsUsingStaticUrlsAllowedObserver` file.
69+
`catalog_category_change_products` event in
70+
`Magento\Catalog\Observer\CategoryProductIndexer` file.
71+
`category_move` event in
72+
`Magento\Catalog\Observer\FlushCategoryPagesCache`

0 commit comments

Comments
 (0)