Skip to content

Commit 5aefff1

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-commerce/magento2ce into ACP2E-3403
2 parents 427ae14 + fd5cf3a commit 5aefff1

File tree

18 files changed

+737
-594
lines changed

18 files changed

+737
-594
lines changed

app/code/Magento/Bundle/view/frontend/requirejs-config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,12 @@ var config = {
1111
slide: 'Magento_Bundle/js/slide',
1212
productSummary: 'Magento_Bundle/js/product-summary'
1313
}
14+
},
15+
config: {
16+
mixins: {
17+
'mage/validation': {
18+
'Magento_Bundle/js/validation': true
19+
}
20+
}
1421
}
1522
};

app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,59 +5,65 @@
55
*/
66
?>
77

8-
<?php /* @var $block \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox */ ?>
8+
<?php
9+
/**
10+
* @var $block \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox
11+
* @var \Magento\Framework\Escaper $escaper
12+
*/
13+
?>
914
<?php $_option = $block->getOption() ?>
1015
<?php $_selections = $_option->getSelections() ?>
11-
<?php $inputClass = 'checkbox product bundle option bundle-option-' . $block->escapeHtmlAttr($_option->getId()) ?>
12-
<?php $inputId = 'bundle-option-' . $block->escapeHtmlAttr($_option->getId()) ?>
13-
<?php $inputName = 'bundle_option[' . $block->escapeHtmlAttr($_option->getId()) . ']' ?>
16+
<?php $inputClass = 'checkbox product bundle option bundle-option-' . $escaper->escapeHtmlAttr($_option->getId()) ?>
17+
<?php $inputId = 'bundle-option-' . $escaper->escapeHtmlAttr($_option->getId()) ?>
18+
<?php $inputName = 'bundle_option[' . $escaper->escapeHtmlAttr($_option->getId()) . ']' ?>
1419
<?php $dataValidation = 'data-validate="{\'validate-one-required-by-name\':\'input[name^=&quot;bundle_option[' .
15-
$block->escapeHtmlAttr($_option->getId()) . ']&quot;]:checked\'}"' ?>
20+
$escaper->escapeHtmlAttr($_option->getId()) . ']&quot;]:checked\'}"' ?>
1621

