diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 356c6ca17da18..f61e99529c3cc 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -208,6 +208,7 @@ public function save() ); $groupChangedPaths = $this->getChangedPaths($sectionId, $groupId, $groupData, $oldConfig, $extraOldGroups); + // phpcs:ignore Magento2.Performance.ForeachArrayMerge $changedPaths = \array_merge($changedPaths, $groupChangedPaths); } @@ -370,6 +371,7 @@ private function getChangedPaths( $oldConfig, $extraOldGroups ); + // phpcs:ignore Magento2.Performance.ForeachArrayMerge $changedPaths = \array_merge($changedPaths, $subGroupChangedPaths); } } @@ -435,11 +437,11 @@ protected function _processGroup( if (!isset($fieldData['value'])) { $fieldData['value'] = null; } - + if ($field->getType() == 'multiline' && is_array($fieldData['value'])) { $fieldData['value'] = trim(implode(PHP_EOL, $fieldData['value'])); } - + $data = [ 'field' => $fieldId, 'groups' => $groups, @@ -453,7 +455,7 @@ protected function _processGroup( $backendModel->addData($data); $this->_checkSingleStoreMode($field, $backendModel); - $path = $this->getFieldPath($field, $fieldId, $extraOldGroups, $oldConfig); + $path = $this->getFieldPath($field, $fieldId, $oldConfig, $extraOldGroups); $backendModel->setPath($path)->setValue($fieldData['value']); $inherit = !empty($fieldData['inherit']); diff --git a/app/code/Magento/Contact/view/frontend/templates/form.phtml b/app/code/Magento/Contact/view/frontend/templates/form.phtml index 673bdc73840dc..66e215b0475ff 100644 --- a/app/code/Magento/Contact/view/frontend/templates/form.phtml +++ b/app/code/Magento/Contact/view/frontend/templates/form.phtml @@ -4,6 +4,9 @@ * See COPYING.txt for license details. */ +// phpcs:disable Magento2.Templates.ThisInTemplate +// phpcs:disable Generic.Files.LineLength.TooLong + /** @var \Magento\Contact\Block\ContactForm $block */ ?>
- +
- +
- +
@@ -50,3 +65,12 @@
+ diff --git a/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml b/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml index be201afa8f66c..caa501d48da83 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml @@ -6,6 +6,8 @@ * @var $block \Magento\Customer\Block\Account\Forgotpassword */ +// phpcs:disable Generic.Files.LineLength.TooLong + /** @var \Magento\Customer\Block\Account\Forgotpassword $block */ ?>
+ diff --git a/app/code/Magento/Customer/view/frontend/templates/form/login.phtml b/app/code/Magento/Customer/view/frontend/templates/form/login.phtml index 339e26fa54328..c208af8547407 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/login.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/login.phtml @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +// phpcs:disable Generic.Files.LineLength.TooLong + /** @var \Magento\Customer\Block\Form\Login $block */ ?>
@@ -22,13 +24,22 @@
- isAutocompleteDisabled()) : ?> autocomplete="off" id="email" type="email" class="input-text" title="escapeHtmlAttr(__('Email')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> + isAutocompleteDisabled()): ?> autocomplete="off" + id="email" type="email" class="input-text" + title="escapeHtmlAttr(__('Email')) ?>" + data-mage-init='{"mage/trim-input":{}}' + data-validate="{required:true, 'validate-email':true}">
- isAutocompleteDisabled()) : ?> autocomplete="off" class="input-text" id="pass" title="escapeHtmlAttr(__('Password')) ?>" data-validate="{required:true}"> + isAutocompleteDisabled()): ?> autocomplete="off" + class="input-text" id="pass" + title="escapeHtmlAttr(__('Password')) ?>" + data-validate="{required:true}">
getChildHtml('form_additional_info') ?> @@ -41,3 +52,12 @@
+ diff --git a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml index bbcb842d02e5a..0e06deb90f0be 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -199,12 +199,6 @@ require([ ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' }).find('input:text').attr('autocomplete', 'off'); - dataForm.submit(function () { - $(this).find(':submit').attr('disabled', 'disabled'); - }); - dataForm.bind("invalid-form.validate", function () { - $(this).find(':submit').prop('disabled', false); - }); }); getShowAddressFields()): ?> @@ -225,13 +219,17 @@ require([ } - diff --git a/app/code/Magento/Customer/view/frontend/web/js/block-submit-on-send.js b/app/code/Magento/Customer/view/frontend/web/js/block-submit-on-send.js new file mode 100644 index 0000000000000..b941ec7a254d8 --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/block-submit-on-send.js @@ -0,0 +1,22 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/mage' +], function ($) { + 'use strict'; + + return function (config) { + var dataForm = $('#' + config.formId); + + dataForm.submit(function () { + $(this).find(':submit').attr('disabled', 'disabled'); + }); + dataForm.bind('invalid-form.validate', function () { + $(this).find(':submit').prop('disabled', false); + }); + }; +}); diff --git a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml index bb5c1ef2b5923..a68805d2149d3 100644 --- a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml +++ b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml @@ -40,3 +40,12 @@ + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml index fea1cf3966b99..1d3d47f70773c 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml @@ -17,6 +17,9 @@ + + + diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php index f8b6e7a197fa4..f2e1f30e1f084 100644 --- a/app/code/Magento/Quote/Model/Quote/Address.php +++ b/app/code/Magento/Quote/Model/Quote/Address.php @@ -1019,6 +1019,13 @@ public function collectShippingRates() */ public function requestShippingRates(AbstractItem $item = null) { + $storeId = $this->getQuote()->getStoreId() ?: $this->storeManager->getStore()->getId(); + $taxInclude = $this->_scopeConfig->getValue( + 'tax/calculation/price_includes_tax', + ScopeInterface::SCOPE_STORE, + $storeId + ); + /** @var $request RateRequest */ $request = $this->_rateRequestFactory->create(); $request->setAllItems($item ? [$item] : $this->getAllItems()); @@ -1028,9 +1035,11 @@ public function requestShippingRates(AbstractItem $item = null) $request->setDestStreet($this->getStreetFull()); $request->setDestCity($this->getCity()); $request->setDestPostcode($this->getPostcode()); - $request->setPackageValue($item ? $item->getBaseRowTotal() : $this->getBaseSubtotal()); + $baseSubtotal = $taxInclude ? $this->getBaseSubtotalTotalInclTax() : $this->getBaseSubtotal(); + $request->setPackageValue($item ? $item->getBaseRowTotal() : $baseSubtotal); + $baseSubtotalWithDiscount = $baseSubtotal + $this->getBaseDiscountAmount(); $packageWithDiscount = $item ? $item->getBaseRowTotal() - - $item->getBaseDiscountAmount() : $this->getBaseSubtotalWithDiscount(); + $item->getBaseDiscountAmount() : $baseSubtotalWithDiscount; $request->setPackageValueWithDiscount($packageWithDiscount); $request->setPackageWeight($item ? $item->getRowWeight() : $this->getWeight()); $request->setPackageQty($item ? $item->getQty() : $this->getItemQty()); @@ -1038,8 +1047,7 @@ public function requestShippingRates(AbstractItem $item = null) /** * Need for shipping methods that use insurance based on price of physical products */ - $packagePhysicalValue = $item ? $item->getBaseRowTotal() : $this->getBaseSubtotal() - - $this->getBaseVirtualAmount(); + $packagePhysicalValue = $item ? $item->getBaseRowTotal() : $baseSubtotal - $this->getBaseVirtualAmount(); $request->setPackagePhysicalValue($packagePhysicalValue); $request->setFreeMethodWeight($item ? 0 : $this->getFreeMethodWeight()); @@ -1047,12 +1055,10 @@ public function requestShippingRates(AbstractItem $item = null) /** * Store and website identifiers specified from StoreManager */ + $request->setStoreId($storeId); if ($this->getQuote()->getStoreId()) { - $storeId = $this->getQuote()->getStoreId(); - $request->setStoreId($storeId); $request->setWebsiteId($this->storeManager->getStore($storeId)->getWebsiteId()); } else { - $request->setStoreId($this->storeManager->getStore()->getId()); $request->setWebsiteId($this->storeManager->getWebsite()->getId()); } $request->setFreeShipping($this->getFreeShipping()); diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php index 242f81b222507..06dc8becf4d3c 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php @@ -345,10 +345,40 @@ public function testRequestShippingRates() $currentCurrencyCode = 'UAH'; + $this->quote->expects($this->any()) + ->method('getStoreId') + ->willReturn($storeId); + + $this->storeManager->expects($this->at(0)) + ->method('getStore') + ->with($storeId) + ->willReturn($this->store); + $this->store->expects($this->any()) + ->method('getWebsiteId') + ->willReturn($webSiteId); + + $this->scopeConfig->expects($this->exactly(1)) + ->method('getValue') + ->with( + 'tax/calculation/price_includes_tax', + ScopeInterface::SCOPE_STORE, + $storeId + ) + ->willReturn(1); + /** @var RateRequest */ $request = $this->getMockBuilder(RateRequest::class) ->disableOriginalConstructor() - ->setMethods(['setStoreId', 'setWebsiteId', 'setBaseCurrency', 'setPackageCurrency']) + ->setMethods( + [ + 'setStoreId', + 'setWebsiteId', + 'setBaseCurrency', + 'setPackageCurrency', + 'getBaseSubtotalTotalInclTax', + 'getBaseSubtotal' + ] + ) ->getMock(); /** @var Collection */ @@ -427,13 +457,6 @@ public function testRequestShippingRates() $this->storeManager->method('getStore') ->willReturn($this->store); - $this->storeManager->expects($this->once()) - ->method('getWebsite') - ->willReturn($this->website); - - $this->store->method('getId') - ->willReturn($storeId); - $this->store->method('getBaseCurrency') ->willReturn($baseCurrency); @@ -445,10 +468,6 @@ public function testRequestShippingRates() ->method('getCurrentCurrencyCode') ->willReturn($currentCurrencyCode); - $this->website->expects($this->once()) - ->method('getId') - ->willReturn($webSiteId); - $this->addressRateFactory->expects($this->once()) ->method('create') ->willReturn($rate); diff --git a/app/code/Magento/SalesRule/view/frontend/requirejs-config.js b/app/code/Magento/SalesRule/view/frontend/requirejs-config.js index 13b701c6fe65a..21f49fb3080fc 100644 --- a/app/code/Magento/SalesRule/view/frontend/requirejs-config.js +++ b/app/code/Magento/SalesRule/view/frontend/requirejs-config.js @@ -8,6 +8,9 @@ var config = { mixins: { 'Magento_Checkout/js/action/select-payment-method': { 'Magento_SalesRule/js/action/select-payment-method-mixin': true + }, + 'Magento_Checkout/js/model/shipping-save-processor': { + 'Magento_SalesRule/js/model/shipping-save-processor-mixin': true } } } diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/model/shipping-save-processor-mixin.js b/app/code/Magento/SalesRule/view/frontend/web/js/model/shipping-save-processor-mixin.js new file mode 100644 index 0000000000000..193acb8eed2f4 --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/model/shipping-save-processor-mixin.js @@ -0,0 +1,34 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'mage/utils/wrapper', + 'Magento_Checkout/js/model/quote', + 'Magento_SalesRule/js/model/coupon' +], function (wrapper, quote, coupon) { + 'use strict'; + + return function (shippingSaveProcessor) { + shippingSaveProcessor.saveShippingInformation = wrapper.wrapSuper( + shippingSaveProcessor.saveShippingInformation, + function (type) { + var updateCouponCallback; + + /** + * Update coupon form + */ + updateCouponCallback = function () { + if (quote.totals() && !quote.totals()['coupon_code']) { + coupon.setCouponCode(''); + coupon.setIsApplied(false); + } + }; + + return this._super(type).done(updateCouponCallback); + } + ); + + return shippingSaveProcessor; + }; +}); diff --git a/dev/tests/integration/testsuite/Magento/Config/Model/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Config/Model/ConfigTest.php index 1b7a504959d54..eedb93099b8c3 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Model/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Model/ConfigTest.php @@ -5,12 +5,18 @@ */ namespace Magento\Config\Model; +use Magento\Backend\App\Area\FrontNameResolver; +use Magento\Config\Model\ResourceModel\Config\Data\Collection; +use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory; +use Magento\Framework\Config\ScopeInterface; +use Magento\Framework\Encryption\EncryptorInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; /** * @magentoAppArea adminhtml */ -class ConfigTest extends \PHPUnit\Framework\TestCase +class ConfigTest extends TestCase { /** * @covers \Magento\Config\Model\Config::save @@ -22,25 +28,25 @@ class ConfigTest extends \PHPUnit\Framework\TestCase public function testSaveWithSingleStoreModeEnabled($groups) { Bootstrap::getObjectManager()->get( - \Magento\Framework\Config\ScopeInterface::class + ScopeInterface::class )->setCurrentScope( - \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE + FrontNameResolver::AREA_CODE ); - /** @var $_configDataObject \Magento\Config\Model\Config */ - $_configDataObject = Bootstrap::getObjectManager()->create(\Magento\Config\Model\Config::class); + /** @var $_configDataObject Config */ + $_configDataObject = Bootstrap::getObjectManager()->create(Config::class); $_configData = $_configDataObject->setSection('dev')->setWebsite('base')->load(); $this->assertEmpty($_configData); - $_configDataObject = Bootstrap::getObjectManager()->create(\Magento\Config\Model\Config::class); + $_configDataObject = Bootstrap::getObjectManager()->create(Config::class); $_configDataObject->setSection('dev')->setGroups($groups)->save(); - /** @var $_configDataObject \Magento\Config\Model\Config */ - $_configDataObject = Bootstrap::getObjectManager()->create(\Magento\Config\Model\Config::class); + /** @var $_configDataObject Config */ + $_configDataObject = Bootstrap::getObjectManager()->create(Config::class); $_configData = $_configDataObject->setSection('dev')->load(); $this->assertArrayHasKey('dev/debug/template_hints_admin', $_configData); $this->assertArrayHasKey('dev/debug/template_hints_blocks', $_configData); - $_configDataObject = Bootstrap::getObjectManager()->create(\Magento\Config\Model\Config::class); + $_configDataObject = Bootstrap::getObjectManager()->create(Config::class); $_configData = $_configDataObject->setSection('dev')->setWebsite('base')->load(); $this->assertArrayNotHasKey('dev/debug/template_hints_admin', $_configData); $this->assertArrayNotHasKey('dev/debug/template_hints_blocks', $_configData); @@ -63,16 +69,16 @@ public function testSave($section, $groups, $expected) { $objectManager = Bootstrap::getObjectManager(); - /** @var $_configDataObject \Magento\Config\Model\Config */ - $_configDataObject = $objectManager->create(\Magento\Config\Model\Config::class); + /** @var $_configDataObject Config */ + $_configDataObject = $objectManager->create(Config::class); $_configDataObject->setSection($section)->setWebsite('base')->setGroups($groups)->save(); foreach ($expected as $group => $expectedData) { - $_configDataObject = $objectManager->create(\Magento\Config\Model\Config::class); + $_configDataObject = $objectManager->create(Config::class); $_configData = $_configDataObject->setSection($group)->setWebsite('base')->load(); if (array_key_exists('payment/payflow_link/pwd', $_configData)) { $_configData['payment/payflow_link/pwd'] = $objectManager->get( - \Magento\Framework\Encryption\EncryptorInterface::class + EncryptorInterface::class )->decrypt( $_configData['payment/payflow_link/pwd'] ); @@ -85,4 +91,102 @@ public function saveDataProvider() { return require __DIR__ . '/_files/config_section.php'; } + + /** + * @param string $website + * @param string $section + * @param array $override + * @param array $inherit + * @param array $expected + * @dataProvider saveWebsiteScopeDataProvider + */ + public function testSaveUseDefault( + string $website, + string $section, + array $override, + array $inherit, + array $expected + ): void { + $objectManager = Bootstrap::getObjectManager(); + /** @var Config $config*/ + $configFactory = $objectManager->create(ConfigFactory::class); + $config = $configFactory->create() + ->setSection($section) + ->setWebsite($website) + ->setGroups($override['groups']) + ->save(); + + $paths = array_keys($expected); + + $this->assertEquals( + $expected, + $this->getConfigValues($config->getScope(), $config->getScopeId(), $paths) + ); + + $config = $configFactory->create() + ->setSection($section) + ->setWebsite($website) + ->setGroups($inherit['groups']) + ->save(); + + $this->assertEmpty( + $this->getConfigValues($config->getScope(), $config->getScopeId(), $paths) + ); + } + + /** + * @return array + */ + public function saveWebsiteScopeDataProvider(): array + { + return [ + [ + 'website' => 'base', + 'section' => 'payment', + [ + 'groups' => [ + 'account' => [ + 'fields' => [ + 'merchant_country' => ['value' => 'GB'], + ], + ], + ] + ], + [ + 'groups' => [ + 'account' => [ + 'fields' => [ + 'merchant_country' => ['inherit' => 1], + ], + ], + ], + ], + 'expected' => [ + 'paypal/general/merchant_country' => 'GB', + ], + ] + ]; + } + + /** + * @param string $scope + * @param int $scopeId + * @param array $paths + * @return array + */ + private function getConfigValues(string $scope, int $scopeId, array $paths): array + { + $objectManager = Bootstrap::getObjectManager(); + /** @var Collection $configCollection */ + $configCollectionFactory = $objectManager->create(CollectionFactory::class); + $configCollection = $configCollectionFactory->create(); + $configCollection->addFieldToFilter('scope', $scope); + $configCollection->addFieldToFilter('scope_id', $scopeId); + $configCollection->addFieldToFilter('path', ['in' => $paths]); + $result = []; + foreach ($configCollection as $data) { + $result[$data->getPath()] = $data->getValue(); + } + return $result; + } } diff --git a/setup/src/Magento/Setup/Console/CompilerPreparation.php b/setup/src/Magento/Setup/Console/CompilerPreparation.php index c39c721b61716..2a92310b7230f 100644 --- a/setup/src/Magento/Setup/Console/CompilerPreparation.php +++ b/setup/src/Magento/Setup/Console/CompilerPreparation.php @@ -65,13 +65,9 @@ public function __construct( */ public function handleCompilerEnvironment() { - $compilationCommands = $this->getCompilerInvalidationCommands(); - $cmdName = $this->input->getFirstArgument(); - $isHelpOption = $this->input->hasParameterOption('--help') || $this->input->hasParameterOption('-h'); - if (!in_array($cmdName, $compilationCommands) || $isHelpOption) { + if (!$this->shouldInvalidateCompiledDI()) { return; } - if (!$this->getGenerationDirectoryAccess()->check()) { throw new GenerationDirectoryAccessException(); } @@ -121,4 +117,38 @@ private function getGenerationDirectoryAccess() return $this->generationDirectoryAccess; } + + /** + * Checks if the command being executed should invalidate compiled DI. + * + * @return bool + */ + private function shouldInvalidateCompiledDI(): bool + { + $compilationCommands = $this->getCompilerInvalidationCommands(); + $cmdName = $this->input->getFirstArgument(); + $isHelpOption = $this->input->hasParameterOption('--help') || $this->input->hasParameterOption('-h'); + $invalidate = false; + if (!$isHelpOption) { + $invalidate = in_array($cmdName, $compilationCommands); + if (!$invalidate) { + // Check if it's an abbreviation of compilation commands. + $expr = preg_replace_callback( + '{([^:]+|)}', + function ($matches) { + return preg_quote($matches[1]) . '[^:]*'; + }, + $cmdName + ); + $commands = preg_grep('{^' . $expr . '$}', $compilationCommands); + if (empty($commands)) { + $commands = preg_grep('{^' . $expr . '$}i', $compilationCommands); + } + if (count($commands) === 1) { + $invalidate = true; + } + } + } + return $invalidate; + } } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php b/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php index 7bd11c64f93ac..5310446eb0f98 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php @@ -136,7 +136,25 @@ public function commandNameDataProvider() 'commandName' => 'not:a:compiler', 'isCompileCommand' => false, 'isHelpOption' => false, - ] + ], + 'ST compiler, directory exists, abbreviation 1' => [ + 'commandName' => 's:d:c', + 'isCompileCommand' => true, + 'isHelpOption' => false, + 'dirExists' => true + ], + 'ST compiler, directory exists, abbreviation 2' => [ + 'commandName' => 'se:di:co', + 'isCompileCommand' => true, + 'isHelpOption' => false, + 'dirExists' => true + ], + 'ST compiler, directory exists, abbreviation ambiguous' => [ + 'commandName' => 'se:di', + 'isCompileCommand' => false, + 'isHelpOption' => false, + 'dirExists' => true + ], ]; }