diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php index 9ee191c2f30a4..4ff8a2c4e753a 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php @@ -8,6 +8,7 @@ namespace Magento\Catalog\Model\Product\Option; +use Magento\Catalog\Pricing\Price\BasePrice; use Magento\Framework\Model\AbstractModel; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Option; @@ -225,7 +226,7 @@ public function saveValues() public function getPrice($flag = false) { if ($flag && $this->getPriceType() == self::TYPE_PERCENT) { - $basePrice = $this->getOption()->getProduct()->getFinalPrice(); + $basePrice = $this->getOption()->getProduct()->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getValue(); $price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100); return $price; } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/ValueTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/ValueTest.php index 7fa5140884582..4a3b008ad4bb1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/ValueTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/ValueTest.php @@ -170,13 +170,30 @@ private function getMockedOption() private function getMockedProduct() { $mockBuilder = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->setMethods(['getFinalPrice', '__wakeup']) + ->setMethods(['getPriceInfo', '__wakeup']) ->disableOriginalConstructor(); $mock = $mockBuilder->getMock(); $mock->expects($this->any()) ->method('getFinalPrice') ->will($this->returnValue(10)); + $priceInfoMock = $this->getMockForAbstractClass( + \Magento\Framework\Pricing\PriceInfoInterface::class, + [], + '', + false, + false, + true, + ['getPrice'] + ); + + $priceMock = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Price\PriceInterface::class); + + $priceInfoMock->expects($this->any())->method('getPrice')->willReturn($priceMock); + + $mock->expects($this->any())->method('getPriceInfo')->willReturn($priceInfoMock); + + $priceMock->expects($this->any())->method('getValue')->willReturn(10); return $mock; } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 09cbb678987e7..2406c9ad40afe 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -2643,7 +2643,12 @@ protected function checkUrlKeyDuplicates() ); foreach ($urlKeyDuplicates as $entityData) { $rowNum = $this->rowNumbers[$entityData['store_id']][$entityData['request_path']]; - $this->addRowError(ValidatorInterface::ERROR_DUPLICATE_URL_KEY, $rowNum); + $message = sprintf( + $this->retrieveMessageTemplate(ValidatorInterface::ERROR_DUPLICATE_URL_KEY), + $entityData['request_path'], + $entityData['sku'] + ); + $this->addRowError(ValidatorInterface::ERROR_DUPLICATE_URL_KEY, $rowNum, 'url_key', $message); } } } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js index 3b1e15bc3b9d6..bb3ea2c5a6eda 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js @@ -276,12 +276,12 @@ define([ var element; _.each(this.disabledAttributes, function (attribute) { - registry.get('index = ' + attribute).disabled(false); + registry.get('code = ' + attribute, 'index = ' + attribute).disabled(false); }); this.disabledAttributes = []; _.each(attributes, function (attribute) { - element = registry.get('index = ' + attribute.code); + element = registry.get('code = ' + attribute.code, 'index = ' + attribute.code); if (!_.isUndefined(element)) { element.disabled(true); this.disabledAttributes.push(attribute.code); diff --git a/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php b/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php index b1c54a1f01260..3b67c0cc0694e 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php @@ -13,6 +13,8 @@ use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SortOrder; use Magento\Framework\Exception\InputException; +use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\ScopeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -61,6 +63,16 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf */ protected $extensionAttributesJoinProcessor; + /** + * @var \Magento\Directory\Model\AllowedCountries + */ + private $allowedCountriesReader; + + /** + * @var \Magento\Customer\Model\Config\Share + */ + private $shareConfig; + /** * @param \Magento\Customer\Model\AddressFactory $addressFactory * @param \Magento\Customer\Model\AddressRegistry $addressRegistry @@ -70,6 +82,10 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf * @param \Magento\Customer\Api\Data\AddressSearchResultsInterfaceFactory $addressSearchResultsFactory * @param \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressCollectionFactory * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor + * @param \Magento\Directory\Model\AllowedCountries|null $allowedCountriesReader + * @param \Magento\Customer\Model\Config\Share|null $shareConfig + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Customer\Model\AddressFactory $addressFactory, @@ -79,7 +95,9 @@ public function __construct( \Magento\Directory\Helper\Data $directoryData, \Magento\Customer\Api\Data\AddressSearchResultsInterfaceFactory $addressSearchResultsFactory, \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressCollectionFactory, - \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor, + \Magento\Directory\Model\AllowedCountries $allowedCountriesReader = null, + \Magento\Customer\Model\Config\Share $shareConfig = null ) { $this->addressFactory = $addressFactory; $this->addressRegistry = $addressRegistry; @@ -89,6 +107,10 @@ public function __construct( $this->addressSearchResultsFactory = $addressSearchResultsFactory; $this->addressCollectionFactory = $addressCollectionFactory; $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; + $this->allowedCountriesReader = $allowedCountriesReader + ?: ObjectManager::getInstance()->get(\Magento\Directory\Model\AllowedCountries::class); + $this->shareConfig = $shareConfig + ?: ObjectManager::getInstance()->get(\Magento\Customer\Model\Config\Share::class); } /** @@ -290,7 +312,7 @@ private function _validate(CustomerAddressModel $customerAddressModel) $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'countryId'])); } else { //Checking if such country exists. - if (!in_array($countryId, $this->directoryData->getCountryCollection()->getAllIds(), true)) { + if (!in_array($countryId, $this->getWebsiteAllowedCountries($customerAddressModel), true)) { $exception->addError( __( 'Invalid value of "%value" provided for the %fieldName field.', @@ -334,4 +356,23 @@ private function _validate(CustomerAddressModel $customerAddressModel) return $exception; } + + /** + * Return allowed counties per website. + * + * @param \Magento\Customer\Model\Address $customerAddressModel + * @return array + */ + private function getWebsiteAllowedCountries(\Magento\Customer\Model\Address $customerAddressModel) + { + $websiteId = null; + + if (!$this->shareConfig->isGlobalScope()) { + $websiteId = $customerAddressModel->getCustomer() + ? $customerAddressModel->getCustomer()->getWebsiteId() + : null; + } + + return $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $websiteId); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php index 8df72f96f93c7..338f6d1dffed5 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php @@ -6,8 +6,8 @@ namespace Magento\Customer\Test\Unit\Model\ResourceModel; use Magento\Customer\Api\Data\AddressInterface as AddressData; -use Magento\Directory\Model\ResourceModel\Country\Collection as Countries; use Magento\Framework\Exception\InputException; +use Magento\Store\Model\ScopeInterface; /** * Unit test for Magento\Customer\Model\ResourceModel\AddressRepository @@ -71,6 +71,16 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $repository; + /** + * @var \Magento\Directory\Model\AllowedCountries|\PHPUnit_Framework_MockObject_MockObject + */ + private $allowedCountriesReaderMock; + + /** + * @var \Magento\Customer\Model\Config\Share|\PHPUnit_Framework_MockObject_MockObject + */ + private $shareConfigMock; + protected function setUp() { $this->addressFactory = $this->getMock( @@ -137,6 +147,26 @@ protected function setUp() false ); + $this->allowedCountriesReaderMock = $this->getMock( + \Magento\Directory\Model\AllowedCountries::class, + ['getAllowedCountries'], + [], + '', + false + ); + $this->shareConfigMock = $this->getMock( + \Magento\Customer\Model\Config\Share::class, + ['isGlobalScope'], + [], + '', + false + ); + $this->shareConfigMock->method('isGlobalScope')->willReturn(false); + $this->allowedCountriesReaderMock + ->method('getAllowedCountries') + ->with(ScopeInterface::SCOPE_WEBSITE, null) + ->willReturn(['1', '2']); + $this->repository = new \Magento\Customer\Model\ResourceModel\AddressRepository( $this->addressFactory, $this->addressRegistry, @@ -145,7 +175,9 @@ protected function setUp() $this->directoryData, $this->addressSearchResultsFactory, $this->addressCollectionFactory, - $this->extensionAttributesJoinProcessor + $this->extensionAttributesJoinProcessor, + $this->allowedCountriesReaderMock, + $this->shareConfigMock ); } @@ -315,15 +347,6 @@ public function testSaveWithInvalidRegion() ->method('getRegion') ->willReturn(''); - /** @var \PHPUnit_Framework_MockObject_MockObject $countryCollection */ - $countryCollection = $this->getMockBuilder(Countries::class) - ->disableOriginalConstructor() - ->getMock(); - $countryCollection->expects($this->once())->method('getAllIds')->willReturn(['1', '2']); - $this->directoryData->expects($this->once()) - ->method('getCountryCollection') - ->willReturn($countryCollection); - $this->repository->save($customerAddress); } @@ -408,15 +431,6 @@ public function testSaveWithInvalidRegionId() ->method('getRegion') ->willReturn(''); - /** @var \PHPUnit_Framework_MockObject_MockObject $countryCollection */ - $countryCollection = $this->getMockBuilder(Countries::class) - ->disableOriginalConstructor() - ->getMock(); - $countryCollection->expects($this->once())->method('getAllIds')->willReturn(['1', '2']); - $this->directoryData->expects($this->once()) - ->method('getCountryCollection') - ->willReturn($countryCollection); - $this->repository->save($customerAddress); } @@ -714,15 +728,6 @@ private function prepareAddressData($countryId, $regionId) $countryModel->expects($this->any())->method('getRegionCollection')->willReturn($regionCollection); $regionCollection->expects($this->any())->method('getAllIds')->willReturn(['3', '4']); - /** @var \PHPUnit_Framework_MockObject_MockObject $countryCollection */ - $countryCollection = $this->getMockBuilder(Countries::class) - ->disableOriginalConstructor() - ->getMock(); - $countryCollection->expects($this->once())->method('getAllIds')->willReturn(['1', '2']); - $this->directoryData->expects($this->once()) - ->method('getCountryCollection') - ->willReturn($countryCollection); - return $customerAddress; } } 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 241ab1451238a..4b041f4052e7e 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/login.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/login.phtml @@ -32,7 +32,7 @@
- isAutocompleteDisabled()) :?> autocomplete="off" id="email" type="email" class="input-text" title="helper(\Magento\Framework\EscapeHelper::class)->escapeHtmlAttr(__('Email')) ?>" data-validate="{required:true, 'validate-email':true}"> + isAutocompleteDisabled()) :?> autocomplete="off" id="email" type="email" class="input-text" title="helper(\Magento\Framework\EscapeHelper::class)->escapeHtmlAttr(__('Email')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}">
@@ -51,12 +51,3 @@
- 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 c59c16ee3601c..516c5aa971ab8 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -134,7 +134,7 @@
- +
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/authentication-popup.js b/app/code/Magento/Customer/view/frontend/web/js/model/authentication-popup.js index fa62ebf5f9d48..9739fc1226917 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/authentication-popup.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/authentication-popup.js @@ -31,7 +31,7 @@ define( /** Show login popup window */ showModal: function () { - $(this.modalWindow).modal('openModal'); + $(this.modalWindow).modal('openModal').trigger('contentUpdated'); } } } diff --git a/app/code/Magento/Customer/view/frontend/web/js/trim-username.js b/app/code/Magento/Customer/view/frontend/web/js/trim-username.js deleted file mode 100644 index 1b6aab6086853..0000000000000 --- a/app/code/Magento/Customer/view/frontend/web/js/trim-username.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -define([ - 'jquery' -], function ($) { - 'use strict'; - - $.widget('mage.trimUsername', { - options: { - cache: {}, - formSelector: 'form', - emailSelector: 'input[type="email"]' - }, - - /** - * Widget initialization - * @private - */ - _create: function () { - // We need to look outside the module for backward compatibility, since someone can already use the module. - // @todo Narrow this selector in 2.3 so it doesn't accidentally finds the email field from the - // newsletter email field or any other "email" field. - this.options.cache.email = $(this.options.formSelector).find(this.options.emailSelector); - this._bind(); - }, - - /** - * Event binding, will monitor change, keyup and paste events. - * @private - */ - _bind: function () { - if (this.options.cache.email.length) { - this._on(this.options.cache.email, { - 'change': this._trimUsername, - 'keyup': this._trimUsername, - 'paste': this._trimUsername - }); - } - }, - - /** - * Trim username - * @private - */ - _trimUsername: function () { - var username = this._getUsername().trim(); - - this.options.cache.email.val(username); - }, - - /** - * Get username value - * @returns {*} - * @private - */ - _getUsername: function () { - return this.options.cache.email.val(); - } - }); - - return $.mage.trimUsername; -}); diff --git a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html index 046cc38d39149..f412d3d15d11f 100644 --- a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html +++ b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html @@ -60,6 +60,7 @@ id="email" type="email" class="input-text" + data-mage-init='{"mage/trim-input":{}}' data-bind="attr: {autocomplete: autocomplete}" data-validate="{required:true, 'validate-email':true}">
diff --git a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html index 20739f621ecff..15a36cc0e977a 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html +++ b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html @@ -12,26 +12,24 @@
-
-
@@ -46,7 +44,6 @@
- diff --git a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php index 8a95b2815eb85..fe7d1692c4a16 100644 --- a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php @@ -803,7 +803,7 @@ public function validateData() if (!$this->isAttributeParticular($columnName)) { if (trim($columnName) == '') { $emptyHeaderColumns[] = $columnNumber; - } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { + } elseif (!preg_match('/^[a-z][\w]*$/u', $columnName)) { $invalidColumns[] = $columnName; } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index 47b0935e31470..3e9e239b3b05f 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -769,7 +769,7 @@ public function validateData() if (!$this->isAttributeParticular($columnName)) { if (trim($columnName) == '') { $emptyHeaderColumns[] = $columnNumber; - } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { + } elseif (!preg_match('/^[a-z][\w]*$/u', $columnName)) { $invalidColumns[] = $columnName; } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php index 004677b899cd0..4e338c2d1df34 100644 --- a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php +++ b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php @@ -32,6 +32,8 @@ public function execute() } } - $this->getResponse()->setRedirect($this->_storeManager->getStore()->getBaseUrl()); + $resultRedirect = $this->resultRedirectFactory->create(); + $resultRedirect->setUrl($this->_storeManager->getStore()->getBaseUrl()); + return $resultRedirect; } } diff --git a/app/code/Magento/Paypal/view/frontend/web/order-review.js b/app/code/Magento/Paypal/view/frontend/web/order-review.js index eb9319aa98cd2..524a604b6763d 100644 --- a/app/code/Magento/Paypal/view/frontend/web/order-review.js +++ b/app/code/Magento/Paypal/view/frontend/web/order-review.js @@ -88,7 +88,7 @@ define([ }, /** - * trigger change for the update of shippping methods from server + * trigger change for the update of shipping methods from server */ _updateOrderHandler: function () { $(this.options.shippingSelector).trigger('change'); @@ -246,7 +246,7 @@ define([ this._updateOrderSubmit(true); this._toggleButton(this.options.updateOrderSelector, true); - // form data and callBack updated based on the shippping Form element + // form data and callBack updated based on the shipping Form element if (this.isShippingSubmitForm) { formData = $(this.options.shippingSubmitFormSelector).serialize() + "&isAjax=true"; callBackResponseHandler = function (response) { diff --git a/app/code/Magento/Quote/Model/ResourceModel/Quote.php b/app/code/Magento/Quote/Model/ResourceModel/Quote.php index 7065e8bb51b40..afa76aba5366e 100644 --- a/app/code/Magento/Quote/Model/ResourceModel/Quote.php +++ b/app/code/Magento/Quote/Model/ResourceModel/Quote.php @@ -171,7 +171,7 @@ public function getReservedOrderId($quote) { return $this->sequenceManager->getSequence( \Magento\Sales\Model\Order::ENTITY, - $quote->getStore()->getGroup()->getDefaultStoreId() + $quote->getStoreId() ) ->getNextValue(); } @@ -230,13 +230,24 @@ public function markQuotesRecollectOnCatalogRules() return $this; } + /** + * @param \Magento\Catalog\Model\Product $product + * @return Quote + * @deprecated + * @see subtractProductFromQuotes + */ + public function substractProductFromQuotes($product) + { + return $this->subtractProductFromQuotes($product); + } + /** * Subtract product from all quotes quantities * * @param \Magento\Catalog\Model\Product $product * @return $this */ - public function substractProductFromQuotes($product) + public function subtractProductFromQuotes($product) { $productId = (int)$product->getId(); if (!$productId) { diff --git a/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php new file mode 100644 index 0000000000000..915241f5721e1 --- /dev/null +++ b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php @@ -0,0 +1,102 @@ +getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->getMock(); + $snapshot = $this->getMockBuilder(Snapshot::class) + ->disableOriginalConstructor() + ->getMock(); + $relationComposite = $this->getMockBuilder(RelationComposite::class) + ->disableOriginalConstructor() + ->getMock(); + $this->quoteMock = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->getMock(); + $this->sequenceManagerMock = $this->getMockBuilder(Manager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->sequenceMock = $this->getMockBuilder(SequenceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->quote = new \Magento\Quote\Model\ResourceModel\Quote( + $context, + $snapshot, + $relationComposite, + $this->sequenceManagerMock, + null + ); + } + + /** + * @param $entityType + * @param $storeId + * @param $reservedOrderId + * @dataProvider getReservedOrderIdDataProvider + */ + public function testGetReservedOrderId($entityType, $storeId, $reservedOrderId) + { + $this->sequenceManagerMock->expects($this->once()) + ->method('getSequence') + ->with($entityType, $storeId) + ->willReturn($this->sequenceMock); + $this->quoteMock->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + $this->sequenceMock->expects($this->once()) + ->method('getNextValue') + ->willReturn($reservedOrderId); + $this->assertEquals($reservedOrderId, $this->quote->getReservedOrderId($this->quoteMock)); + } + + /** + * @return array + */ + public function getReservedOrderIdDataProvider() + { + return [ + [\Magento\Sales\Model\Order::ENTITY, 1, '1000000001'], + [\Magento\Sales\Model\Order::ENTITY, 2, '2000000001'], + [\Magento\Sales\Model\Order::ENTITY, 3, '3000000001'] + ]; + } +} diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals/Discount.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals/Discount.php index cdeb596a54ac7..b28dbda5f3810 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals/Discount.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals/Discount.php @@ -15,8 +15,6 @@ */ class Discount extends \Magento\Sales\Block\Adminhtml\Order\Create\Totals\DefaultTotals { - //protected $_template = 'tax/checkout/subtotal.phtml'; - /** * Tax config * diff --git a/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php b/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php index 8a8ee5e9c799f..2152ff7c84556 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php +++ b/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php @@ -121,10 +121,15 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { /** @var \Magento\Sales\Model\AbstractModel $object */ if ($object instanceof EntityInterface && $object->getIncrementId() == null) { + $store = $object->getStore(); + $storeId = $store->getId(); + if ($storeId === null) { + $storeId = $store->getGroup()->getDefaultStoreId(); + } $object->setIncrementId( $this->sequenceManager->getSequence( $object->getEntityType(), - $object->getStore()->getGroup()->getDefaultStoreId() + $storeId )->getNextValue() ); } diff --git a/app/code/Magento/Sales/Observer/Backend/SubtractQtyFromQuotesObserver.php b/app/code/Magento/Sales/Observer/Backend/SubtractQtyFromQuotesObserver.php index 775a7dab95cfe..cd8c705750d6c 100644 --- a/app/code/Magento/Sales/Observer/Backend/SubtractQtyFromQuotesObserver.php +++ b/app/code/Magento/Sales/Observer/Backend/SubtractQtyFromQuotesObserver.php @@ -31,6 +31,6 @@ public function __construct(\Magento\Quote\Model\ResourceModel\Quote $quote) public function execute(\Magento\Framework\Event\Observer $observer) { $product = $observer->getEvent()->getProduct(); - $this->_quote->substractProductFromQuotes($product); + $this->_quote->subtractProductFromQuotes($product); } } diff --git a/app/code/Magento/Sales/Test/Unit/Observer/Backend/SubtractQtyFromQuotesObserverTest.php b/app/code/Magento/Sales/Test/Unit/Observer/Backend/SubtractQtyFromQuotesObserverTest.php index 1208e3a755543..8e2174775b117 100644 --- a/app/code/Magento/Sales/Test/Unit/Observer/Backend/SubtractQtyFromQuotesObserverTest.php +++ b/app/code/Magento/Sales/Test/Unit/Observer/Backend/SubtractQtyFromQuotesObserverTest.php @@ -15,12 +15,12 @@ class SubtractQtyFromQuotesObserverTest extends \PHPUnit_Framework_TestCase protected $_model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Quote\Model\ResourceModel\Quote|\PHPUnit_Framework_MockObject_MockObject */ protected $_quoteMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject */ protected $_observerMock; @@ -54,7 +54,7 @@ public function testSubtractQtyFromQuotes() false ); $this->_eventMock->expects($this->once())->method('getProduct')->will($this->returnValue($productMock)); - $this->_quoteMock->expects($this->once())->method('substractProductFromQuotes')->with($productMock); + $this->_quoteMock->expects($this->once())->method('subtractProductFromQuotes')->with($productMock); $this->_model->execute($this->_observerMock); } } diff --git a/app/code/Magento/Search/view/frontend/web/form-mini.js b/app/code/Magento/Search/view/frontend/web/form-mini.js index 51398168c6e19..02a8f618a2298 100644 --- a/app/code/Magento/Search/view/frontend/web/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/form-mini.js @@ -207,6 +207,7 @@ define([ break; case $.ui.keyCode.ENTER: this.searchForm.trigger('submit'); + e.preventDefault(); break; case $.ui.keyCode.DOWN: if (this.responseList.indexList) { diff --git a/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml b/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml index 32f692c32fccf..bb8ac51236d2c 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml @@ -11,10 +11,10 @@ getSaveButtonHtml(); ?> getRenameFormHtml(); ?> - + \ No newline at end of file diff --git a/app/code/Magento/Tax/view/adminhtml/web/js/validate.js b/app/code/Magento/Tax/view/adminhtml/web/js/validate.js new file mode 100644 index 0000000000000..a49f199ba56b6 --- /dev/null +++ b/app/code/Magento/Tax/view/adminhtml/web/js/validate.js @@ -0,0 +1,15 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/mage' +], function (jQuery) { + 'use strict'; + + return function (data, element) { + jQuery(element).mage('form').mage('validation'); + }; +}); diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index ce04887732f6d..d7dd27874d365 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -147,6 +147,14 @@ protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) */ protected function getImageData($product) { + /*Set variant product if it is configurable product. + It will show variant product image in sidebar instead of configurable product image.*/ + $simpleOption = $product->getCustomOption('simple_product'); + if ($simpleOption !== null) { + $optionProduct = $simpleOption->getProduct(); + $product = $optionProduct; + } + /** @var \Magento\Catalog\Helper\Image $helper */ $helper = $this->imageHelperFactory->create() ->init($product, 'wishlist_sidebar_block'); diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less index e1d1851267afa..1576141fe0596 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less @@ -494,6 +494,16 @@ } } + // + // Category page 1 column layout + // --------------------------------------------- + + .catalog-category-view.page-layout-1column { + .column.main { + min-height: inherit; + } + } + } // diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less index c64efa65ae2f9..980e3367678f1 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less @@ -562,6 +562,16 @@ } } } + + // + // Category page 1 column layout + // --------------------------------------------- + + .catalog-category-view.page-layout-1column { + .column.main { + min-height: inherit; + } + } } // diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less index 7acb082bdff65..84f116c2c9547 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_listings.less @@ -425,7 +425,7 @@ .product-item { margin-left: calc(~'(100% - 4 * 24.439%) / 3'); - padding: 0; + padding: 5px; width: 24.439%; &:nth-child(4n + 1) { diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/1.csv index 0c13b51b55287..235d18468b739 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/1.csv +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/1.csv @@ -1,2 +1,3 @@ four and 75/100,4.75 -four and 5/10,4.50 \ No newline at end of file +four and 5/10,4.50 + diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php index a8dc20d9465a3..02ee6ca2c9579 100644 --- a/lib/internal/Magento/Framework/App/Language/Dictionary.php +++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php @@ -193,7 +193,9 @@ private function readPackCsv($vendor, $package) foreach ($foundCsvFiles as $foundCsvFile) { $file = $directoryRead->openFile($foundCsvFile); while (($row = $file->readCsv()) !== false) { - $result[$row[0]] = $row[1]; + if (is_array($row) && count($row) > 1) { + $result[$row[0]] = $row[1]; + } } } } diff --git a/lib/web/css/source/lib/_navigation.less b/lib/web/css/source/lib/_navigation.less index 56aa2e7ef86b9..b2ed4352a334a 100644 --- a/lib/web/css/source/lib/_navigation.less +++ b/lib/web/css/source/lib/_navigation.less @@ -355,6 +355,25 @@ overflow: visible !important; } + &.parent { + > .level-top { + padding-right: 20px; + + > .ui-menu-icon { + position: absolute; + right: 0; + + .lib-icon-font( + @icon-down, + @_icon-font-size: 12px, + @_icon-font-line-height: 20px, + @_icon-font-text-hide: true, + @_icon-font-position: after + ); + } + } + } + .submenu { .lib-css(background, @_submenu-background-color); .lib-css(border, @_submenu-border-width @_submenu-border-style @_submenu-border-color); @@ -414,6 +433,26 @@ left: auto !important; right: 100%; } + + li { + margin: 0; + &.parent { + > a { + > .ui-menu-icon { + position: absolute; + right: 3px; + + .lib-icon-font( + @icon-next, + @_icon-font-size: 12px, + @_icon-font-line-height: 20px, + @_icon-font-text-hide: true, + @_icon-font-position: after + ); + } + } + } + } } &.more { diff --git a/lib/web/mage/trim-input.js b/lib/web/mage/trim-input.js new file mode 100644 index 0000000000000..678192dcf61ac --- /dev/null +++ b/lib/web/mage/trim-input.js @@ -0,0 +1,60 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery' +], function ($) { + 'use strict'; + + $.widget('mage.trimInput', { + options: { + cache: {} + }, + + /** + * Widget initialization + * @private + */ + _create: function () { + this.options.cache.input = $(this.element); + this._bind(); + }, + + /** + * Event binding, will monitor change, keyup and paste events. + * @private + */ + _bind: function () { + if (this.options.cache.input.length) { + this._on(this.options.cache.input, { + 'change': this._trimInput, + 'keyup': this._trimInput, + 'paste': this._trimInput + }); + } + }, + + /** + * Trim value + * @private + */ + _trimInput: function () { + var input = this._getInputValue().trim(); + + this.options.cache.input.val(input); + }, + + /** + * Get input value + * @returns {*} + * @private + */ + _getInputValue: function () { + return this.options.cache.input.val(); + } + }); + + return $.mage.trimInput; +}); diff --git a/lib/web/modernizr/modernizr.js b/lib/web/modernizr/modernizr.js index 9b4f68aaaaaa9..0833cfb105cee 100644 --- a/lib/web/modernizr/modernizr.js +++ b/lib/web/modernizr/modernizr.js @@ -910,7 +910,7 @@ window.Modernizr = (function( window, document, undefined ) { bool = inputElem.checkValidity && inputElem.checkValidity() === false; } else { - // If the upgraded input compontent rejects the :) text, we got a winner + // If the upgraded input component rejects the :) text, we got a winner bool = inputElem.value != smile; } } diff --git a/lib/web/tiny_mce/classes/Formatter.js b/lib/web/tiny_mce/classes/Formatter.js index 0cbca75ec504b..5f05d3f3015ad 100644 --- a/lib/web/tiny_mce/classes/Formatter.js +++ b/lib/web/tiny_mce/classes/Formatter.js @@ -445,7 +445,7 @@ childCount = getChildCount(node); // Remove empty nodes but only if there is multiple wrappers and they are not block - // elements so never remove single

since that would remove the currrent empty block element where the caret is at + // elements so never remove single

since that would remove the current empty block element where the caret is at if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { dom.remove(node, 1); return; diff --git a/lib/web/tiny_mce/classes/dom/DOMUtils.js b/lib/web/tiny_mce/classes/dom/DOMUtils.js index 783dbea1cacb9..eb8b4b7ab5d78 100644 --- a/lib/web/tiny_mce/classes/dom/DOMUtils.js +++ b/lib/web/tiny_mce/classes/dom/DOMUtils.js @@ -1106,7 +1106,7 @@ /** * Returns a unique id. This can be useful when generating elements on the fly. - * This method will not check if the element allready exists. + * This method will not check if the element already exists. * * @method uniqueId * @param {String} p Optional prefix to add infront of all ids defaults to "mce_". diff --git a/lib/web/tiny_mce/tiny_mce_jquery_src.js b/lib/web/tiny_mce/tiny_mce_jquery_src.js index 0c03d0d0ade44..8b474eee25796 100644 --- a/lib/web/tiny_mce/tiny_mce_jquery_src.js +++ b/lib/web/tiny_mce/tiny_mce_jquery_src.js @@ -14451,7 +14451,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { childCount = getChildCount(node); // Remove empty nodes but only if there is multiple wrappers and they are not block - // elements so never remove single

since that would remove the currrent empty block element where the caret is at + // elements so never remove single

since that would remove the current empty block element where the caret is at if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { dom.remove(node, 1); return; diff --git a/lib/web/tiny_mce/tiny_mce_prototype_src.js b/lib/web/tiny_mce/tiny_mce_prototype_src.js index 0eb43989cb919..b6f9a42b48e7e 100644 --- a/lib/web/tiny_mce/tiny_mce_prototype_src.js +++ b/lib/web/tiny_mce/tiny_mce_prototype_src.js @@ -15301,7 +15301,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { childCount = getChildCount(node); // Remove empty nodes but only if there is multiple wrappers and they are not block - // elements so never remove single

since that would remove the currrent empty block element where the caret is at + // elements so never remove single

since that would remove the current empty block element where the caret is at if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { dom.remove(node, 1); return; diff --git a/lib/web/tiny_mce/tiny_mce_src.js b/lib/web/tiny_mce/tiny_mce_src.js index 7189ca9e1592d..e64998971ef7f 100644 --- a/lib/web/tiny_mce/tiny_mce_src.js +++ b/lib/web/tiny_mce/tiny_mce_src.js @@ -15275,7 +15275,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { childCount = getChildCount(node); // Remove empty nodes but only if there is multiple wrappers and they are not block - // elements so never remove single

since that would remove the currrent empty block element where the caret is at + // elements so never remove single

since that would remove the current empty block element where the caret is at if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { dom.remove(node, 1); return; diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index 9d8502feb27c9..4a7a55c70c4bf 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -1,6 +1,6 @@ + * * {bool} * *