1722
<div class="field option <?= ($_option->getRequired()) ? ' required': '' ?>">
1823
<label class="label">
19-
<span><?= $block->escapeHtml($_option->getTitle()) ?></span>
24+
<span><?= $escaper->escapeHtml($_option->getTitle()) ?></span>
2025
</label>
2126
<div class="control">
2227
<div class="nested options-list">
2328
<?php if ($block->showSingle()): ?>
2429
<?= /* @noEscape */ $block->getSelectionQtyTitlePrice($_selections[0]) ?>
2530
<?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($_selections[0]) ?>
2631
<input type="hidden"
27-
class="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?> product bundle option"
28-
name="bundle_option[<?= $block->escapeHtml($_option->getId()) ?>]"
29-
value="<?= $block->escapeHtmlAttr($_selections[0]->getSelectionId()) ?>"/>
32+
class="bundle-option-<?= $escaper->escapeHtmlAttr($_option->getId()) ?> product bundle option"
33+
name="bundle_option[<?= $escaper->escapeHtml($_option->getId()) ?>]"
34+
value="<?= $escaper->escapeHtmlAttr($_selections[0]->getSelectionId()) ?>"/>
3035
<?php else: ?>
3136
<?php foreach ($_selections as $selection): ?>
3237
<?php $sectionId = $selection->getSelectionId() ?>
3338
<div class="field choice">
3439
<input class="<?=/* @noEscape */ $inputClass ?> change-container-classname"
35-
id="<?=/* @noEscape */ $inputId . '-' . $block->escapeHtmlAttr($sectionId)?>"
36-
type="checkbox"
37-
<?php if ($_option->getRequired()): ?>
38-
<?= /* @noEscape */ $dataValidation ?>
39-
<?php endif;?>
40-
name="<?=/* @noEscape */ $inputName .'['. $block->escapeHtmlAttr($sectionId)?>]"
41-
data-selector="<?= /* @noEscape */ $inputName.'['.$block->escapeHtmlAttr($sectionId)?>]"
42-
<?php if ($block->isSelected($selection)): ?>
43-
<?= ' checked="checked"' ?>
44-
<?php endif; ?>
45-
<?php if (!$selection->isSaleable()): ?>
46-
<?= ' disabled="disabled"' ?>
47-
<?php endif; ?>
48-
value="<?= $block->escapeHtmlAttr($sectionId) ?>"
49-
data-errors-message-box="#validation-message-box"/>
40+
id="<?=/* @noEscape */ $inputId . '-' . $escaper->escapeHtmlAttr($sectionId)?>"
41+
type="checkbox"
42+
<?php if ($_option->getRequired()): ?>
43+
<?= /* @noEscape */ $dataValidation ?>
44+
<?php endif;?>
45+
name="<?=/* @noEscape */ $inputName .'['. $escaper->escapeHtmlAttr($sectionId)?>]"
46+
data-selector="<?= /* @noEscape */ $inputName.'['.$escaper->escapeHtmlAttr($sectionId)?>]"
47+
<?php if ($block->isSelected($selection)): ?>
48+
<?= ' checked="checked"' ?>
49+
<?php endif; ?>
50+
<?php if (!$selection->isSaleable()): ?>
51+
<?= ' disabled="disabled"' ?>
52+
<?php endif; ?>
53+
value="<?= $escaper->escapeHtmlAttr($sectionId) ?>"
54+
data-errors-msg-box="#validation-message-box-<?=$escaper->escapeHtmlAttr($_option->getId())?>"/>
5055
<label class="label"
51-
for="<?= /* @noEscape */ $inputId . '-' . $block->escapeHtmlAttr($sectionId) ?>">
56+
for="<?= /* @noEscape */ $inputId . '-' . $escaper->escapeHtmlAttr($sectionId) ?>">
5257
<span><?= /* @noEscape */ $block->getSelectionQtyTitlePrice($selection) ?></span>
5358
<br/>
5459
<?= /* @noEscape */ $block->getTierPriceRenderer()->renderTierPrice($selection) ?>
5560
</label>
5661
</div>
62+
5763
<?php endforeach; ?>
58-
<div id="bundle-option-<?= $block->escapeHtmlAttr($_option->getId()) ?>-container"></div>
59-
<div id="validation-message-box"></div>
6064
<?php endif; ?>
6165
</div>
66+
<div id="bundle-option-<?= $escaper->escapeHtmlAttr($_option->getId()) ?>-container"></div>
67+
<div id="validation-message-box-<?= $escaper->escapeHtmlAttr($_option->getId()) ?>"></div>
6268
</div>
6369
</div>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
define([
2+
'jquery',
3+
'jquery-ui-modules/widget'
4+
], function ($) {
5+
'use strict';
6+
var enhancedMageValidation = {
7+
/**
8+
* @param {*} error
9+
* @param {*} element
10+
*/
11+
options: {
12+
errorPlacement: function (error, element) {
13+
var errorPlacement = element,
14+
fieldWrapper,messageBox;
15+
16+
// logic for date-picker error placement
17+
if (element.hasClass('_has-datepicker')) {
18+
errorPlacement = element.siblings('button');
19+
}
20+
// logic for field wrapper
21+
fieldWrapper = element.closest('.addon');
22+
23+
if (fieldWrapper.length) {
24+
errorPlacement = fieldWrapper.after(error);
25+
}
26+
//logic for checkboxes/radio
27+
if (element.is(':checkbox') || element.is(':radio')) {
28+
errorPlacement = element.parents('.control').children().last();
29+
30+
//fallback if group does not have .control parent
31+
if (!errorPlacement.length) {
32+
errorPlacement = element.siblings('label').last();
33+
}
34+
}
35+
if (element.attr('data-errors-msg-box')) {
36+
messageBox = $(element.attr('data-errors-msg-box'));
37+
messageBox.html(error);
38+
return;
39+
}
40+
//logic for control with tooltip
41+
if (element.siblings('.tooltip').length) {
42+
errorPlacement = element.siblings('.tooltip');
43+
}
44+
//logic for select with tooltip in after element
45+
if (element.next().find('.tooltip').length) {
46+
errorPlacement = element.next();
47+
}
48+
errorPlacement.after(error);
49+
}
50+
51+
}
52+
};
53+
54+
return function (mageValidation) {
55+
$.widget('mage.validation', mageValidation, enhancedMageValidation);
56+
return $.mage.validation;
57+
};
58+
});

