Skip to content

Commit 7e7e711

Browse files
Merge branch '2.4.8-beta1-develop' into AC-11946
2 parents 87f70c6 + d202a12 commit 7e7e711

File tree

141 files changed

+5738
-421
lines changed

Some content is hidden

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

141 files changed

+5738
-421
lines changed

app/code/Magento/Backend/Console/Command/MaintenanceStatusCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5353
{
5454
$output->writeln(
5555
'<info>Status: maintenance mode is ' .
56-
($this->maintenanceMode->isOn() ? 'active' : 'not active') . '</info>'
56+
($this->maintenanceMode->isOn() ? 'enabled' : 'disabled') . '</info>'
5757
);
5858
$addressInfo = $this->maintenanceMode->getAddressInfo();
5959
$addresses = implode(' ', $addressInfo);

app/code/Magento/Backend/Model/Validator/IpValidator.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
<?php
2+
23
/**
34
* Copyright © Magento, Inc. All rights reserved.
45
* See COPYING.txt for license details.
56
*/
7+
68
namespace Magento\Backend\Model\Validator;
79

10+
use Magento\Framework\App\Utility\IPAddress;
11+
812
/**
913
* Class to validate list of IPs for maintenance commands
1014
*/
@@ -25,12 +29,22 @@ class IpValidator
2529
*/
2630
private $invalidIps;
2731

32+
/**
33+
* @param IPAddress $ipAddress
34+
*/
35+
public function __construct(
36+
private readonly IPAddress $ipAddress,
37+
) {
38+
}
39+
2840
/**
2941
* Validates list of ips
3042
*
3143
* @param string[] $ips
3244
* @param bool $noneAllowed
45+
*
3346
* @return string[]
47+
*
3448
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
3549
*/
3650
public function validateIps(array $ips, $noneAllowed)
@@ -55,22 +69,26 @@ public function validateIps(array $ips, $noneAllowed)
5569
$messages[] = "Invalid IP $invalidIp";
5670
}
5771
}
72+
5873
return $messages;
5974
}
6075

