diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
index cf6301cb31a9c..62c1cc086048b 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
@@ -62,6 +62,7 @@ public function loadAttributeOptions()
{
$attributes = [
'base_subtotal_with_discount' => __('Subtotal (Excl. Tax)'),
+ 'base_subtotal_total_incl_tax' => __('Subtotal (Incl. Tax)'),
'base_subtotal' => __('Subtotal'),
'total_qty' => __('Total Items Quantity'),
'weight' => __('Total Weight'),
@@ -99,6 +100,7 @@ public function getInputType()
{
switch ($this->getAttribute()) {
case 'base_subtotal':
+ case 'base_subtotal_total_incl_tax':
case 'weight':
case 'total_qty':
return 'numeric';
diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml
index 57a2c17419532..f6a705ee368e9 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/AdminCreateCartPriceRuleActionGroup.xml
@@ -19,6 +19,7 @@
+
@@ -26,6 +27,7 @@
-
+
+
diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml
index c8363a3df6221..5607512c862b3 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml
index cc695b347c4fb..727222213b118 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleAddressConditionsData.xml
@@ -10,6 +10,7 @@
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
Magento\SalesRule\Model\Rule\Condition\Address|base_subtotal
+ Magento\SalesRule\Model\Rule\Condition\Address|base_subtotal_total_incl_tax
Magento\SalesRule\Model\Rule\Condition\Address|total_qty
Magento\SalesRule\Model\Rule\Condition\Address|weight
Magento\SalesRule\Model\Rule\Condition\Address|shipping_method
diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithSubtotalInclTaxTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithSubtotalInclTaxTest.xml
new file mode 100644
index 0000000000000..a52e8e10459e5
--- /dev/null
+++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithSubtotalInclTaxTest.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml
index 7a995b1feeeda..d76e9edb828bd 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml
@@ -10,6 +10,7 @@
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
+
diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml
index 74542be376c45..159f2a1a82ece 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml
@@ -92,7 +92,7 @@
stepKey="waitForElementDiscountVisible"/>
-
+
@@ -132,7 +132,7 @@
stepKey="waitForElementDiscountVisible1"/>
-
+
diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/Rule/Condition/AddressTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/Rule/Condition/AddressTest.php
new file mode 100644
index 0000000000000..70036c06922c5
--- /dev/null
+++ b/app/code/Magento/SalesRule/Test/Unit/Model/Rule/Condition/AddressTest.php
@@ -0,0 +1,65 @@
+createMock(\Magento\Rule\Model\Condition\Context::class);
+ $directoryCountry = $this->createMock(\Magento\Directory\Model\Config\Source\Country::class);
+ $directoryAllregion = $this->createMock(\Magento\Directory\Model\Config\Source\Allregion::class);
+ $shippingAllmethods = $this->createMock(\Magento\Shipping\Model\Config\Source\Allmethods::class);
+ $paymentAllmethods = $this->createMock(\Magento\Payment\Model\Config\Source\Allmethods::class);
+ $this->model = new Address(
+ $context,
+ $directoryCountry,
+ $directoryAllregion,
+ $shippingAllmethods,
+ $paymentAllmethods
+ );
+ }
+
+ /**
+ * Test that all attributes are present in options list
+ */
+ public function testLoadAttributeOptions(): void
+ {
+ $attributes = [
+ 'base_subtotal_with_discount',
+ 'base_subtotal_total_incl_tax',
+ 'base_subtotal',
+ 'total_qty',
+ 'weight',
+ 'payment_method',
+ 'shipping_method',
+ 'postcode',
+ 'region',
+ 'region_id',
+ 'country_id',
+ ];
+
+ $this->model->loadAttributeOptions();
+ $this->assertEquals($attributes, array_keys($this->model->getAttributeOption()));
+ }
+}
diff --git a/app/code/Magento/Search/Model/SynonymAnalyzer.php b/app/code/Magento/Search/Model/SynonymAnalyzer.php
index 16d0b0b4ddcd9..f9d18179be4ee 100644
--- a/app/code/Magento/Search/Model/SynonymAnalyzer.php
+++ b/app/code/Magento/Search/Model/SynonymAnalyzer.php
@@ -137,10 +137,10 @@ private function getSearchPattern(array $words): string
{
$patterns = [];
for ($lastItem = count($words); $lastItem > 0; $lastItem--) {
- $words = array_map(function ($word) {
+ $safeRegexWords = array_map(function ($word) {
return preg_quote($word, '/');
}, $words);
- $phrase = implode("\s+", \array_slice($words, 0, $lastItem));
+ $phrase = implode("\s+", \array_slice($safeRegexWords, 0, $lastItem));
$patterns[] = '^' . $phrase . ',';
$patterns[] = ',' . $phrase . ',';
$patterns[] = ',' . $phrase . '$';
diff --git a/app/code/Magento/Search/Test/Unit/Model/SynonymAnalyzerTest.php b/app/code/Magento/Search/Test/Unit/Model/SynonymAnalyzerTest.php
index 9e6d087f72f99..70e93ca6b4404 100644
--- a/app/code/Magento/Search/Test/Unit/Model/SynonymAnalyzerTest.php
+++ b/app/code/Magento/Search/Test/Unit/Model/SynonymAnalyzerTest.php
@@ -84,4 +84,42 @@ public function testGetSynonymsForPhraseEmptyPhrase()
$actual = $this->synonymAnalyzer->getSynonymsForPhrase($phrase);
$this->assertEquals($expected, $actual);
}
+
+ /**
+ * @test
+ *
+ * Phrase that is long and has quotes in it scenario
+ */
+ public function testLongQuotedPhrase()
+ {
+ $phrase = 'LSS 3/8"X3/4"X25\' EZ-PULL 1/2" INS SWEAT LINESET W/90 END BEND SUCTION LINE INSULATED';
+ $expected = [
+ 0 => [ 0 => "LSS" ],
+ 1 => [ 0 => "3/8\"X3/4\"X25'" ],
+ 2 => [ 0 => "EZ-PULL" ],
+ 3 => [ 0 => "1/2\"" ],
+ 4 => [ 0 => "INS" ],
+ 5 => [ 0 => "SWEAT" ],
+ 6 => [ 0 => "LINESET" ],
+ 7 => [ 0 => "W/90" ],
+ 8 => [ 0 => "END" ],
+ 9 => [ 0 => "BEND", 1 => "TWIST" ],
+ 10 => [ 0 => "SUCTION", 1 => "WEIGHT" ],
+ 11 => [ 0 => "LINE" ],
+ 12 => [ 0 => "INSULATED" ]
+ ];
+ $this->synReaderModel->expects($this->once())
+ ->method('loadByPhrase')
+ ->with($phrase)
+ ->willReturnSelf();
+ $this->synReaderModel->expects($this->once())
+ ->method('getData')
+ ->willReturn([
+ ['synonyms' => 'BEND,TWIST'],
+ ['synonyms' => 'SUCTION,WEIGHT'],
+ ]);
+
+ $actual = $this->synonymAnalyzer->getSynonymsForPhrase($phrase);
+ $this->assertEquals($expected, $actual);
+ }
}
diff --git a/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml b/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml
index 0ba20d201f909..0bfdc0eed289c 100644
--- a/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml
+++ b/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml
@@ -77,7 +77,7 @@
-
+
diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
index f0a5f357f8a92..298ae22cb8904 100644
--- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
+++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml
@@ -141,7 +141,7 @@
-
+
diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/multiline.js b/app/code/Magento/Ui/view/base/web/js/form/components/multiline.js
new file mode 100644
index 0000000000000..8c8816a0559a8
--- /dev/null
+++ b/app/code/Magento/Ui/view/base/web/js/form/components/multiline.js
@@ -0,0 +1,57 @@
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/**
+ * @api
+ */
+define([
+ './group'
+], function (Group) {
+ 'use strict';
+
+ return Group.extend({
+ defaults: {
+ links: {
+ value: '${ $.provider }:${ $.dataScope }'
+ }
+ },
+
+ /**
+ * Initialize Multiline component.
+ *
+ * @returns {Object}
+ */
+ initialize: function () {
+ return this._super()
+ ._prepareValue();
+ },
+
+ /**
+ * {@inheritdoc}
+ */
+ initObservable: function () {
+ this._super()
+ .observe('value');
+
+ return this;
+ },
+
+ /**
+ * Prepare value for Multiline options.
+ *
+ * @returns {Object} Chainable.
+ * @private
+ */
+ _prepareValue: function () {
+ var value = this.value();
+
+ if (typeof value === 'string') {
+ this.value(value.split('\n'));
+ }
+
+ return this;
+ }
+ });
+});
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js
index 1432372dd75a9..af9142745206b 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js
@@ -127,7 +127,7 @@ define([
if (this.options.showsTime) {
shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone);
} else {
- shiftedValue = moment(value, this.outputDateFormat);
+ shiftedValue = moment(value, this.outputDateFormat, true);
}
if (!shiftedValue.isValid()) {
diff --git a/app/code/Magento/Ui/view/base/web/js/grid/provider.js b/app/code/Magento/Ui/view/base/web/js/grid/provider.js
index 2ba8bd73af910..021ae83eb1c7d 100644
--- a/app/code/Magento/Ui/view/base/web/js/grid/provider.js
+++ b/app/code/Magento/Ui/view/base/web/js/grid/provider.js
@@ -14,7 +14,8 @@ define([
'uiLayout',
'Magento_Ui/js/modal/alert',
'mage/translate',
- 'uiElement'
+ 'uiElement',
+ 'Magento_Ui/js/grid/data-storage'
], function ($, _, utils, resolver, layout, alert, $t, Element) {
'use strict';
diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php
index 28a4a3a7e0b41..452f488050202 100644
--- a/app/code/Magento/Ups/Model/Carrier.php
+++ b/app/code/Magento/Ups/Model/Carrier.php
@@ -17,6 +17,7 @@
use Magento\Framework\Async\CallbackDeferred;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\HTTP\AsyncClient\HttpException;
use Magento\Framework\HTTP\AsyncClient\HttpResponseDeferredInterface;
use Magento\Framework\HTTP\AsyncClient\Request;
use Magento\Framework\HTTP\AsyncClientInterface;
@@ -33,6 +34,7 @@
use Magento\Shipping\Model\Rate\Result;
use Magento\Shipping\Model\Rate\Result\ProxyDeferredFactory;
use Magento\Shipping\Model\Rate\ResultFactory as RateFactory;
+use Magento\Shipping\Model\Shipment\Request as Shipment;
use Magento\Shipping\Model\Simplexml\Element;
use Magento\Shipping\Model\Simplexml\ElementFactory;
use Magento\Shipping\Model\Tracking\Result\ErrorFactory as TrackErrorFactory;
@@ -40,7 +42,6 @@
use Magento\Shipping\Model\Tracking\ResultFactory as TrackFactory;
use Magento\Store\Model\ScopeInterface;
use Magento\Ups\Helper\Config;
-use Magento\Shipping\Model\Shipment\Request as Shipment;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Throwable;
@@ -811,10 +812,15 @@ protected function _getXmlQuotes()
[
'deferred' => new CallbackDeferred(
function () use ($httpResponse) {
- if ($httpResponse->get()->getStatusCode() >= 400) {
- $xmlResponse = '';
- } else {
- $xmlResponse = $httpResponse->get()->getBody();
+ $responseResult = null;
+ $xmlResponse = '';
+ try {
+ $responseResult = $httpResponse->get();
+ } catch (HttpException $exception) {
+ $this->_logger->critical($exception);
+ }
+ if ($responseResult) {
+ $xmlResponse = $responseResult->getStatusCode() >= 400 ? '' : $responseResult->getBody();
}
return $this->_parseXmlResponse($xmlResponse);
diff --git a/app/code/Magento/Ups/etc/adminhtml/system.xml b/app/code/Magento/Ups/etc/adminhtml/system.xml
index 3a1676d221977..6890e1bdaf870 100644
--- a/app/code/Magento/Ups/etc/adminhtml/system.xml
+++ b/app/code/Magento/Ups/etc/adminhtml/system.xml
@@ -13,9 +13,6 @@
Magento\Config\Model\Config\Backend\Encrypted
-
- 1
-
@@ -89,9 +86,6 @@
Magento\Config\Model\Config\Backend\Encrypted
-
- 1
-
@@ -123,9 +117,6 @@
Magento\Config\Model\Config\Backend\Encrypted
-
- 1
-
diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml
index f068b0cf0079f..b6b7040a41bca 100644
--- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml
+++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml
@@ -4,10 +4,17 @@
* See COPYING.txt for license details.
*/
-/** @var $upsModel \Magento\Ups\Helper\Config */
-/** @var $block \Magento\Ups\Block\Backend\System\CarrierConfig */
-/** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */
+use Magento\Framework\Escaper;
+use Magento\Framework\Json\Helper\Data;
+use Magento\Framework\View\Helper\SecureHtmlRenderer;
+use Magento\Store\Model\Website;
+use Magento\Ups\Block\Backend\System\CarrierConfig;
+/**
+ * @var CarrierConfig $block
+ * @var Escaper $escaper
+ * @var SecureHtmlRenderer $secureRenderer
+ */
$upsCarrierConfig = $block->getCarrierConfig();
$orShipArr = $upsCarrierConfig->getCode('originShipment');
$defShipArr = $upsCarrierConfig->getCode('method');
@@ -15,26 +22,26 @@ $defShipArr = $upsCarrierConfig->getCode('method');
$sectionCode = $block->getRequest()->getParam('section');
$websiteCode = $block->getRequest()->getParam('website');
$storeCode = $block->getRequest()->getParam('store');
-/** @var \Magento\Framework\Json\Helper\Data $jsonHelper */
+/** @var Data $jsonHelper */
$jsonHelper = $block->getData('jsonHelper');
if (!$storeCode && $websiteCode) {
- /** @var $web \Magento\Store\Model\Website */
+ /** @var Website $web */
$web = $block->getWebsiteModel()->load($websiteCode);
$storedAllowedMethods = explode(',', $web->getConfig('carriers/ups/allowed_methods'));
- $storedOriginShipment = $block->escapeHtml($web->getConfig('carriers/ups/origin_shipment'));
- $storedFreeShipment = $block->escapeHtml($web->getConfig('carriers/ups/free_method'));
- $storedUpsType = $block->escapeHtml($web->getConfig('carriers/ups/type'));
+ $storedOriginShipment = $escaper->escapeHtml($web->getConfig('carriers/ups/origin_shipment'));
+ $storedFreeShipment = $escaper->escapeHtml($web->getConfig('carriers/ups/free_method'));
+ $storedUpsType = $escaper->escapeHtml($web->getConfig('carriers/ups/type'));
} elseif ($storeCode) {
$storedAllowedMethods = explode(',', $block->getConfig('carriers/ups/allowed_methods', $storeCode));
- $storedOriginShipment = $block->escapeHtml($block->getConfig('carriers/ups/origin_shipment', $storeCode));
- $storedFreeShipment = $block->escapeHtml($block->getConfig('carriers/ups/free_method', $storeCode));
- $storedUpsType = $block->escapeHtml($block->getConfig('carriers/ups/type', $storeCode));
+ $storedOriginShipment = $escaper->escapeHtml($block->getConfig('carriers/ups/origin_shipment', $storeCode));
+ $storedFreeShipment = $escaper->escapeHtml($block->getConfig('carriers/ups/free_method', $storeCode));
+ $storedUpsType = $escaper->escapeHtml($block->getConfig('carriers/ups/type', $storeCode));
} else {
$storedAllowedMethods = explode(',', $block->getConfig('carriers/ups/allowed_methods'));
- $storedOriginShipment = $block->escapeHtml($block->getConfig('carriers/ups/origin_shipment'));
- $storedFreeShipment = $block->escapeHtml($block->getConfig('carriers/ups/free_method'));
- $storedUpsType = $block->escapeHtml($block->getConfig('carriers/ups/type'));
+ $storedOriginShipment = $escaper->escapeHtml($block->getConfig('carriers/ups/origin_shipment'));
+ $storedFreeShipment = $escaper->escapeHtml($block->getConfig('carriers/ups/free_method'));
+ $storedUpsType = $escaper->escapeHtml($block->getConfig('carriers/ups/type'));
}
?>
@@ -87,14 +94,16 @@ require(["prototype"], function(){
'carriers_ups_origin_shipment','carriers_ups_negotiated_active','carriers_ups_shipper_number',
'carriers_ups_mode_xml','carriers_ups_include_taxes'];
this.onlyUpsElements = ['carriers_ups_gateway_url'];
+ this.authUpsXmlElements = ['carriers_ups_username',
+ 'carriers_ups_password','carriers_ups_access_license_number'];
script;
$scriptString .= 'this.storedOriginShipment = \'' . /* @noEscape */ $storedOriginShipment . '\';
this.storedFreeShipment = \'' . /* @noEscape */ $storedFreeShipment . '\';
- this.storedUpsType = \'' . /* @noEscape */ $storedUpsType . '\';';
+ this.storedUpsType = \'' . /* @noEscape */ $storedUpsType . '\';';
?>
-jsonEncode($storedAllowedMethods) .
- ';
+jsonEncode($storedAllowedMethods) . ';
this.originShipmentObj = ' . /* @noEscape */ $jsonHelper->jsonEncode($orShipArr) . ';
this.originShipmentObj[\'default\'] = ' . /* @noEscape */ $jsonHelper->jsonEncode($defShipArr) . ';';
@@ -119,8 +128,9 @@ $scriptString .= <<