app/code/Magento/Catalog/view/frontend/web/js/related-products.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,12 @@ define([
4747
* @return {Boolean} - Prevent default event action and event propagation.
4848
*/
4949
_selectAllRelated: function (e) {
50-
var innerHTML = this.options.relatedProductsCheckFlag ?
51-
this.options.selectAllMessage : this.options.unselectAllMessage;
50+
let isChecked = this.options.relatedProductsCheckFlag;
5251

53-
$(e.target).html(innerHTML);
54-
$(this.options.relatedCheckbox + ':visible').attr(
55-
'checked',
56-
this.options.relatedProductsCheckFlag = !this.options.relatedProductsCheckFlag
57-
);
52+
$(e.target).html(isChecked ? this.options.selectAllMessage : this.options.unselectAllMessage);
53+
this.options.relatedProductsCheckFlag = !isChecked;
54+
55+
$(this.options.relatedCheckbox + ':visible').prop('checked', this.options.relatedProductsCheckFlag);
5856
this._addRelatedToProduct();
5957

6058
return false;

app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ protected function _construct()
6464
*/
6565
public function prepareCondition($attribute, $value)
6666
{
67-
$condition = false;
67+
$condition = $value;
6868

6969
if (is_array($value)) {
7070
if ($attribute->getBackendType() == 'varchar') { // multiselect

app/code/Magento/Customer/view/adminhtml/web/js/form/element/region.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ define([
2525
countryId = this.source.data.country_id,
2626
hasRegionList = indexedOptionsArray.some(option => option.country_id === countryId);
2727

28-
this.source.set(
29-
this.regionScope,
30-
hasRegionList
31-
? parseFloat(value) ? this.indexedOptions?.[value]?.label || '' : ''
32-
: this.source.data?.region || ''
33-
);
28+
// Clear the region field when the country changes
29+
this.source.set(this.regionScope, '');
30+
31+
if (hasRegionList) {
32+
this.source.set(
33+
this.regionScope,
34+
parseFloat(value) ? this.indexedOptions?.[value]?.label || '' : ''
35+
);
36+
}
3437
}
3538
});
3639
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
/**
3+
* Copyright 2024 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Directory\Test\Fixture;
9+
10+
use Magento\Directory\Model\Currency;
11+
use Magento\Framework\App\ResourceConnection;
12+
use Magento\Framework\DataObject;
13+
use Magento\Framework\Locale\FormatInterface;
14+
use Magento\TestFramework\Fixture\RevertibleDataFixtureInterface;
15+
16+
/**
17+
* Data fixture for currency rate.
18+
*/
19+
class CurrencyRate implements RevertibleDataFixtureInterface
20+
{
21+
/**
22+
* @var FormatInterface
23+
*/
24+
private $format;
25+
26+
/**
27+
* @var Currency
28+
*/
29+
private $currency;
30+
31+
/**
32+
* @var ResourceConnection
33+
*/
34+
private $resourceConnection;
35+
36+
public function __construct(
37+
FormatInterface $format,
38+
Currency $currency,
39+
ResourceConnection $resourceConnection
40+
) {
41+
$this->format = $format;
42+
$this->currency = $currency;
43+
$this->resourceConnection = $resourceConnection;
44+
}
45+
46+
public function apply(array $data = []): ?DataObject
47+
{
48+
foreach ($data as $currencyCode => $rate) {
49+
foreach ($rate as $currencyTo => $value) {
50+
$value = abs((float) $this->format->getNumber($value));
51+
$data[$currencyCode][$currencyTo] = $value;
52+
}
53+
}
54+
55+
return $this->currency->saveRates($data);
56+
}
57+
58+
public function revert(DataObject $data): void
59+
{
60+
$connection = $this->resourceConnection->getConnection();
61+
$currencyTable = $this->resourceConnection->getTableName('directory_currency_rate');
62+
63+
foreach ($data as $currencyCode => $rate) {
64+
foreach ($rate as $currencyTo) {
65+
$connection->delete(
66+
$currencyTable,
67+
[
68+
'currency_from = ?' => $currencyCode,
69+
'currency_to = ?' => $currencyTo,
70+
]
71+
);
72+
}
73+
}
74+
}
75+
}

app/code/Magento/Quote/Model/QuoteManagement.php

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -694,12 +694,14 @@ protected function _prepareCustomerQuote($quote)
694694
$hasDefaultBilling = true;
695695
}
696696
}
697-
//save here new customer address
698-
$shippingAddress->setCustomerId($quote->getCustomerId());
699-
$this->addressRepository->save($shippingAddress);
700-
$quote->addCustomerAddress($shippingAddress);
697+
if (!$shippingAddress->getId()) {
698+
//save here new customer address
699+
$shippingAddress->setCustomerId($quote->getCustomerId());
700+
$this->addressRepository->save($shippingAddress);
701+
$quote->addCustomerAddress($shippingAddress);
702+
$this->addressesToSync[] = $shippingAddress->getId();
703+
}
701704
$shipping->setCustomerAddressData($shippingAddress);
702-
$this->addressesToSync[] = $shippingAddress->getId();
703705
$shipping->setCustomerAddressId($shippingAddress->getId());
704706
}
705707
}
@@ -727,11 +729,13 @@ protected function _prepareCustomerQuote($quote)
727729
}
728730
$billingAddress->setIsDefaultBilling(true);
729731
}
730-
$billingAddress->setCustomerId($quote->getCustomerId());
731-
$this->addressRepository->save($billingAddress);
732-
$quote->addCustomerAddress($billingAddress);
732+
if (!$billingAddress->getId()) {
733+
$billingAddress->setCustomerId($quote->getCustomerId());
734+
$this->addressRepository->save($billingAddress);
735+
$quote->addCustomerAddress($billingAddress);
736+
$this->addressesToSync[] = $billingAddress->getId();
737+
}
733738
$billing->setCustomerAddressData($billingAddress);
734-
$this->addressesToSync[] = $billingAddress->getId();
735739
$billing->setCustomerAddressId($billingAddress->getId());
736740

737741
// Admin order: `Same As Billing Address`- when new billing address saved in address book

0 commit comments

Comments
 (0)