6176
/**
6277
* Filter ips into 'none', valid and invalid ips
6378
*
6479
* @param string[] $ips
80+
*
6581
* @return void
6682
*/
6783
private function filterIps(array $ips)
6884
{
6985
foreach ($ips as $ip) {
70-
if (filter_var($ip, FILTER_VALIDATE_IP)) {
71-
$this->validIps[] = $ip;
72-
} elseif ($ip == 'none') {
86+
if ($ip === 'none') {
7387
$this->none[] = $ip;
88+
} elseif ($this->ipAddress->isValidAddress($ip)) {
89+
$this->validIps[] = $ip;
90+
} elseif ($this->ipAddress->isValidRange($ip)) {
91+
$this->validIps[] = $ip;
7492
} else {
7593
$this->invalidIps[] = $ip;
7694
}

app/code/Magento/Backend/Test/Unit/Console/Command/MaintenanceStatusCommandTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,20 @@ public function executeDataProvider()
5353
return [
5454
[
5555
[true, ['127.0.0.1', '127.0.0.2']],
56-
'Status: maintenance mode is active' . PHP_EOL .
56+
'Status: maintenance mode is enabled' . PHP_EOL .
5757
'List of exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL
5858
],
5959
[
6060
[true, []],
61-
'Status: maintenance mode is active' . PHP_EOL . 'List of exempt IP-addresses: none' . PHP_EOL
61+
'Status: maintenance mode is enabled' . PHP_EOL . 'List of exempt IP-addresses: none' . PHP_EOL
6262
],
6363
[
6464
[false, []],
65-
'Status: maintenance mode is not active' . PHP_EOL . 'List of exempt IP-addresses: none' . PHP_EOL
65+
'Status: maintenance mode is disabled' . PHP_EOL . 'List of exempt IP-addresses: none' . PHP_EOL
6666
],
6767
[
6868
[false, ['127.0.0.1', '127.0.0.2']],
69-
'Status: maintenance mode is not active' . PHP_EOL .
69+
'Status: maintenance mode is disabled' . PHP_EOL .
7070
'List of exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL
7171
],
7272
];

app/code/Magento/Backend/Test/Unit/Model/Validator/IpValidatorTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\Backend\Test\Unit\Model\Validator;
99

1010
use Magento\Backend\Model\Validator\IpValidator;
11+
use Magento\Framework\App\Utility\IPAddress;
1112
use PHPUnit\Framework\TestCase;
1213

1314
/**
@@ -25,7 +26,9 @@ class IpValidatorTest extends TestCase
2526
*/
2627
protected function setUp(): void
2728
{
28-
$this->ipValidator = new IpValidator();
29+
$this->ipValidator = new IpValidator(
30+
new IPAddress()
31+
);
2932
}
3033

3134
/**
@@ -45,6 +48,7 @@ public function validateIpsNoneAllowedDataProvider(): array
4548
{
4649
return [
4750
[['127.0.0.1', '127.0.0.2'], []],
51+
[['127.0.0.0/24'], []],
4852
[['none'], []],
4953
[['none', '127.0.0.1'], ["Multiple values are not allowed when 'none' is used"]],
5054
[['127.0.0.1', 'none'], ["Multiple values are not allowed when 'none' is used"]],
@@ -72,6 +76,7 @@ public function validateIpsNoneNotAllowedDataProvider()
7276
{
7377
return [
7478
[['127.0.0.1', '127.0.0.2'], []],
79+
[['127.0.0.0/24'], []],
7580
[['none'], ["'none' is not allowed"]],
7681
[['none', '127.0.0.1'], ["'none' is not allowed"]],
7782
[['127.0.0.1', 'none'], ["'none' is not allowed"]],
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\Bundle\Model\Product;
20+
21+
use Magento\Catalog\Model\Product;
22+
use Magento\Framework\Serialize\Serializer\Json;
23+
24+
/**
25+
* Get original price for bundle products
26+
*/
27+
class OriginalPrice
28+
{
29+
/**
30+
* @param Json $serializer
31+
*/
32+
public function __construct(private readonly Json $serializer)
33+
{
34+
}
35+
36+
/**
37+
* Get Original Total price for Bundle items
38+
*
39+
* @param Product $product
40+
* @return float
41+
*/
42+
public function getTotalBundleItemsOriginalPrice(Product $product): float
43+
{
44+
$price = 0.0;
45+
46+
if (!$product->hasCustomOptions()) {
47+
return $price;
48+
}
49+
50+
$selectionIds = $this->getBundleSelectionIds($product);
51+
52+
if (empty($selectionIds)) {
53+
return $price;
54+
}
55+
56+
$selections = $product->getTypeInstance()->getSelectionsByIds($selectionIds, $product);
57+
foreach ($selections->getItems() as $selection) {
58+
if (!$selection->isSalable()) {
59+
continue;
60+
}
61+
62+
$selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId());
63+
if ($selectionQty) {
64+
$price += $this->getSelectionOriginalTotalPrice(
65+
$product,
66+
$selection,
67+
(float) $selectionQty->getValue()
68+
);
69+
}
70+
}
71+
72+
return $price;
73+
}
74+
75+
/**
76+
* Calculate total original price of selection
77+
*
78+
* @param Product $bundleProduct
79+
* @param Product $selectionProduct
80+
* @param float $selectionQty
81+
*
82+
* @return float
83+
*/
84+
private function getSelectionOriginalTotalPrice(
85+
Product $bundleProduct,
86+
Product $selectionProduct,
87+
float $selectionQty
88+
): float {
89+
$price = $this->getSelectionOriginalPrice($bundleProduct, $selectionProduct);
90+
91+
return $price * $selectionQty;
92+
}
93+
94+
/**
95+
* Calculate the original price of selection
96+
*
97+
* @param Product $bundleProduct
98+
* @param Product $selectionProduct
99+
*
100+
* @return float
101+
*/
102+
public function getSelectionOriginalPrice(Product $bundleProduct, Product $selectionProduct): float
103+
{
104+
if ($bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) {
105+
return (float) $selectionProduct->getPrice();
106+
}
107+
if ($selectionProduct->getSelectionPriceType()) {
108+
// percent
109+
return $bundleProduct->getPrice() * ($selectionProduct->getSelectionPriceValue() / 100);
110+
}
111+
112+
// fixed
113+
return (float) $selectionProduct->getSelectionPriceValue();
114+
}
115+
116+
/**
117+
* Retrieve array of bundle selection IDs
118+
*
119+
* @param Product $product
120+
* @return array
121+
*/
122+
private function getBundleSelectionIds(Product $product): array
123+
{
124+
$customOption = $product->getCustomOption('bundle_selection_ids');
125+
if ($customOption) {
126+
$selectionIds = $this->serializer->unserialize($customOption->getValue());
127+
if (is_array($selectionIds)) {
128+
return $selectionIds;
129+
}
130+
}
131+
return [];
132+
}
133+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\Bundle\Plugin\Quote;
20+
21+
use Magento\Bundle\Model\Product\OriginalPrice;
22+
use Magento\Bundle\Model\Product\Type;
23+
use Magento\Quote\Model\Quote;
24+
use Magento\Quote\Model\Quote\Address\Total\Subtotal;
25+
use Magento\Quote\Api\Data\ShippingAssignmentInterface;
26+
use Magento\Quote\Model\Quote\Address\Total;
27+
28+
/**
29+
* Update bundle base original price
30+
*/
31+
class UpdateBundleQuoteItemBaseOriginalPrice
32+
{
33+
/**
34+
* @param OriginalPrice $price
35+
*/
36+
public function __construct(
37+
private readonly OriginalPrice $price
38+
) {
39+
}
40+
41+
/**
42+
* Update bundle base original price
43+
*
44+
* @param Subtotal $subject
45+
* @param Subtotal $result
46+
* @param Quote $quote
47+
* @param ShippingAssignmentInterface $shippingAssignment
48+
* @param Total $total
49+
*
50+
* @return Subtotal
51+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
52+
*/
53+
public function afterCollect(
54+
Subtotal $subject,
55+
Subtotal $result,
56+
Quote $quote,
57+
ShippingAssignmentInterface $shippingAssignment,
58+
Total $total
59+
): Subtotal {
60+
foreach ($quote->getAllVisibleItems() as $quoteItem) {
61+
if ($quoteItem->getProductType() === Type::TYPE_CODE) {
62+
$price = $quoteItem->getProduct()->getPrice();
63+
$price += $this->price->getTotalBundleItemsOriginalPrice($quoteItem->getProduct());
64+
$quoteItem->setBaseOriginalPrice($price);
65+
}
66+
}
67+
return $result;
68+
}
69+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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="AdminClickAddOptionForBundleItemsActionGroup">
12+
<annotations>
13+
<description>Click 'Add Option' button for bundle items.</description>
14+
</annotations>
15+
16+
<click selector="{{AdminProductFormBundleSection.addOption}}" stepKey="clickAddOption"/>
17+
</actionGroup>
18+
</actionGroups>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
<actionGroup ref="FilterProductGridByNameActionGroup" stepKey="filterBundleProductOptionsDownToName">
110110
<argument name="product" value="BundleProduct"/>
111111
</actionGroup>
112+
112113
<actionGroup ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup" stepKey="clickOnBundleProductToEdit"/>
113114
<comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="conditionallyOpenSectionBundleItemsToEdit"/>
114115
<actionGroup ref="AdminClickAddOptionOnBundleProductEditPageActionGroup" stepKey="clickAddOption"/>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
<conditionalClick selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" dependentSelector="{{AdminProductFormBundleSection.bundleItemsToggle}}" visible="false" stepKey="conditionallyOpenSectionBundleItems"/>
4848
<!-- scrollTo before click to fix flaky failure -->
4949
<scrollTo selector="{{AdminProductFormBundleSection.addOption}}" stepKey="scrollToAddOption"/>
50-
<click selector="{{AdminProductFormBundleSection.addOption}}" stepKey="clickAddOption3"/>
50+
<actionGroup ref="AdminClickAddOptionForBundleItemsActionGroup" stepKey="clickAddOption3"/>
5151
<waitForElementVisible selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" stepKey="waitForBundleOptions"/>
5252
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" userInput="{{BundleProduct.optionTitle1}}" stepKey="fillOptionTitle"/>
5353
<selectOption selector="{{AdminProductFormBundleSection.bundleOptionXInputType('0')}}" userInput="{{BundleProduct.optionInputType1}}" stepKey="selectInputType"/>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
<comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForBundleProductCreationPage"/>
4343
<conditionalClick selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" dependentSelector="{{AdminProductFormBundleSection.bundleItemsToggle}}" visible="false" stepKey="conditionallyOpenSectionBundleItems"/>
44-
<click selector="{{AdminProductFormBundleSection.addOption}}" stepKey="clickAddOption3"/>
44+
<actionGroup ref="AdminClickAddOptionForBundleItemsActionGroup" stepKey="clickAddOption3"/>
4545
<waitForElementVisible selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" stepKey="waitForBundleOptions"/>
4646
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" userInput="{{BundleProduct.optionTitle1}}" stepKey="fillOptionTitle"/>
4747
<selectOption selector="{{AdminProductFormBundleSection.bundleOptionXInputType('0')}}" userInput="{{BundleProduct.optionInputType1}}" stepKey="selectInputType"/>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
<comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForBundleProductCreationPage"/>
4242
<conditionalClick selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" dependentSelector="{{AdminProductFormBundleSection.bundleItemsToggle}}" visible="false" stepKey="conditionallyOpenSectionBundleItems"/>
43-
<click selector="{{AdminProductFormBundleSection.addOption}}" stepKey="clickAddOption3"/>
43+
<actionGroup ref="AdminClickAddOptionForBundleItemsActionGroup" stepKey="clickAddOption3"/>
4444
<waitForElementVisible selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" stepKey="waitForBundleOptions"/>
4545
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXTitle('0')}}" userInput="{{BundleProduct.optionTitle1}}" stepKey="fillOptionTitle"/>
4646
<selectOption selector="{{AdminProductFormBundleSection.bundleOptionXInputType('0')}}" userInput="{{BundleProduct.optionInputType1}}" stepKey="selectInputType"/>

0 commit comments

Comments
 (0)