-
+ |
= /* @escapeNotVerified */ $block->getActions($_item) ?>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/cart/estimate-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/estimate-service.js
index 76e3d911e7d3f..54e496131972e 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/cart/estimate-service.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/estimate-service.js
@@ -14,55 +14,71 @@ define([
'use strict';
var rateProcessors = [],
- totalsProcessors = [];
+ totalsProcessors = [],
- quote.shippingAddress.subscribe(function () {
- var type = quote.shippingAddress().getType();
+ /**
+ * Estimate totals for shipping address and update shipping rates.
+ */
+ estimateTotalsAndUpdateRates = function () {
+ var type = quote.shippingAddress().getType();
- if (
- quote.isVirtual() ||
- window.checkoutConfig.activeCarriers && window.checkoutConfig.activeCarriers.length === 0
- ) {
- // update totals block when estimated address was set
- totalsProcessors['default'] = totalsDefaultProvider;
- totalsProcessors[type] ?
- totalsProcessors[type].estimateTotals(quote.shippingAddress()) :
- totalsProcessors['default'].estimateTotals(quote.shippingAddress());
- } else {
- // check if user data not changed -> load rates from cache
- if (!cartCache.isChanged('address', quote.shippingAddress()) &&
- !cartCache.isChanged('cartVersion', customerData.get('cart')()['data_id']) &&
- cartCache.get('rates')
+ if (
+ quote.isVirtual() ||
+ window.checkoutConfig.activeCarriers && window.checkoutConfig.activeCarriers.length === 0
) {
- shippingService.setShippingRates(cartCache.get('rates'));
+ // update totals block when estimated address was set
+ totalsProcessors['default'] = totalsDefaultProvider;
+ totalsProcessors[type] ?
+ totalsProcessors[type].estimateTotals(quote.shippingAddress()) :
+ totalsProcessors['default'].estimateTotals(quote.shippingAddress());
+ } else {
+ // check if user data not changed -> load rates from cache
+ if (!cartCache.isChanged('address', quote.shippingAddress()) &&
+ !cartCache.isChanged('cartVersion', customerData.get('cart')()['data_id']) &&
+ cartCache.get('rates')
+ ) {
+ shippingService.setShippingRates(cartCache.get('rates'));
- return;
+ return;
+ }
+
+ // update rates list when estimated address was set
+ rateProcessors['default'] = defaultProcessor;
+ rateProcessors[type] ?
+ rateProcessors[type].getRates(quote.shippingAddress()) :
+ rateProcessors['default'].getRates(quote.shippingAddress());
+
+ // save rates to cache after load
+ shippingService.getShippingRates().subscribe(function (rates) {
+ cartCache.set('rates', rates);
+ });
}
+ },
- // update rates list when estimated address was set
- rateProcessors['default'] = defaultProcessor;
- rateProcessors[type] ?
- rateProcessors[type].getRates(quote.shippingAddress()) :
- rateProcessors['default'].getRates(quote.shippingAddress());
+ /**
+ * Estimate totals for shipping address.
+ */
+ estimateTotalsShipping = function () {
+ totalsDefaultProvider.estimateTotals(quote.shippingAddress());
+ },
- // save rates to cache after load
- shippingService.getShippingRates().subscribe(function (rates) {
- cartCache.set('rates', rates);
- });
- }
- });
- quote.shippingMethod.subscribe(function () {
- totalsDefaultProvider.estimateTotals(quote.shippingAddress());
- });
- quote.billingAddress.subscribe(function () {
- var type = quote.billingAddress().getType();
+ /**
+ * Estimate totals for billing address.
+ */
+ estimateTotalsBilling = function () {
+ var type = quote.billingAddress().getType();
+
+ if (quote.isVirtual()) {
+ // update totals block when estimated address was set
+ totalsProcessors['default'] = totalsDefaultProvider;
+ totalsProcessors[type] ?
+ totalsProcessors[type].estimateTotals(quote.billingAddress()) :
+ totalsProcessors['default'].estimateTotals(quote.billingAddress());
+ }
+ };
- if (quote.isVirtual()) {
- // update totals block when estimated address was set
- totalsProcessors['default'] = totalsDefaultProvider;
- totalsProcessors[type] ?
- totalsProcessors[type].estimateTotals(quote.billingAddress()) :
- totalsProcessors['default'].estimateTotals(quote.billingAddress());
- }
- });
+ quote.shippingAddress.subscribe(estimateTotalsAndUpdateRates);
+ quote.shippingMethod.subscribe(estimateTotalsShipping);
+ quote.billingAddress.subscribe(estimateTotalsBilling);
+ customerData.get('cart').subscribe(estimateTotalsShipping);
});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js
index 73f4df567903c..28e04699f8daf 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js
@@ -218,16 +218,31 @@ define([
* Apply resolved billing address to quote
*/
applyBillingAddress: function () {
- var shippingAddress;
+ var shippingAddress,
+ isBillingAddressInitialized;
if (quote.billingAddress()) {
selectBillingAddress(quote.billingAddress());
return;
}
+
+ if (quote.isVirtual()) {
+ isBillingAddressInitialized = addressList.some(function (addrs) {
+ if (addrs.isDefaultBilling()) {
+ selectBillingAddress(addrs);
+
+ return true;
+ }
+
+ return false;
+ });
+ }
+
shippingAddress = quote.shippingAddress();
- if (shippingAddress &&
+ if (!isBillingAddressInitialized &&
+ shippingAddress &&
shippingAddress.canUseForBilling() &&
(shippingAddress.isDefaultShipping() || !quote.isVirtual())
) {
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
index f9dae2691e5f3..7b858c92bee34 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
@@ -25,6 +25,8 @@ define([
if (countryId) {
if (addressData.region && addressData.region['region_id']) {
regionId = addressData.region['region_id'];
+ } else if (!addressData['region_id']) {
+ regionId = undefined;
} else if (countryId === window.checkoutConfig.defaultCountryId) {
regionId = window.checkoutConfig.defaultRegionId;
}
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
index d31c0dca38116..fde88ebadb393 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
@@ -35,7 +35,7 @@ define([
var checkoutConfig = window.checkoutConfig,
validators = [],
observedElements = [],
- postcodeElement = null,
+ postcodeElements = [],
postcodeElementName = 'postcode';
validators.push(defaultValidator);
@@ -101,7 +101,7 @@ define([
if (element.index === postcodeElementName) {
this.bindHandler(element, delay);
- postcodeElement = element;
+ postcodeElements.push(element);
}
},
@@ -136,7 +136,13 @@ define([
if (!formPopUpState.isVisible()) {
clearTimeout(self.validateAddressTimeout);
self.validateAddressTimeout = setTimeout(function () {
- self.postcodeValidation();
+ if (element.index === postcodeElementName) {
+ self.postcodeValidation(element);
+ } else {
+ $.each(postcodeElements, function (index, elem) {
+ self.postcodeValidation(elem);
+ });
+ }
self.validateFields();
}, delay);
}
@@ -148,8 +154,8 @@ define([
/**
* @return {*}
*/
- postcodeValidation: function () {
- var countryId = $('select[name="country_id"]').val(),
+ postcodeValidation: function (postcodeElement) {
+ var countryId = $('select[name="country_id"]:visible').val(),
validationResult,
warnMessage;
@@ -178,8 +184,8 @@ define([
*/
validateFields: function () {
var addressFlat = addressConverter.formDataProviderToFlatData(
- this.collectObservedData(),
- 'shippingAddress'
+ this.collectObservedData(),
+ 'shippingAddress'
),
address;
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
index 3a6574bff8948..447d626b339bd 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
@@ -35,9 +35,8 @@ define([
saveShippingInformation: function () {
var payload;
- if (!quote.billingAddress()) {
- selectBillingAddressAction(quote.shippingAddress());
- }
+ /* Assign selected address every time buyer selects address*/
+ selectBillingAddressAction(quote.shippingAddress());
payload = {
addressInformation: {
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
index 6b5d08c2641cc..6f9a1a46826da 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js
@@ -17,7 +17,8 @@ define([
'Magento_Customer/js/customer-data',
'Magento_Checkout/js/action/set-billing-address',
'Magento_Ui/js/model/messageList',
- 'mage/translate'
+ 'mage/translate',
+ 'Magento_Checkout/js/model/shipping-rates-validator'
],
function (
ko,
@@ -33,7 +34,8 @@ function (
customerData,
setBillingAddressAction,
globalMessageList,
- $t
+ $t,
+ shippingRatesValidator
) {
'use strict';
@@ -71,6 +73,7 @@ function (
quote.paymentMethod.subscribe(function () {
checkoutDataResolver.resolveBillingAddress();
}, this);
+ shippingRatesValidator.initFields(this.get('name') + '.form-fields');
},
/**
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js b/app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js
index 90ad07da0ae37..50bbeb30509b7 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js
@@ -33,6 +33,9 @@ define([
listens: {
email: 'emailHasChanged',
emailFocused: 'validateEmail'
+ },
+ ignoreTmpls: {
+ email: true
}
},
checkDelay: 2000,
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js
index e4b1e464348b9..db49683129f2b 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js
@@ -24,11 +24,17 @@ define([
/** @inheritdoc */
initialize: function () {
+ var stepsValue;
+
this._super();
$(window).hashchange(_.bind(stepNavigator.handleHash, stepNavigator));
if (!window.location.hash) {
- stepNavigator.setHash(stepNavigator.steps().sort(stepNavigator.sortItems)[0].code);
+ stepsValue = stepNavigator.steps();
+
+ if (stepsValue.length) {
+ stepNavigator.setHash(stepsValue.sort(stepNavigator.sortItems)[0].code);
+ }
}
stepNavigator.handleHash();
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
index cc1d960bbe44b..ea521b3a8afd4 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
@@ -8,7 +8,7 @@
- ,
+ ,
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
index 05ced7a978f82..2a5dc27328a43 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
@@ -8,7 +8,7 @@
- ,
+ ,
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
index 97286a28552d2..541413955cb47 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
@@ -8,7 +8,7 @@
- ,
+ ,
diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json
index a53558981e2f8..c6c2102600974 100644
--- a/app/code/Magento/CheckoutAgreements/composer.json
+++ b/app/code/Magento/CheckoutAgreements/composer.json
@@ -10,7 +10,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php
index 890c9bf5eae52..f7970b0a93ca9 100644
--- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php
+++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php
@@ -79,7 +79,7 @@ public function execute()
$filesystem = $this->_objectManager->get(\Magento\Framework\Filesystem::class);
$dir = $filesystem->getDirectoryRead(DirectoryList::MEDIA);
$filePath = $path . '/' . \Magento\Framework\File\Uploader::getCorrectFileName($file);
- if ($dir->isFile($dir->getRelativePath($filePath))) {
+ if ($dir->isFile($dir->getRelativePath($filePath)) && !preg_match('/^\.htaccess$/', $file)) {
$this->getStorage()->deleteFile($filePath);
}
}
diff --git a/app/code/Magento/Cms/Test/Mftf/Page/StorefrontHomePage.xml b/app/code/Magento/Cms/Test/Mftf/Page/StorefrontHomePage.xml
index fe1719a640070..571eb702bacfc 100644
--- a/app/code/Magento/Cms/Test/Mftf/Page/StorefrontHomePage.xml
+++ b/app/code/Magento/Cms/Test/Mftf/Page/StorefrontHomePage.xml
@@ -11,5 +11,6 @@
+
diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json
index 64e97e0a38e18..3f425e91b89e2 100644
--- a/app/code/Magento/Cms/composer.json
+++ b/app/code/Magento/Cms/composer.json
@@ -18,7 +18,7 @@
"magento/module-cms-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "102.0.6",
+ "version": "102.0.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_wysiwyg_images_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_wysiwyg_images_index.xml
index 1bc8828ef6c8e..5bf66ef302f04 100644
--- a/app/code/Magento/Cms/view/adminhtml/layout/cms_wysiwyg_images_index.xml
+++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_wysiwyg_images_index.xml
@@ -9,7 +9,11 @@
-
+
+
+ Magento\Backend\Block\DataProviders\UploadConfig
+
+
diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml
index f87dc07dc04f4..b26188f25f3ef 100644
--- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml
+++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml
@@ -7,6 +7,14 @@
// @codingStandardsIgnoreFile
/** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content\Uploader */
+
+$resizeConfig = $block->getImageUploadConfigData()->getIsResizeEnabled()
+ ? "{action: 'resize', maxWidth: "
+ . $block->getImageUploadMaxWidth()
+ . ", maxHeight: "
+ . $block->getImageUploadMaxHeight()
+ . "}"
+ : "{action: 'resize'}";
?>
@@ -99,11 +107,9 @@ require([
action: 'load',
fileTypes: /^image\/(gif|jpeg|png)$/,
maxFileSize: = (int) $block->getFileSizeService()->getMaxFileSize() ?> * 10
- }, {
- action: 'resize',
- maxWidth: = (int) $block->getImageUploadMaxWidth() ?> ,
- maxHeight: = (int) $block->getImageUploadMaxHeight() ?>
- }, {
+ },
+ = /* @noEscape */ $resizeConfig ?>,
+ {
action: 'save'
}]
});
diff --git a/app/code/Magento/CmsUrlRewrite/composer.json b/app/code/Magento/CmsUrlRewrite/composer.json
index 414dcdf54921d..abd8ad9fe2916 100644
--- a/app/code/Magento/CmsUrlRewrite/composer.json
+++ b/app/code/Magento/CmsUrlRewrite/composer.json
@@ -9,7 +9,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php
index c6e2412f7e58f..0472c5daa276f 100644
--- a/app/code/Magento/Config/Model/Config.php
+++ b/app/code/Magento/Config/Model/Config.php
@@ -237,13 +237,14 @@ private function getField(string $sectionId, string $groupId, string $fieldId):
* Get field path
*
* @param Field $field
+ * @param string $fieldId Need for support of clone_field feature
* @param array &$oldConfig Need for compatibility with _processGroup()
* @param array &$extraOldGroups Need for compatibility with _processGroup()
* @return string
*/
- private function getFieldPath(Field $field, array &$oldConfig, array &$extraOldGroups): string
+ private function getFieldPath(Field $field, string $fieldId, array &$oldConfig, array &$extraOldGroups): string
{
- $path = $field->getGroupPath() . '/' . $field->getId();
+ $path = $field->getGroupPath() . '/' . $fieldId;
/**
* Look for custom defined field path
@@ -303,7 +304,7 @@ private function getChangedPaths(
if (isset($groupData['fields'])) {
foreach ($groupData['fields'] as $fieldId => $fieldData) {
$field = $this->getField($sectionId, $groupId, $fieldId);
- $path = $this->getFieldPath($field, $oldConfig, $extraOldGroups);
+ $path = $this->getFieldPath($field, $fieldId, $oldConfig, $extraOldGroups);
if ($this->isValueChanged($oldConfig, $path, $fieldData)) {
$changedPaths[] = $path;
}
@@ -398,7 +399,7 @@ protected function _processGroup(
$backendModel->addData($data);
$this->_checkSingleStoreMode($field, $backendModel);
- $path = $this->getFieldPath($field, $extraOldGroups, $oldConfig);
+ $path = $this->getFieldPath($field, $fieldId, $extraOldGroups, $oldConfig);
$backendModel->setPath($path)->setValue($fieldData['value']);
$inherit = !empty($fieldData['inherit']);
diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json
index e43c9b0382e25..793d423280414 100644
--- a/app/code/Magento/Config/composer.json
+++ b/app/code/Magento/Config/composer.json
@@ -13,7 +13,7 @@
"magento/module-deploy": "100.2.*"
},
"type": "magento2-module",
- "version": "101.0.6",
+ "version": "101.0.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ConfigurableImportExport/composer.json b/app/code/Magento/ConfigurableImportExport/composer.json
index b2070fe7ebc44..253d2b39b9881 100644
--- a/app/code/Magento/ConfigurableImportExport/composer.json
+++ b/app/code/Magento/ConfigurableImportExport/composer.json
@@ -11,7 +11,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php
index 5cd8b6a7d0b95..b5940e36aa792 100644
--- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php
@@ -158,7 +158,7 @@ protected function getVariationMatrix()
$configurableMatrix = json_decode($configurableMatrix, true);
foreach ($configurableMatrix as $item) {
- if ($item['newProduct']) {
+ if (isset($item['newProduct']) && $item['newProduct']) {
$result[$item['variationKey']] = $this->mapData($item);
if (isset($item['qty'])) {
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php b/app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php
index d63ff06b7a483..ef757902097e4 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php
@@ -13,9 +13,10 @@
use Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Catalog\Model\Product;
+use Magento\Store\Model\ScopeInterface;
/**
- * {@inheritdoc}
+ * Resolves the product from a configured item.
*/
class ItemProductResolver implements ItemResolverInterface
{
@@ -38,7 +39,10 @@ public function __construct(ScopeConfigInterface $scopeConfig)
}
/**
- * {@inheritdoc}
+ * Get the final product from a configured item by product type and selection.
+ *
+ * @param ItemInterface $item
+ * @return ProductInterface
*/
public function getFinalProduct(ItemInterface $item): ProductInterface
{
@@ -46,20 +50,11 @@ public function getFinalProduct(ItemInterface $item): ProductInterface
* Show parent product thumbnail if it must be always shown according to the related setting in system config
* or if child thumbnail is not available.
*/
- $parentProduct = $item->getProduct();
- $finalProduct = $parentProduct;
+ $finalProduct = $item->getProduct();
$childProduct = $this->getChildProduct($item);
- if ($childProduct !== $parentProduct) {
- $configValue = $this->scopeConfig->getValue(
- self::CONFIG_THUMBNAIL_SOURCE,
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- );
- $childThumb = $childProduct->getData('thumbnail');
- $finalProduct =
- ($configValue == Thumbnail::OPTION_USE_PARENT_IMAGE) || (!$childThumb || $childThumb == 'no_selection')
- ? $parentProduct
- : $childProduct;
+ if ($childProduct !== null && $this->isUseChildProduct($childProduct)) {
+ $finalProduct = $childProduct;
}
return $finalProduct;
@@ -69,17 +64,30 @@ public function getFinalProduct(ItemInterface $item): ProductInterface
* Get item configurable child product.
*
* @param ItemInterface $item
- * @return Product
+ * @return Product|null
*/
- private function getChildProduct(ItemInterface $item): Product
+ private function getChildProduct(ItemInterface $item)
{
$option = $item->getOptionByCode('simple_product');
- $product = $item->getProduct();
- if ($option) {
- $product = $option->getProduct();
- }
+ return $option ? $option->getProduct() : null;
+ }
- return $product;
+ /**
+ * Is need to use child product
+ *
+ * @param Product $childProduct
+ * @return bool
+ */
+ private function isUseChildProduct(Product $childProduct): bool
+ {
+ $configValue = $this->scopeConfig->getValue(
+ self::CONFIG_THUMBNAIL_SOURCE,
+ ScopeInterface::SCOPE_STORE
+ );
+ $childThumb = $childProduct->getData('thumbnail');
+ return $configValue !== Thumbnail::OPTION_USE_PARENT_IMAGE
+ && $childThumb !== null
+ && $childThumb !== 'no_selection';
}
}
diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php
new file mode 100644
index 0000000000000..34e04c107d0a8
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php
@@ -0,0 +1,64 @@
+getProductToValidate($subject, $model);
+ if ($model->getProduct() !== $product) {
+ // We need to replace product only for validation and keep original product for all other cases.
+ $clone = clone $model;
+ $clone->setProduct($product);
+ $model = $clone;
+ }
+
+ return [$model];
+ }
+
+ /**
+ * @param \Magento\SalesRule\Model\Rule\Condition\Product $subject
+ * @param \Magento\Framework\Model\AbstractModel $model
+ *
+ * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product
+ */
+ private function getProductToValidate(
+ \Magento\SalesRule\Model\Rule\Condition\Product $subject,
+ \Magento\Framework\Model\AbstractModel $model
+ ) {
+ /** @var \Magento\Catalog\Model\Product $product */
+ $product = $model->getProduct();
+
+ $attrCode = $subject->getAttribute();
+
+ /* Check for attributes which are not available for configurable products */
+ if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) {
+ /** @var \Magento\Catalog\Model\AbstractModel $childProduct */
+ $childProduct = current($model->getChildren())->getProduct();
+ if ($childProduct->hasData($attrCode)) {
+ $product = $childProduct;
+ }
+ }
+
+ return $product;
+ }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
index 62ad21a24ac7e..1ff78a632c3bb 100644
--- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
+++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
@@ -7,11 +7,11 @@
use Magento\Catalog\Model\Product;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
-use Magento\Framework\Setup\UpgradeDataInterface;
-use Magento\Framework\Setup\ModuleContextInterface;
-use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
+use Magento\Framework\Setup\ModuleContextInterface;
+use Magento\Framework\Setup\ModuleDataSetupInterface;
+use Magento\Framework\Setup\UpgradeDataInterface;
/**
* Upgrade Data script
@@ -62,6 +62,10 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface
}
}
+ if (version_compare($context->getVersion(), '2.2.2', '<')) {
+ $this->upgradeQuoteItemPrice($setup);
+ }
+
$setup->endSetup();
}
@@ -97,4 +101,30 @@ private function updateRelatedProductTypes(string $attributeId, array $relatedPr
implode(',', $relatedProductTypes)
);
}
+
+ /**
+ * Update 'price' value for quote items without price of configurable products subproducts.
+ *
+ * @param ModuleDataSetupInterface $setup
+ */
+ private function upgradeQuoteItemPrice(ModuleDataSetupInterface $setup)
+ {
+ $connection = $setup->getConnection();
+ $quoteItemTable = $setup->getTable('quote_item');
+ $select = $connection->select();
+ $select->joinLeft(
+ ['qi2' => $quoteItemTable],
+ 'qi1.parent_item_id = qi2.item_id',
+ ['price']
+ )->where(
+ 'qi1.price = 0'
+ . ' AND qi1.parent_item_id IS NOT NULL'
+ . ' AND qi2.product_type = "' . Configurable::TYPE_CODE . '"'
+ );
+ $updateQuoteItem = $setup->getConnection()->updateFromSelect(
+ $select,
+ ['qi1' => $quoteItemTable]
+ );
+ $setup->getConnection()->query($updateQuoteItem);
+ }
}
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml
new file mode 100644
index 0000000000000..d918649ed4914
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateApiConfigurableProductActionGroup.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{productName}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductActionGroup.xml
new file mode 100644
index 0000000000000..3b4e7f55d186c
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductActionGroup.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductWithExcludingOptionsActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductWithExcludingOptionsActionGroup.xml
new file mode 100644
index 0000000000000..c4485ab5f5c9b
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/AdminCreateConfigurableProductWithExcludingOptionsActionGroup.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml
index 83e0aa1deaedf..a2f824dd8864e 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
configurable
configurable
@@ -38,4 +38,15 @@
EavStockItem
CustomAttributeCategoryIds
+
+ api-configurable-product-with-out-category
+ configurable
+ 4
+ 4
+ API Configurable Product
+ api-configurable-product
+ 1
+ 100
+ EavStockItem
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductOptionData.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductOptionData.xml
index 21dcf998a6399..e98175bc8d40b 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductOptionData.xml
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductOptionData.xml
@@ -7,11 +7,18 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
option
ValueIndex1
ValueIndex2
+
+
+ option
+ ValueIndex1
+ ValueIndex2
+ ValueIndex3
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ValueIndexData.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ValueIndexData.xml
index 54d489a446fd7..e1cd70790a6b2 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ValueIndexData.xml
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ValueIndexData.xml
@@ -7,11 +7,14 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminNewAttributePanelSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminNewAttributePanelSection.xml
index 86e22554d95f0..429d535952f76 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminNewAttributePanelSection.xml
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminNewAttributePanelSection.xml
@@ -19,5 +19,7 @@
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
index 996a392230eea..be0c2b05e48ba 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
@@ -13,5 +13,6 @@
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml
new file mode 100644
index 0000000000000..d07ff3ec4d656
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5.00
+
+
+
+ 10.00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.00
+
+
+
+
+ 20.00
+
+
+
+
+ 25.00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Configuration/Item/ItemProductResolverTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Configuration/Item/ItemProductResolverTest.php
index 28e3e5e4cb5c6..8df6dddc3eb5a 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Configuration/Item/ItemProductResolverTest.php
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Configuration/Item/ItemProductResolverTest.php
@@ -3,7 +3,6 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-
declare(strict_types=1);
namespace Magento\ConfigurableProduct\Test\Unit\Model\Product\Configuration\Item;
@@ -14,86 +13,148 @@
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
use Magento\ConfigurableProduct\Model\Product\Configuration\Item\ItemProductResolver;
use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
-use Magento\Store\Model\ScopeInterface;
+use Magento\Quote\Model\Quote\Item\Option;
+use PHPUnit\Framework\TestCase;
/**
- * Tests \Magento\ConfigurableProduct\Model\Product\Configuration\Item\ItemProductResolver
+ * ItemProductResolver test
*/
-class ItemProductResolverTest extends \PHPUnit\Framework\TestCase
+class ItemProductResolverTest extends TestCase
{
/**
* @var ItemProductResolver
*/
- private $resolver;
+ private $model;
/**
- * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var ItemInterface | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $item;
+
+ /**
+ * @var Product | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $parentProduct;
+
+ /**
+ * @var ScopeConfigInterface | \PHPUnit_Framework_MockObject_MockObject
*/
private $scopeConfig;
/**
- * @inheritdoc
+ * @var OptionInterface | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $option;
+
+ /**
+ * @var Product | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $childProduct;
+
+ /**
+ * Set up method
+ *
+ * @return void
*/
protected function setUp()
{
- $objectManagerHelper = new ObjectManager($this);
- $this->scopeConfig = $this->createPartialMock(ScopeConfigInterface::class, ['getValue', 'isSetFlag']);
- $this->resolver = $objectManagerHelper->getObject(
- ItemProductResolver::class,
- ['scopeConfig' => $this->scopeConfig]
- );
+ parent::setUp();
+
+ $this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parentProduct = $this->getMockBuilder(Product::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->parentProduct
+ ->method('getSku')
+ ->willReturn('parent_product');
+
+ $this->childProduct = $this->getMockBuilder(Product::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->childProduct
+ ->method('getSku')
+ ->willReturn('child_product');
+
+ $this->option = $this->getMockBuilder(Option::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->option
+ ->method('getProduct')
+ ->willReturn($this->childProduct);
+
+ $this->item = $this->getMockBuilder(ItemInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->item
+ ->expects($this->once())
+ ->method('getProduct')
+ ->willReturn($this->parentProduct);
+
+ $this->model = new ItemProductResolver($this->scopeConfig);
}
/**
- * @param bool $existOption
- * @param string $configImageSource
+ * Test for deleted child product from configurable product
+ *
* @return void
- * @dataProvider getFinalProductDataProvider
*/
- public function testGetFinalProduct(bool $existOption, string $configImageSource)
+ public function testGetFinalProductChildIsNull()
{
- $option = null;
- $parentProduct = $this->createMock(Product::class);
- $finalProduct = $parentProduct;
-
- if ($existOption) {
- $childProduct = $this->createPartialMock(Product::class, ['getData']);
- $childProduct->expects($this->once())->method('getData')->with('thumbnail')->willReturn('someImage');
-
- $option = $this->createPartialMock(
- OptionInterface::class,
- ['getProduct', 'getValue']
- );
- $option->expects($this->once())->method('getProduct')->willReturn($childProduct);
-
- $this->scopeConfig->expects($this->once())
- ->method('getValue')
- ->with(ItemProductResolver::CONFIG_THUMBNAIL_SOURCE, ScopeInterface::SCOPE_STORE)
- ->willReturn($configImageSource);
-
- $finalProduct = ($configImageSource == Thumbnail::OPTION_USE_PARENT_IMAGE) ? $parentProduct : $childProduct;
- }
-
- $item = $this->createPartialMock(
- ItemInterface::class,
- ['getProduct', 'getOptionByCode', 'getFileDownloadParams']
+ $this->item->method('getOptionByCode')
+ ->willReturn(null);
+
+ $finalProduct = $this->model->getFinalProduct($this->item);
+ $this->assertEquals(
+ $this->parentProduct->getSku(),
+ $finalProduct->getSku()
);
- $item->expects($this->exactly(2))->method('getProduct')->willReturn($parentProduct);
- $item->expects($this->once())->method('getOptionByCode')->with('simple_product')->willReturn($option);
+ }
- $this->assertEquals($finalProduct, $this->resolver->getFinalProduct($item));
+ /**
+ * Tests child product from configurable product
+ *
+ * @dataProvider provideScopeConfig
+ * @param string $expectedSku
+ * @param string $scopeValue
+ * @param string | null $thumbnail
+ * @return void
+ */
+ public function testGetFinalProductChild($expectedSku, $scopeValue, $thumbnail)
+ {
+ $this->item->method('getOptionByCode')
+ ->willReturn($this->option);
+
+ $this->childProduct->method('getData')
+ ->willReturn($thumbnail);
+
+ $this->scopeConfig->method('getValue')
+ ->willReturn($scopeValue);
+
+ $finalProduct = $this->model->getFinalProduct($this->item);
+ $this->assertEquals($expectedSku, $finalProduct->getSku());
}
/**
+ * Data provider for scope test
+ *
* @return array
*/
- public function getFinalProductDataProvider(): array
+ public function provideScopeConfig(): array
{
return [
- [false, Thumbnail::OPTION_USE_PARENT_IMAGE],
- [true, Thumbnail::OPTION_USE_PARENT_IMAGE],
- [true, Thumbnail::OPTION_USE_OWN_IMAGE],
+ ['child_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'thumbnail'],
+ ['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'thumbnail'],
+
+ ['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, null],
+ ['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'no_selection'],
+
+ ['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, null],
+ ['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'no_selection'],
];
}
}
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php
new file mode 100644
index 0000000000000..54b7b71dd5ed8
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php
@@ -0,0 +1,226 @@
+objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ $this->validator = $this->createValidator();
+ $this->validatorPlugin = $this->objectManager->getObject(ValidatorPlugin::class);
+ }
+
+ /**
+ * @return \Magento\SalesRule\Model\Rule\Condition\Product
+ */
+ private function createValidator(): SalesRuleProduct
+ {
+ /** @var Context|\PHPUnit_Framework_MockObject_MockObject $contextMock */
+ $contextMock = $this->getMockBuilder(Context::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var Data|\PHPUnit_Framework_MockObject_MockObject $backendHelperMock */
+ $backendHelperMock = $this->getMockBuilder(Data::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var Config|\PHPUnit_Framework_MockObject_MockObject $configMock */
+ $configMock = $this->getMockBuilder(Config::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject $productFactoryMock */
+ $productFactoryMock = $this->getMockBuilder(ProductFactory::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $productRepositoryMock */
+ $productRepositoryMock = $this->getMockBuilder(ProductRepositoryInterface::class)
+ ->getMockForAbstractClass();
+ $attributeLoaderInterfaceMock = $this->getMockBuilder(AbstractEntity::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getAttributesByCode'])
+ ->getMock();
+ $attributeLoaderInterfaceMock
+ ->expects($this->any())
+ ->method('getAttributesByCode')
+ ->willReturn([]);
+ /** @var Product|\PHPUnit_Framework_MockObject_MockObject $productMock */
+ $productMock = $this->getMockBuilder(Product::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['loadAllAttributes', 'getConnection', 'getTable'])
+ ->getMock();
+ $productMock->expects($this->any())
+ ->method('loadAllAttributes')
+ ->willReturn($attributeLoaderInterfaceMock);
+ /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */
+ $collectionMock = $this->getMockBuilder(Collection::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var FormatInterface|\PHPUnit_Framework_MockObject_MockObject $formatMock */
+ $formatMock = new Format(
+ $this->getMockBuilder(ScopeResolverInterface::class)->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder(ResolverInterface::class)->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder(CurrencyFactory::class)->disableOriginalConstructor()->getMock()
+ );
+
+ return new SalesRuleProduct(
+ $contextMock,
+ $backendHelperMock,
+ $configMock,
+ $productFactoryMock,
+ $productRepositoryMock,
+ $productMock,
+ $collectionMock,
+ $formatMock
+ );
+ }
+
+ public function testChildIsUsedForValidation()
+ {
+ $configurableProductMock = $this->createProductMock();
+ $configurableProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Configurable::TYPE_CODE);
+ $configurableProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(false);
+
+ /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
+ $item = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setProduct', 'getProduct', 'getChildren'])
+ ->getMockForAbstractClass();
+ $item->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($configurableProductMock);
+
+ $simpleProductMock = $this->createProductMock();
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Type::TYPE_SIMPLE);
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(true);
+
+ $childItem = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getProduct'])
+ ->getMockForAbstractClass();
+ $childItem->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($simpleProductMock);
+
+ $item->expects($this->any())
+ ->method('getChildren')
+ ->willReturn([$childItem]);
+ $item->expects($this->once())
+ ->method('setProduct')
+ ->with($this->identicalTo($simpleProductMock));
+
+ $this->validator->setAttribute('special_price');
+
+ $this->validatorPlugin->beforeValidate($this->validator, $item);
+ }
+
+ /**
+ * @return Product|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createProductMock(): \PHPUnit_Framework_MockObject_MockObject
+ {
+ $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'getAttribute',
+ 'getId',
+ 'setQuoteItemQty',
+ 'setQuoteItemPrice',
+ 'getTypeId',
+ 'hasData',
+ ])
+ ->getMock();
+ $productMock
+ ->expects($this->any())
+ ->method('setQuoteItemQty')
+ ->willReturnSelf();
+ $productMock
+ ->expects($this->any())
+ ->method('setQuoteItemPrice')
+ ->willReturnSelf();
+
+ return $productMock;
+ }
+
+ public function testChildIsNotUsedForValidation()
+ {
+ $simpleProductMock = $this->createProductMock();
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Type::TYPE_SIMPLE);
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(true);
+
+ /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
+ $item = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setProduct', 'getProduct'])
+ ->getMockForAbstractClass();
+ $item->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($simpleProductMock);
+
+ $this->validator->setAttribute('special_price');
+
+ $this->validatorPlugin->beforeValidate($this->validator, $item);
+ }
+}
diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json
index 33ee30a25b012..74e611af2cbbc 100644
--- a/app/code/Magento/ConfigurableProduct/composer.json
+++ b/app/code/Magento/ConfigurableProduct/composer.json
@@ -19,12 +19,13 @@
"suggest": {
"magento/module-webapi": "100.2.*",
"magento/module-sales": "101.0.*",
+ "magento/module-sales-rule": "101.0.*",
"magento/module-product-video": "100.2.*",
"magento/module-configurable-sample-data": "Sample Data version:100.2.*",
"magento/module-product-links-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.6",
+ "version": "100.2.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml
index dfbad0dd5a764..e6e0da721e150 100644
--- a/app/code/Magento/ConfigurableProduct/etc/di.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/di.xml
@@ -125,6 +125,13 @@
+
+
+
+ - Magento\ConfigurableProduct\Model\ProductOptionProcessor
+
+
+
Magento\ConfigurableProduct\Pricing\Price\FinalPriceResolver
@@ -221,6 +228,9 @@
+
+
+
@@ -228,4 +238,11 @@
+
+
+
+ - false
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml
index 0b971ef775e16..b7d4c92aaa992 100644
--- a/app/code/Magento/ConfigurableProduct/etc/module.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/module.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
index 6b6c1762fadd9..78974877dd90d 100644
--- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
+++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
@@ -477,7 +477,9 @@ define([
_getPrices: function () {
var prices = {},
elements = _.toArray(this.options.settings),
- hasProductPrice = false;
+ hasProductPrice = false,
+ optionPriceDiff = 0,
+ allowedProduct, optionPrices, basePrice, optionFinalPrice;
_.each(elements, function (element) {
var selected = element.options[element.selectedIndex],
@@ -485,8 +487,23 @@ define([
priceValue = {};
if (config && config.allowedProducts.length === 1 && !hasProductPrice) {
+ prices = {};
priceValue = this._calculatePrice(config);
hasProductPrice = true;
+ } else if (element.value) {
+ allowedProduct = this._getAllowedProductWithMinPrice(config.allowedProducts);
+ optionPrices = this.options.spConfig.optionPrices;
+ basePrice = parseFloat(this.options.spConfig.prices.basePrice.amount);
+
+ if (!_.isEmpty(allowedProduct)) {
+ optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);
+ optionPriceDiff = optionFinalPrice - basePrice;
+ }
+
+ if (optionPriceDiff !== 0) {
+ prices = {};
+ priceValue = this._calculatePriceDifference(allowedProduct);
+ }
}
prices[element.attributeId] = priceValue;
@@ -495,6 +512,55 @@ define([
return prices;
},
+ /**
+ * Get product with minimum price from selected options.
+ *
+ * @param {Array} allowedProducts
+ * @returns {String}
+ * @private
+ */
+ _getAllowedProductWithMinPrice: function (allowedProducts) {
+ var optionPrices = this.options.spConfig.optionPrices,
+ product = {},
+ optionMinPrice, optionFinalPrice;
+
+ _.each(allowedProducts, function (allowedProduct) {
+ optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);
+
+ if (_.isEmpty(product)) {
+ optionMinPrice = optionFinalPrice;
+ product = allowedProduct;
+ }
+
+ if (optionFinalPrice < optionMinPrice) {
+ product = allowedProduct;
+ }
+ }, this);
+
+ return product;
+ },
+
+ /**
+ * Calculate price difference for allowed product
+ *
+ * @param {*} allowedProduct - Product
+ * @returns {*}
+ * @private
+ */
+ _calculatePriceDifference: function (allowedProduct) {
+ var displayPrices = $(this.options.priceHolderSelector).priceBox('option').prices,
+ newPrices = this.options.spConfig.optionPrices[allowedProduct];
+
+ _.each(displayPrices, function (price, code) {
+
+ if (newPrices[code]) {
+ displayPrices[code].amount = newPrices[code].amount - displayPrices[code].amount;
+ }
+ });
+
+ return displayPrices;
+ },
+
/**
* Returns prices for configured products
*
diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/options-updater.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/options-updater.js
index 558a1fdf31085..6f18798303151 100644
--- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/options-updater.js
+++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/options-updater.js
@@ -61,6 +61,7 @@ define([
this.setProductOptions(cartData());
this.updateOptions();
}.bind(this));
+ this.updateOptions();
},
/**
diff --git a/app/code/Magento/ConfigurableProductSales/composer.json b/app/code/Magento/ConfigurableProductSales/composer.json
index ca6638924b8c6..5baa9bef17e11 100644
--- a/app/code/Magento/ConfigurableProductSales/composer.json
+++ b/app/code/Magento/ConfigurableProductSales/composer.json
@@ -12,7 +12,7 @@
"magento/module-configurable-product": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json
index 49ac8ec40dbc4..72c8005c53432 100644
--- a/app/code/Magento/Contact/composer.json
+++ b/app/code/Magento/Contact/composer.json
@@ -10,7 +10,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cookie/composer.json b/app/code/Magento/Cookie/composer.json
index cc04b0ccd5d7d..ba4427e9681b5 100644
--- a/app/code/Magento/Cookie/composer.json
+++ b/app/code/Magento/Cookie/composer.json
@@ -10,7 +10,7 @@
"magento/module-backend": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json
index a8c124dc57207..ddbe7df2c0a2e 100644
--- a/app/code/Magento/Cron/composer.json
+++ b/app/code/Magento/Cron/composer.json
@@ -10,7 +10,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json
index da76425436038..021fe7ae9bc56 100644
--- a/app/code/Magento/CurrencySymbol/composer.json
+++ b/app/code/Magento/CurrencySymbol/composer.json
@@ -11,7 +11,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit.php b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit.php
index be2d143e7f864..0bf7f607a531b 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit.php
@@ -57,6 +57,8 @@ public function __construct(
* Update Save and Delete buttons. Remove Delete button if group can't be deleted.
*
* @return void
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
*/
protected function _construct()
{
@@ -68,6 +70,23 @@ protected function _construct()
$this->buttonList->update('save', 'label', __('Save Customer Group'));
$this->buttonList->update('delete', 'label', __('Delete Customer Group'));
+ $this->buttonList->update(
+ 'delete',
+ 'onclick',
+ sprintf(
+ "deleteConfirm('%s','%s', %s)",
+ 'Are you sure?',
+ $this->getDeleteUrl(),
+ json_encode(
+ [
+ 'action' => '',
+ 'data' => [
+ 'form_key' => $this->getFormKey()
+ ]
+ ]
+ )
+ )
+ );
$groupId = $this->coreRegistry->registry(RegistryConstants::CURRENT_GROUP_ID);
if (!$groupId || $this->groupManagement->isReadonly($groupId)) {
diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPassword.php b/app/code/Magento/Customer/Controller/Account/ForgotPassword.php
index f115b64efebdd..cd2c46ff53043 100644
--- a/app/code/Magento/Customer/Controller/Account/ForgotPassword.php
+++ b/app/code/Magento/Customer/Controller/Account/ForgotPassword.php
@@ -40,10 +40,17 @@ public function __construct(
/**
* Forgot customer password page
*
- * @return \Magento\Framework\View\Result\Page
+ * @return \Magento\Framework\Controller\Result\Redirect|\Magento\Framework\View\Result\Page
*/
public function execute()
{
+ if ($this->session->isLoggedIn()) {
+ /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
+ $resultRedirect = $this->resultRedirectFactory->create();
+ $resultRedirect->setPath('*/*/');
+ return $resultRedirect;
+ }
+
/** @var \Magento\Framework\View\Result\Page $resultPage */
$resultPage = $this->resultPageFactory->create();
$resultPage->getLayout()->getBlock('forgotPassword')->setEmailValue($this->session->getForgottenEmail());
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group/Delete.php b/app/code/Magento/Customer/Controller/Adminhtml/Group/Delete.php
index 571ef57702bc3..6fc9f45ab62ff 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Group/Delete.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Group/Delete.php
@@ -7,6 +7,7 @@
namespace Magento\Customer\Controller\Adminhtml\Group;
use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Exception\NotFoundException;
class Delete extends \Magento\Customer\Controller\Adminhtml\Group
{
@@ -14,9 +15,14 @@ class Delete extends \Magento\Customer\Controller\Adminhtml\Group
* Delete customer group.
*
* @return \Magento\Backend\Model\View\Result\Redirect
+ * @throws NotFoundException
*/
public function execute()
{
+ if (!$this->getRequest()->isPost()) {
+ throw new NotFoundException(__('Page not found'));
+ }
+
$id = $this->getRequest()->getParam('id');
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
diff --git a/app/code/Magento/Customer/Controller/Ajax/Login.php b/app/code/Magento/Customer/Controller/Ajax/Login.php
index 8664e0cbf87ea..9aa76d6202bc9 100644
--- a/app/code/Magento/Customer/Controller/Ajax/Login.php
+++ b/app/code/Magento/Customer/Controller/Ajax/Login.php
@@ -7,8 +7,6 @@
namespace Magento\Customer\Controller\Ajax;
use Magento\Customer\Api\AccountManagementInterface;
-use Magento\Framework\Exception\EmailNotConfirmedException;
-use Magento\Framework\Exception\InvalidEmailOrPasswordException;
use Magento\Framework\App\ObjectManager;
use Magento\Customer\Model\Account\Redirect as AccountRedirect;
use Magento\Framework\App\Config\ScopeConfigInterface;
@@ -70,6 +68,11 @@ class Login extends \Magento\Framework\App\Action\Action
*/
private $cookieMetadataFactory;
+ /**
+ * @var \Magento\Customer\Model\Session
+ */
+ private $customerSession;
+
/**
* Initialize Login controller
*
@@ -108,7 +111,6 @@ public function __construct(
/**
* Get account redirect.
- * For release backward compatibility.
*
* @deprecated 100.0.10
* @return AccountRedirect
@@ -134,6 +136,8 @@ public function setAccountRedirect($value)
}
/**
+ * Initializes config dependency.
+ *
* @deprecated 100.0.10
* @return ScopeConfigInterface
*/
@@ -146,6 +150,8 @@ protected function getScopeConfig()
}
/**
+ * Sets config dependency.
+ *
* @deprecated 100.0.10
* @param ScopeConfigInterface $value
* @return void
@@ -200,25 +206,17 @@ public function execute()
$response['redirectUrl'] = $this->_redirect->success($redirectRoute);
$this->getAccountRedirect()->clearRedirectCookie();
}
- } catch (EmailNotConfirmedException $e) {
- $response = [
- 'errors' => true,
- 'message' => $e->getMessage()
- ];
- } catch (InvalidEmailOrPasswordException $e) {
- $response = [
- 'errors' => true,
- 'message' => $e->getMessage()
- ];
} catch (LocalizedException $e) {
$response = [
'errors' => true,
- 'message' => $e->getMessage()
+ 'message' => $e->getMessage(),
+ 'captcha' => $this->customerSession->getData('user_login_show_captcha')
];
} catch (\Exception $e) {
$response = [
'errors' => true,
- 'message' => __('Invalid login or password.')
+ 'message' => __('Invalid login or password.'),
+ 'captcha' => $this->customerSession->getData('user_login_show_captcha')
];
}
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index 8f2565189ef4c..b5b1905e68d8d 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -670,8 +670,8 @@ public function resetPassword($email, $resetToken, $newPassword)
$customerSecure->setRpTokenCreatedAt(null);
$customerSecure->setPasswordHash($this->createPasswordHash($newPassword));
$this->getAuthentication()->unlock($customer->getId());
- $this->sessionManager->destroy();
$this->destroyCustomerSessions($customer->getId());
+ $this->sessionManager->destroy();
$this->customerRepository->save($customer);
return true;
diff --git a/app/code/Magento/Customer/Model/Authentication.php b/app/code/Magento/Customer/Model/Authentication.php
index 0967f1a0189e3..b0729647d7eec 100644
--- a/app/code/Magento/Customer/Model/Authentication.php
+++ b/app/code/Magento/Customer/Model/Authentication.php
@@ -167,7 +167,7 @@ public function authenticate($customerId, $password)
{
$customerSecure = $this->customerRegistry->retrieveSecureData($customerId);
$hash = $customerSecure->getPasswordHash();
- if (!$this->encryptor->validateHash($password, $hash)) {
+ if (!$hash || !$this->encryptor->validateHash($password, $hash)) {
$this->processAuthenticationFailure($customerId);
if ($this->isLocked($customerId)) {
throw new UserLockedException(__('The account is locked.'));
diff --git a/app/code/Magento/Customer/Model/GroupManagement.php b/app/code/Magento/Customer/Model/GroupManagement.php
index eb5d90f2fd7ea..48cb5d55061c5 100644
--- a/app/code/Magento/Customer/Model/GroupManagement.php
+++ b/app/code/Magento/Customer/Model/GroupManagement.php
@@ -15,7 +15,6 @@
use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
-use Magento\Framework\Data\Collection;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Model\StoreManagerInterface;
@@ -170,7 +169,7 @@ public function getLoggedInGroups()
->create();
$groupNameSortOrder = $this->sortOrderBuilder
->setField('customer_group_code')
- ->setDirection(Collection::SORT_ORDER_ASC)
+ ->setAscendingDirection()
->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilters($notLoggedInFilter)
diff --git a/app/code/Magento/Customer/Model/Indexer/Source.php b/app/code/Magento/Customer/Model/Indexer/Source.php
index e4bf03e08a9ad..983cda7063903 100644
--- a/app/code/Magento/Customer/Model/Indexer/Source.php
+++ b/app/code/Magento/Customer/Model/Indexer/Source.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Customer\Model\Indexer;
+use Magento\Customer\Model\ResourceModel\Customer\Indexer\CollectionFactory;
use Magento\Customer\Model\ResourceModel\Customer\Indexer\Collection;
use Magento\Framework\App\ResourceConnection\SourceProviderInterface;
use Traversable;
@@ -25,11 +26,11 @@ class Source implements \IteratorAggregate, \Countable, SourceProviderInterface
private $batchSize;
/**
- * @param \Magento\Customer\Model\ResourceModel\Customer\Indexer\CollectionFactory $collection
+ * @param CollectionFactory $collectionFactory
* @param int $batchSize
*/
public function __construct(
- \Magento\Customer\Model\ResourceModel\Customer\Indexer\CollectionFactory $collectionFactory,
+ CollectionFactory $collectionFactory,
$batchSize = 10000
) {
$this->customerCollection = $collectionFactory->create();
@@ -37,7 +38,7 @@ public function __construct(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getMainTable()
{
@@ -45,7 +46,7 @@ public function getMainTable()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getIdFieldName()
{
@@ -53,7 +54,7 @@ public function getIdFieldName()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function addFieldToSelect($fieldName, $alias = null)
{
@@ -62,7 +63,7 @@ public function addFieldToSelect($fieldName, $alias = null)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getSelect()
{
@@ -70,7 +71,7 @@ public function getSelect()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function addFieldToFilter($attribute, $condition = null)
{
@@ -79,7 +80,7 @@ public function addFieldToFilter($attribute, $condition = null)
}
/**
- * @return int
+ * @inheritdoc
*/
public function count()
{
@@ -105,4 +106,22 @@ public function getIterator()
$pageNumber++;
} while ($pageNumber <= $lastPage);
}
+
+ /**
+ * Joins Attribute
+ *
+ * @param string $alias alias for the joined attribute
+ * @param string|\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute
+ * @param string $bind attribute of the main entity to link with joined $filter
+ * @param string $filter primary key for the joined entity (entity_id default)
+ * @param string $joinType inner|left
+ * @param int|null $storeId
+ * @return void
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @see Collection::joinAttribute()
+ */
+ public function joinAttribute($alias, $attribute, $bind, $filter = null, $joinType = 'inner', $storeId = null)
+ {
+ $this->customerCollection->joinAttribute($alias, $attribute, $bind, $filter, $joinType, $storeId);
+ }
}
diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
index 29f97d9f643a7..9e745769e2c36 100644
--- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
+++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
@@ -7,69 +7,80 @@
namespace Magento\Customer\Model\ResourceModel;
use Magento\Customer\Api\CustomerMetadataInterface;
-use Magento\Customer\Model\Delegation\Data\NewOperation;
+use Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\CustomerRegistry;
+use Magento\Customer\Model\Data\CustomerSecureFactory;
use Magento\Customer\Model\Customer\NotificationStorage;
+use Magento\Customer\Model\Delegation\Data\NewOperation;
+use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\Api\ImageProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaInterface;
+use Magento\Framework\Api\Search\FilterGroup;
+use Magento\Framework\Event\ManagerInterface;
use Magento\Customer\Model\Delegation\Storage as DelegatedStorage;
use Magento\Framework\App\ObjectManager;
+use Magento\Store\Model\StoreManagerInterface;
/**
* Customer repository.
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyFields)
*/
-class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInterface
+class CustomerRepository implements CustomerRepositoryInterface
{
/**
- * @var \Magento\Customer\Model\CustomerFactory
+ * @var CustomerFactory
*/
protected $customerFactory;
/**
- * @var \Magento\Customer\Model\Data\CustomerSecureFactory
+ * @var CustomerSecureFactory
*/
protected $customerSecureFactory;
/**
- * @var \Magento\Customer\Model\CustomerRegistry
+ * @var CustomerRegistry
*/
protected $customerRegistry;
/**
- * @var \Magento\Customer\Model\ResourceModel\AddressRepository
+ * @var AddressRepository
*/
protected $addressRepository;
/**
- * @var \Magento\Customer\Model\ResourceModel\Customer
+ * @var Customer
*/
protected $customerResourceModel;
/**
- * @var \Magento\Customer\Api\CustomerMetadataInterface
+ * @var CustomerMetadataInterface
*/
protected $customerMetadata;
/**
- * @var \Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory
+ * @var CustomerSearchResultsInterfaceFactory
*/
protected $searchResultsFactory;
/**
- * @var \Magento\Framework\Event\ManagerInterface
+ * @var ManagerInterface
*/
protected $eventManager;
/**
- * @var \Magento\Store\Model\StoreManagerInterface
+ * @var StoreManagerInterface
*/
protected $storeManager;
/**
- * @var \Magento\Framework\Api\ExtensibleDataObjectConverter
+ * @var ExtensibleDataObjectConverter
*/
protected $extensibleDataObjectConverter;
@@ -84,7 +95,7 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte
protected $imageProcessor;
/**
- * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface
+ * @var JoinProcessorInterface
*/
protected $extensionAttributesJoinProcessor;
@@ -104,38 +115,38 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte
private $delegatedStorage;
/**
- * @param \Magento\Customer\Model\CustomerFactory $customerFactory
- * @param \Magento\Customer\Model\Data\CustomerSecureFactory $customerSecureFactory
- * @param \Magento\Customer\Model\CustomerRegistry $customerRegistry
- * @param \Magento\Customer\Model\ResourceModel\AddressRepository $addressRepository
- * @param \Magento\Customer\Model\ResourceModel\Customer $customerResourceModel
- * @param \Magento\Customer\Api\CustomerMetadataInterface $customerMetadata
- * @param \Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory $searchResultsFactory
- * @param \Magento\Framework\Event\ManagerInterface $eventManager
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
+ * @param CustomerFactory $customerFactory
+ * @param CustomerSecureFactory $customerSecureFactory
+ * @param CustomerRegistry $customerRegistry
+ * @param AddressRepository $addressRepository
+ * @param Customer $customerResourceModel
+ * @param CustomerMetadataInterface $customerMetadata
+ * @param CustomerSearchResultsInterfaceFactory $searchResultsFactory
+ * @param ManagerInterface $eventManager
+ * @param StoreManagerInterface $storeManager
+ * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
* @param DataObjectHelper $dataObjectHelper
* @param ImageProcessorInterface $imageProcessor
- * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor
+ * @param JoinProcessorInterface $extensionAttributesJoinProcessor
* @param CollectionProcessorInterface $collectionProcessor
* @param NotificationStorage $notificationStorage
* @param DelegatedStorage|null $delegatedStorage
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
- \Magento\Customer\Model\CustomerFactory $customerFactory,
- \Magento\Customer\Model\Data\CustomerSecureFactory $customerSecureFactory,
- \Magento\Customer\Model\CustomerRegistry $customerRegistry,
- \Magento\Customer\Model\ResourceModel\AddressRepository $addressRepository,
- \Magento\Customer\Model\ResourceModel\Customer $customerResourceModel,
- \Magento\Customer\Api\CustomerMetadataInterface $customerMetadata,
- \Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory $searchResultsFactory,
- \Magento\Framework\Event\ManagerInterface $eventManager,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+ CustomerFactory $customerFactory,
+ CustomerSecureFactory $customerSecureFactory,
+ CustomerRegistry $customerRegistry,
+ AddressRepository $addressRepository,
+ Customer $customerResourceModel,
+ CustomerMetadataInterface $customerMetadata,
+ CustomerSearchResultsInterfaceFactory $searchResultsFactory,
+ ManagerInterface $eventManager,
+ StoreManagerInterface $storeManager,
+ ExtensibleDataObjectConverter $extensibleDataObjectConverter,
DataObjectHelper $dataObjectHelper,
ImageProcessorInterface $imageProcessor,
- \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor,
+ JoinProcessorInterface $extensionAttributesJoinProcessor,
CollectionProcessorInterface $collectionProcessor,
NotificationStorage $notificationStorage,
DelegatedStorage $delegatedStorage = null
@@ -155,8 +166,7 @@ public function __construct(
$this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
$this->collectionProcessor = $collectionProcessor;
$this->notificationStorage = $notificationStorage;
- $this->delegatedStorage = $delegatedStorage
- ?? ObjectManager::getInstance()->get(DelegatedStorage::class);
+ $this->delegatedStorage = $delegatedStorage ?? ObjectManager::getInstance()->get(DelegatedStorage::class);
}
/**
@@ -214,7 +224,7 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
$customerModel->setRpToken(null);
$customerModel->setRpTokenCreatedAt(null);
}
- if (!array_key_exists('default_billing', $customerArr)
+ if (!array_key_exists('addresses', $customerArr)
&& null !== $prevCustomerDataArr
&& array_key_exists('default_billing', $prevCustomerDataArr)
) {
@@ -222,7 +232,7 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
$prevCustomerDataArr['default_billing']
);
}
- if (!array_key_exists('default_shipping', $customerArr)
+ if (!array_key_exists('addresses', $customerArr)
&& null !== $prevCustomerDataArr
&& array_key_exists('default_shipping', $prevCustomerDataArr)
) {
@@ -395,15 +405,12 @@ public function deleteById($customerId)
* Helper function that adds a FilterGroup to the collection.
*
* @deprecated 100.2.0
- * @param \Magento\Framework\Api\Search\FilterGroup $filterGroup
- * @param \Magento\Customer\Model\ResourceModel\Customer\Collection $collection
+ * @param FilterGroup $filterGroup
+ * @param Collection $collection
* @return void
- * @throws \Magento\Framework\Exception\InputException
*/
- protected function addFilterGroupToCollection(
- \Magento\Framework\Api\Search\FilterGroup $filterGroup,
- \Magento\Customer\Model\ResourceModel\Customer\Collection $collection
- ) {
+ protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection)
+ {
$fields = [];
foreach ($filterGroup->getFilters() as $filter) {
$condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCheckCustomerInGridActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCheckCustomerInGridActionGroup.xml
new file mode 100644
index 0000000000000..59925da01a7ad
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCheckCustomerInGridActionGroup.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminConfigCustomerActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminConfigCustomerActionGroup.xml
new file mode 100644
index 0000000000000..3fc25ecf57faa
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminConfigCustomerActionGroup.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml
new file mode 100644
index 0000000000000..8b908fa1456a9
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
index e4420f189900e..8ffc9306ea37e 100644
--- a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
0
12
@@ -88,5 +88,19 @@
Yes
Yes
RegionNY
+ United States
+
+
+ Jane
+ Doe
+ Magento
+
+ - 172, Westminster Bridge Rd
+
+ London
+
+ SE1 7RW
+ GB
+ 444-44-444-44
diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerGroupData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerGroupData.xml
new file mode 100644
index 0000000000000..d7fc22f085344
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerGroupData.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ApiCustomerGroup
+ 0
+ Retail Customer
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Metadata/customer-group-meta.xml b/app/code/Magento/Customer/Test/Mftf/Metadata/customer-group-meta.xml
new file mode 100644
index 0000000000000..a45bf1645d088
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Metadata/customer-group-meta.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ application/json
+
+
+
+ application/json
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Page/AdminCustomerConfigPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/AdminCustomerConfigPage.xml
new file mode 100644
index 0000000000000..3cf8490ec4af1
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Page/AdminCustomerConfigPage.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Page/AdminEditCustomerPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/AdminEditCustomerPage.xml
index 9a28bad4e0d6a..72d5d90bdc05f 100644
--- a/app/code/Magento/Customer/Test/Mftf/Page/AdminEditCustomerPage.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Page/AdminEditCustomerPage.xml
@@ -10,5 +10,7 @@
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Page/AdminNewCustomerPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/AdminNewCustomerPage.xml
index b508409d37a01..1b73441dd149d 100644
--- a/app/code/Magento/Customer/Test/Mftf/Page/AdminNewCustomerPage.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Page/AdminNewCustomerPage.xml
@@ -11,5 +11,8 @@
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerAddressPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerAddressPage.xml
new file mode 100644
index 0000000000000..bdbbcab67da67
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerAddressPage.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountAddressSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountAddressSection.xml
new file mode 100644
index 0000000000000..db9619dde671f
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountAddressSection.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountEditAddressSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountEditAddressSection.xml
new file mode 100644
index 0000000000000..0f64c675ead49
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountEditAddressSection.xml
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml
index 7eef792f0f048..d651d56504c76 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml
@@ -9,6 +9,7 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml
new file mode 100644
index 0000000000000..33696fbd616e3
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerConfigSection.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerEditAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerEditAddressesSection.xml
new file mode 100644
index 0000000000000..3c9e14033fb0d
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerEditAddressesSection.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml
new file mode 100644
index 0000000000000..88b46d245105f
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
index 01b758c9c3e3b..f6a6cb2d457e1 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
@@ -7,12 +7,14 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml
index e5dc187e8ab7a..8e4d69e6a270d 100644
--- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
@@ -19,6 +19,9 @@
+
+
+
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Ajax/LoginTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Ajax/LoginTest.php
index 2fca6c99be319..c0ef4e342559c 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Ajax/LoginTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Ajax/LoginTest.php
@@ -6,12 +6,30 @@
// @codingStandardsIgnoreFile
-/**
- * Test customer ajax login controller
- */
namespace Magento\Customer\Test\Unit\Controller\Ajax;
+use Magento\Customer\Api\Data\CustomerInterface;
+use Magento\Customer\Controller\Ajax\Login;
+use Magento\Customer\Model\Account\Redirect;
+use Magento\Customer\Model\AccountManagement;
+use Magento\Customer\Model\Session;
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\Request\Http;
+use Magento\Framework\App\Response\RedirectInterface;
+use Magento\Framework\App\ResponseInterface;
+use Magento\Framework\Controller\Result\Json;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\Controller\Result\Raw;
+use Magento\Framework\Controller\Result\RawFactory;
use Magento\Framework\Exception\InvalidEmailOrPasswordException;
+use Magento\Framework\Json\Helper\Data;
+use Magento\Framework\ObjectManager\ObjectManager as FakeObjectManager;
+use Magento\Framework\Stdlib\Cookie\CookieMetadata;
+use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
+use Magento\Framework\Stdlib\CookieManagerInterface;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -19,217 +37,187 @@
class LoginTest extends \PHPUnit\Framework\TestCase
{
/**
- * @var \Magento\Customer\Controller\Ajax\Login
+ * @var Login
*/
- protected $object;
+ private $controller;
/**
- * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
+ * @var Http|MockObject
*/
- protected $request;
+ private $request;
/**
- * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var ResponseInterface|MockObject
*/
- protected $response;
+ private $response;
/**
- * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject
+ * @var Session|MockObject
*/
- protected $customerSession;
+ private $customerSession;
/**
- * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var FakeObjectManager|MockObject
*/
- protected $objectManager;
+ private $objectManager;
/**
- * @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var AccountManagement|MockObject
*/
- protected $customerAccountManagementMock;
+ private $accountManagement;
/**
- * @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+ * @var Data|MockObject
*/
- protected $jsonHelperMock;
+ private $jsonHelper;
/**
- * @var \Magento\Framework\Controller\Result\Json|\PHPUnit_Framework_MockObject_MockObject
+ * @var Json|MockObject
*/
- protected $resultJson;
+ private $resultJson;
/**
- * @var \Magento\Framework\Controller\Result\JsonFactory| \PHPUnit_Framework_MockObject_MockObject
+ * @var JsonFactory|MockObject
*/
- protected $resultJsonFactory;
+ private $resultJsonFactory;
/**
- * @var \Magento\Framework\Controller\Result\Raw| \PHPUnit_Framework_MockObject_MockObject
+ * @var Raw|MockObject
*/
- protected $resultRaw;
+ private $resultRaw;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var RedirectInterface|MockObject
*/
- protected $redirectMock;
+ private $redirect;
/**
- * @var \Magento\Framework\Stdlib\CookieManagerInterface| \PHPUnit_Framework_MockObject_MockObject
+ * @var CookieManagerInterface|MockObject
*/
private $cookieManager;
/**
- * @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory| \PHPUnit_Framework_MockObject_MockObject
+ * @var CookieMetadataFactory|MockObject
*/
private $cookieMetadataFactory;
/**
- * @var \Magento\Framework\Stdlib\Cookie\CookieMetadata| \PHPUnit_Framework_MockObject_MockObject
+ * @inheritdoc
*/
- private $cookieMetadata;
-
protected function setUp()
{
- $this->request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
- ->disableOriginalConstructor()->getMock();
- $this->response = $this->createPartialMock(\Magento\Framework\App\ResponseInterface::class, ['setRedirect', 'sendResponse', 'representJson', 'setHttpResponseCode']);
- $this->customerSession = $this->createPartialMock(\Magento\Customer\Model\Session::class, [
+ $this->request = $this->getMockBuilder(Http::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->response = $this->createPartialMock(ResponseInterface::class, ['setRedirect', 'sendResponse', 'representJson', 'setHttpResponseCode']);
+ $this->customerSession = $this->createPartialMock(Session::class, [
'isLoggedIn',
'getLastCustomerId',
'getBeforeAuthUrl',
'setBeforeAuthUrl',
'setCustomerDataAsLoggedIn',
- 'regenerateId'
+ 'regenerateId',
+ 'getData'
]);
- $this->objectManager = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, ['get']);
- $this->customerAccountManagementMock =
- $this->createPartialMock(\Magento\Customer\Model\AccountManagement::class, ['authenticate']);
+ $this->objectManager = $this->createPartialMock(FakeObjectManager::class, ['get']);
+ $this->accountManagement = $this->createPartialMock(AccountManagement::class, ['authenticate']);
- $this->jsonHelperMock = $this->createPartialMock(\Magento\Framework\Json\Helper\Data::class, ['jsonDecode']);
+ $this->jsonHelper = $this->createPartialMock(Data::class, ['jsonDecode']);
- $this->resultJson = $this->getMockBuilder(\Magento\Framework\Controller\Result\Json::class)
+ $this->resultJson = $this->getMockBuilder(Json::class)
->disableOriginalConstructor()
->getMock();
- $this->resultJsonFactory = $this->getMockBuilder(\Magento\Framework\Controller\Result\JsonFactory::class)
+ $this->resultJsonFactory = $this->getMockBuilder(JsonFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
- $this->cookieManager = $this->getMockBuilder(\Magento\Framework\Stdlib\CookieManagerInterface::class)
+ $this->cookieManager = $this->getMockBuilder(CookieManagerInterface::class)
->setMethods(['getCookie', 'deleteCookie'])
->getMockForAbstractClass();
- $this->cookieMetadataFactory = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class)
+ $this->cookieMetadataFactory = $this->getMockBuilder(CookieMetadataFactory::class)
->disableOriginalConstructor()
->getMock();
- $this->cookieMetadata = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\CookieMetadata::class)
+ $this->cookieMetadata = $this->getMockBuilder(CookieMetadata::class)
->disableOriginalConstructor()
->getMock();
- $this->resultRaw = $this->getMockBuilder(\Magento\Framework\Controller\Result\Raw::class)
+ $this->resultRaw = $this->getMockBuilder(Raw::class)
->disableOriginalConstructor()
->getMock();
- $resultRawFactory = $this->getMockBuilder(\Magento\Framework\Controller\Result\RawFactory::class)
+ $resultRawFactory = $this->getMockBuilder(RawFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
- $resultRawFactory->expects($this->atLeastOnce())
- ->method('create')
+ $resultRawFactory->method('create')
->willReturn($this->resultRaw);
- $contextMock = $this->createMock(\Magento\Framework\App\Action\Context::class);
- $this->redirectMock = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class);
- $contextMock->expects($this->atLeastOnce())->method('getRedirect')->willReturn($this->redirectMock);
- $contextMock->expects($this->atLeastOnce())->method('getRequest')->willReturn($this->request);
-
- $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
- $this->object = $objectManager->getObject(
- \Magento\Customer\Controller\Ajax\Login::class,
+ /** @var Context|MockObject $context */
+ $context = $this->createMock(Context::class);
+ $this->redirect = $this->createMock(RedirectInterface::class);
+ $context->method('getRedirect')
+ ->willReturn($this->redirect);
+ $context->method('getRequest')
+ ->willReturn($this->request);
+
+ $objectManager = new ObjectManager($this);
+ $this->controller = $objectManager->getObject(
+ Login::class,
[
- 'context' => $contextMock,
+ 'context' => $context,
'customerSession' => $this->customerSession,
- 'helper' => $this->jsonHelperMock,
+ 'helper' => $this->jsonHelper,
'response' => $this->response,
'resultRawFactory' => $resultRawFactory,
'resultJsonFactory' => $this->resultJsonFactory,
'objectManager' => $this->objectManager,
- 'customerAccountManagement' => $this->customerAccountManagementMock,
+ 'customerAccountManagement' => $this->accountManagement,
'cookieManager' => $this->cookieManager,
'cookieMetadataFactory' => $this->cookieMetadataFactory
]
);
}
+ /**
+ * Checks successful login.
+ */
public function testLogin()
{
$jsonRequest = '{"username":"customer@example.com", "password":"password"}';
$loginSuccessResponse = '{"errors": false, "message":"Login successful."}';
+ $this->withRequest($jsonRequest);
- $this->request
- ->expects($this->any())
- ->method('getContent')
- ->willReturn($jsonRequest);
-
- $this->request
- ->expects($this->any())
- ->method('getMethod')
- ->willReturn('POST');
-
- $this->request
- ->expects($this->any())
- ->method('isXmlHttpRequest')
- ->willReturn(true);
-
- $this->resultJsonFactory->expects($this->atLeastOnce())
- ->method('create')
+ $this->resultJsonFactory->method('create')
->willReturn($this->resultJson);
- $this->jsonHelperMock
- ->expects($this->any())
- ->method('jsonDecode')
+ $this->jsonHelper->method('jsonDecode')
->with($jsonRequest)
->willReturn(['username' => 'customer@example.com', 'password' => 'password']);
- $customerMock = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\CustomerInterface::class);
- $this->customerAccountManagementMock
- ->expects($this->any())
- ->method('authenticate')
+ /** @var CustomerInterface|MockObject $customer */
+ $customer = $this->getMockForAbstractClass(CustomerInterface::class);
+ $this->accountManagement->method('authenticate')
->with('customer@example.com', 'password')
- ->willReturn($customerMock);
+ ->willReturn($customer);
- $this->customerSession->expects($this->once())
- ->method('setCustomerDataAsLoggedIn')
- ->with($customerMock);
+ $this->customerSession->method('setCustomerDataAsLoggedIn')
+ ->with($customer);
+ $this->customerSession->method('regenerateId');
- $this->customerSession->expects($this->once())->method('regenerateId');
+ /** @var Redirect|MockObject $redirect */
+ $redirect = $this->createMock(Redirect::class);
+ $this->controller->setAccountRedirect($redirect);
+ $redirect->method('getRedirectCookie')
+ ->willReturn('some_url1');
- $redirectMock = $this->createMock(\Magento\Customer\Model\Account\Redirect::class);
- $this->object->setAccountRedirect($redirectMock);
- $redirectMock->expects($this->once())->method('getRedirectCookie')->willReturn('some_url1');
+ $this->withCookieManager();
- $this->cookieManager->expects($this->once())
- ->method('getCookie')
- ->with('mage-cache-sessid')
- ->willReturn(true);
- $this->cookieMetadataFactory->expects($this->once())
- ->method('createCookieMetadata')
- ->willReturn($this->cookieMetadata);
- $this->cookieMetadata->expects($this->once())
- ->method('setPath')
- ->with('/')
- ->willReturnSelf();
- $this->cookieManager->expects($this->once())
- ->method('deleteCookie')
- ->with('mage-cache-sessid', $this->cookieMetadata)
- ->willReturnSelf();
+ $this->withScopeConfig();
- $scopeConfigMock = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
- $this->object->setScopeConfig($scopeConfigMock);
- $scopeConfigMock->expects($this->once())->method('getValue')
- ->with('customer/startup/redirect_dashboard')
- ->willReturn(0);
-
- $this->redirectMock->expects($this->once())->method('success')->willReturn('some_url2');
- $this->resultRaw->expects($this->never())->method('setHttpResponseCode');
+ $this->redirect->method('success')
+ ->willReturn('some_url2');
+ $this->resultRaw->expects(self::never())
+ ->method('setHttpResponseCode');
$result = [
'errors' => false,
@@ -237,67 +225,103 @@ public function testLogin()
'redirectUrl' => 'some_url2',
];
- $this->resultJson
- ->expects($this->once())
- ->method('setData')
+ $this->resultJson->method('setData')
->with($result)
->willReturn($loginSuccessResponse);
- $this->assertEquals($loginSuccessResponse, $this->object->execute());
+ self::assertEquals($loginSuccessResponse, $this->controller->execute());
}
+ /**
+ * Checks unsuccessful login.
+ */
public function testLoginFailure()
{
$jsonRequest = '{"username":"invalid@example.com", "password":"invalid"}';
$loginFailureResponse = '{"message":"Invalid login or password."}';
+ $this->withRequest($jsonRequest);
- $this->request
- ->expects($this->any())
- ->method('getContent')
- ->willReturn($jsonRequest);
-
- $this->request
- ->expects($this->any())
- ->method('getMethod')
- ->willReturn('POST');
-
- $this->request
- ->expects($this->any())
- ->method('isXmlHttpRequest')
- ->willReturn(true);
-
- $this->resultJsonFactory->expects($this->once())
- ->method('create')
+ $this->resultJsonFactory->method('create')
->willReturn($this->resultJson);
- $this->jsonHelperMock
- ->expects($this->any())
- ->method('jsonDecode')
+ $this->jsonHelper->method('jsonDecode')
->with($jsonRequest)
->willReturn(['username' => 'invalid@example.com', 'password' => 'invalid']);
- $customerMock = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\CustomerInterface::class);
- $this->customerAccountManagementMock
- ->expects($this->any())
- ->method('authenticate')
+ /** @var CustomerInterface|MockObject $customer */
+ $customer = $this->getMockForAbstractClass(CustomerInterface::class);
+ $this->accountManagement->method('authenticate')
->with('invalid@example.com', 'invalid')
->willThrowException(new InvalidEmailOrPasswordException(__('Invalid login or password.')));
- $this->customerSession->expects($this->never())
+ $this->customerSession->expects(self::never())
->method('setCustomerDataAsLoggedIn')
- ->with($customerMock);
-
- $this->customerSession->expects($this->never())->method('regenerateId');
+ ->with($customer);
+ $this->customerSession->expects(self::never())
+ ->method('regenerateId');
+ $this->customerSession->method('getData')
+ ->with('user_login_show_captcha')
+ ->willReturn(false);
$result = [
'errors' => true,
- 'message' => __('Invalid login or password.')
+ 'message' => __('Invalid login or password.'),
+ 'captcha' => false
];
- $this->resultJson
- ->expects($this->once())
- ->method('setData')
+ $this->resultJson->method('setData')
->with($result)
->willReturn($loginFailureResponse);
- $this->assertEquals($loginFailureResponse, $this->object->execute());
+ self::assertEquals($loginFailureResponse, $this->controller->execute());
+ }
+
+ /**
+ * Emulates request behavior.
+ *
+ * @param string $jsonRequest
+ */
+ private function withRequest(string $jsonRequest)
+ {
+ $this->request->method('getContent')
+ ->willReturn($jsonRequest);
+
+ $this->request->method('getMethod')
+ ->willReturn('POST');
+
+ $this->request->method('isXmlHttpRequest')
+ ->willReturn(true);
+ }
+
+ /**
+ * Emulates cookie manager behavior.
+ */
+ private function withCookieManager()
+ {
+ $this->cookieManager->method('getCookie')
+ ->with('mage-cache-sessid')
+ ->willReturn(true);
+ $cookieMetadata = $this->getMockBuilder(CookieMetadata::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->cookieMetadataFactory->method('createCookieMetadata')
+ ->willReturn($cookieMetadata);
+ $cookieMetadata->method('setPath')
+ ->with('/')
+ ->willReturnSelf();
+ $this->cookieManager->method('deleteCookie')
+ ->with('mage-cache-sessid', $cookieMetadata)
+ ->willReturnSelf();
+ }
+
+ /**
+ * Emulates config behavior.
+ */
+ private function withScopeConfig()
+ {
+ /** @var ScopeConfigInterface|MockObject $scopeConfig */
+ $scopeConfig = $this->createMock(ScopeConfigInterface::class);
+ $this->controller->setScopeConfig($scopeConfig);
+ $scopeConfig->method('getValue')
+ ->with('customer/startup/redirect_dashboard')
+ ->willReturn(0);
}
}
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index e3d8f22088ef6..af45eb7931308 100644
--- a/app/code/Magento/Customer/composer.json
+++ b/app/code/Magento/Customer/composer.json
@@ -29,7 +29,7 @@
"magento/module-customer-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "101.0.6",
+ "version": "101.0.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
index 4de6644b948fb..d2a9b3f44624d 100644
--- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
+++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml
@@ -486,9 +486,6 @@
-
- true
-
text
diff --git a/app/code/Magento/Customer/view/frontend/web/js/action/login.js b/app/code/Magento/Customer/view/frontend/web/js/action/login.js
index 6c7096190e38f..34cfa39e01c43 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/action/login.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/action/login.js
@@ -31,11 +31,11 @@ define([
if (response.errors) {
messageContainer.addErrorMessage(response);
callbacks.forEach(function (callback) {
- callback(loginData);
+ callback(loginData, response);
});
} else {
callbacks.forEach(function (callback) {
- callback(loginData);
+ callback(loginData, response);
});
customerData.invalidate(['customer']);
diff --git a/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js b/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js
index 89d9b320c049d..9742e37f2df57 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js
@@ -83,7 +83,7 @@ define([
} else {
isValid = $.validator.validateSingleElement(this.options.cache.input);
zxcvbnScore = zxcvbn(password).score;
- displayScore = isValid ? zxcvbnScore : 1;
+ displayScore = isValid && zxcvbnScore > 0 ? zxcvbnScore : 1;
}
}
diff --git a/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js b/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
index c14a59af49706..37bd3a19df638 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
@@ -84,7 +84,6 @@ define([
if (formElement.validation() &&
formElement.validation('isValid')
) {
- this.isLoading(true);
loginAction(loginData);
}
diff --git a/app/code/Magento/CustomerAnalytics/composer.json b/app/code/Magento/CustomerAnalytics/composer.json
index d9c428ffcf5b7..901989b9d2550 100644
--- a/app/code/Magento/CustomerAnalytics/composer.json
+++ b/app/code/Magento/CustomerAnalytics/composer.json
@@ -7,7 +7,7 @@
"magento/module-customer": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
index 36c1e761d013c..1ff1adc3dac58 100644
--- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
@@ -299,8 +299,8 @@ public function validateData()
$rows = [];
foreach ($source as $row) {
$rows[] = [
- Address::COLUMN_EMAIL => $row[Customer::COLUMN_EMAIL],
- Address::COLUMN_WEBSITE => $row[Customer::COLUMN_WEBSITE]
+ Address::COLUMN_EMAIL => $row[Customer::COLUMN_EMAIL] ?? null,
+ Address::COLUMN_WEBSITE => $row[Customer::COLUMN_WEBSITE] ?? null
];
}
$source->rewind();
diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json
index d71be31723043..ebf8f7f52b99a 100644
--- a/app/code/Magento/CustomerImportExport/composer.json
+++ b/app/code/Magento/CustomerImportExport/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Deploy/composer.json b/app/code/Magento/Deploy/composer.json
index 3c28dc345cba4..79ccab30d2924 100644
--- a/app/code/Magento/Deploy/composer.json
+++ b/app/code/Magento/Deploy/composer.json
@@ -10,7 +10,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.5",
+ "version": "100.2.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php b/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php
index 25519e5c83054..a2db0f43061ea 100644
--- a/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php
+++ b/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php
@@ -5,7 +5,6 @@
*/
namespace Magento\Developer\Console\Command;
-use Magento\Framework\App\State;
use Magento\Framework\Validator\Locale;
use Magento\Framework\View\Asset\Repository;
use Symfony\Component\Console\Command\Command;
diff --git a/app/code/Magento/Developer/composer.json b/app/code/Magento/Developer/composer.json
index e2236e248cfc3..771853609211a 100644
--- a/app/code/Magento/Developer/composer.json
+++ b/app/code/Magento/Developer/composer.json
@@ -8,7 +8,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json
index fae1eb9e1454f..93926d6e1e28b 100644
--- a/app/code/Magento/Dhl/composer.json
+++ b/app/code/Magento/Dhl/composer.json
@@ -19,7 +19,7 @@
"magento/module-checkout": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Directory/Test/Mftf/Data/CurrencyConfigData.xml b/app/code/Magento/Directory/Test/Mftf/Data/CurrencyConfigData.xml
new file mode 100644
index 0000000000000..1fd39933f51af
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Mftf/Data/CurrencyConfigData.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ BaseCurrency
+ DefaultCurrency
+ AllowedCurrencies
+
+
+ USD
+
+
+ USD
+
+
+
+ - USD
+
+
+
+ BaseCurrency
+ DefaultCurrency
+ AllowedCurrenciesEuroAndUSD
+
+
+
+ - EUR
+ - USD
+
+
+
diff --git a/app/code/Magento/Directory/Test/Mftf/Metadata/currency_config-meta.xml b/app/code/Magento/Directory/Test/Mftf/Metadata/currency_config-meta.xml
new file mode 100644
index 0000000000000..5ef1179ea7829
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Mftf/Metadata/currency_config-meta.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ application/x-www-form-urlencoded
+
+
+
diff --git a/app/code/Magento/Directory/Test/Mftf/Section/StorefrontHeaderCurrencySwitcherSection.xml b/app/code/Magento/Directory/Test/Mftf/Section/StorefrontHeaderCurrencySwitcherSection.xml
new file mode 100644
index 0000000000000..d7e8bf1a71c1d
--- /dev/null
+++ b/app/code/Magento/Directory/Test/Mftf/Section/StorefrontHeaderCurrencySwitcherSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json
index c6de1d1eefe6c..a4b5991095307 100644
--- a/app/code/Magento/Directory/composer.json
+++ b/app/code/Magento/Directory/composer.json
@@ -10,7 +10,7 @@
"lib-libxml": "*"
},
"type": "magento2-module",
- "version": "100.2.5",
+ "version": "100.2.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Downloadable/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Downloadable.php b/app/code/Magento/Downloadable/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Downloadable.php
index f56b219f72db2..a283891afc406 100644
--- a/app/code/Magento/Downloadable/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Downloadable.php
+++ b/app/code/Magento/Downloadable/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Downloadable.php
@@ -11,6 +11,9 @@
use Magento\Downloadable\Api\Data\SampleInterfaceFactory;
use Magento\Downloadable\Api\Data\LinkInterfaceFactory;
+/**
+ * Class for initialization downloadable info from request.
+ */
class Downloadable
{
/**
@@ -92,6 +95,8 @@ public function afterInitialize(
}
}
$extension->setDownloadableProductLinks($links);
+ } else {
+ $extension->setDownloadableProductLinks([]);
}
if (isset($downloadable['sample']) && is_array($downloadable['sample'])) {
$samples = [];
@@ -107,6 +112,8 @@ public function afterInitialize(
}
}
$extension->setDownloadableProductSamples($samples);
+ } else {
+ $extension->setDownloadableProductSamples([]);
}
$product->setExtensionAttributes($extension);
if ($product->getLinksPurchasedSeparately()) {
diff --git a/app/code/Magento/Downloadable/Setup/UpgradeData.php b/app/code/Magento/Downloadable/Setup/UpgradeData.php
new file mode 100644
index 0000000000000..aec15ce7f9d90
--- /dev/null
+++ b/app/code/Magento/Downloadable/Setup/UpgradeData.php
@@ -0,0 +1,58 @@
+eavSetupFactory = $eavSetupFactory;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
+ {
+ $setup->startSetup();
+
+ if (version_compare($context->getVersion(), '2.0.3', '<')) {
+ /** @var EavSetup $eavSetup */
+ $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
+ // remove default value
+ $eavSetup->updateAttribute(
+ \Magento\Catalog\Model\Product::ENTITY,
+ 'links_exist',
+ 'default_value',
+ null
+ );
+ }
+
+ $setup->endSetup();
+ }
+}
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/LinkData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/LinkData.xml
new file mode 100644
index 0000000000000..4f48ca7309baa
--- /dev/null
+++ b/app/code/Magento/Downloadable/Test/Mftf/Data/LinkData.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Api Downloadable Link
+ 2.00
+ url
+ No
+ 1000
+ 0
+ https://static.magento.com/sites/all/themes/mag_redesign/images/magento-logo.svg
+
+
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml
new file mode 100644
index 0000000000000..28b4aa261b941
--- /dev/null
+++ b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ api-downloadable-product
+ downloadable
+ 4
+ 4
+ Api Downloadable Product
+ 123.00
+ api-downloadable-product
+ 1
+ 100
+ EavStockItem
+ ApiProductDescription
+ ApiProductShortDescription
+ apiDownloadableLink
+
+
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Metadata/downloadable_link-meta.xml b/app/code/Magento/Downloadable/Test/Mftf/Metadata/downloadable_link-meta.xml
new file mode 100644
index 0000000000000..2511244d445c1
--- /dev/null
+++ b/app/code/Magento/Downloadable/Test/Mftf/Metadata/downloadable_link-meta.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ application/json
+
+ string
+ integer
+ integer
+ number
+ integer
+ string
+ string
+ link_file_content
+ string
+ string
+ string
+ string
+ sample_file_content
+ string
+
+ boolean
+
+
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Metadata/link_file_content-meta.xml b/app/code/Magento/Downloadable/Test/Mftf/Metadata/link_file_content-meta.xml
new file mode 100644
index 0000000000000..d5d6c16c71736
--- /dev/null
+++ b/app/code/Magento/Downloadable/Test/Mftf/Metadata/link_file_content-meta.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ string
+ string
+
+
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Metadata/sample_file_content-meta.xml b/app/code/Magento/Downloadable/Test/Mftf/Metadata/sample_file_content-meta.xml
new file mode 100644
index 0000000000000..3da91807ceb48
--- /dev/null
+++ b/app/code/Magento/Downloadable/Test/Mftf/Metadata/sample_file_content-meta.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ string
+ string
+
+
diff --git a/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php b/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php
index 7749c5980c864..8f7bf5b30d226 100644
--- a/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php
+++ b/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php
@@ -89,7 +89,7 @@ public function testSetResourceInvalidPath()
/**
* @expectedException \Magento\Framework\Exception\LocalizedException
- * @exectedExceptionMessage Please set resource file and link type.
+ * @expectedExceptionMessage Please set resource file and link type.
*/
public function testGetFileSizeNoResource()
{
diff --git a/app/code/Magento/Downloadable/composer.json b/app/code/Magento/Downloadable/composer.json
index e737c3121f454..e8a885cb49806 100644
--- a/app/code/Magento/Downloadable/composer.json
+++ b/app/code/Magento/Downloadable/composer.json
@@ -25,7 +25,7 @@
"magento/module-downloadable-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.5",
+ "version": "100.2.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Downloadable/etc/di.xml b/app/code/Magento/Downloadable/etc/di.xml
index 932e48e880880..4e9b0b55afb0b 100644
--- a/app/code/Magento/Downloadable/etc/di.xml
+++ b/app/code/Magento/Downloadable/etc/di.xml
@@ -77,6 +77,13 @@
+
+
+
+ - Magento\Downloadable\Model\ProductOptionProcessor
+
+
+
diff --git a/app/code/Magento/Downloadable/etc/events.xml b/app/code/Magento/Downloadable/etc/events.xml
index e4f03ff238d4a..5a985fc33802e 100644
--- a/app/code/Magento/Downloadable/etc/events.xml
+++ b/app/code/Magento/Downloadable/etc/events.xml
@@ -6,10 +6,10 @@
*/
-->
-
+
-
+
diff --git a/app/code/Magento/Downloadable/etc/module.xml b/app/code/Magento/Downloadable/etc/module.xml
index 4c4e165feb014..fb13121335730 100644
--- a/app/code/Magento/Downloadable/etc/module.xml
+++ b/app/code/Magento/Downloadable/etc/module.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/app/code/Magento/DownloadableImportExport/composer.json b/app/code/Magento/DownloadableImportExport/composer.json
index 763eceaea8460..07336fa5c9957 100644
--- a/app/code/Magento/DownloadableImportExport/composer.json
+++ b/app/code/Magento/DownloadableImportExport/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Eav/Model/Attribute/Data/File.php b/app/code/Magento/Eav/Model/Attribute/Data/File.php
index 0364330517b88..d6476eefc59b1 100644
--- a/app/code/Magento/Eav/Model/Attribute/Data/File.php
+++ b/app/code/Magento/Eav/Model/Attribute/Data/File.php
@@ -120,8 +120,7 @@ public function extractValue(RequestInterface $request)
}
/**
- * Validate file by attribute validate rules
- * Return array of errors
+ * Validate file by attribute validate rules and return array of errors.
*
* @param array $value
* @return string[]
@@ -147,7 +146,7 @@ protected function _validateByRules($value)
return $this->_fileValidator->getMessages();
}
- if (!is_uploaded_file($value['tmp_name'])) {
+ if (!empty($value['tmp_name']) && !is_uploaded_file($value['tmp_name'])) {
return [__('"%1" is not a valid file.', $label)];
}
@@ -174,12 +173,22 @@ public function validateValue($value)
if ($this->getIsAjaxRequest()) {
return true;
}
+ $fileData = $value;
+
+ if (is_string($value) && !empty($value)) {
+ $dir = $this->_directory->getAbsolutePath($this->getAttribute()->getEntityType()->getEntityTypeCode());
+ $fileData = [
+ 'size' => filesize($dir . $value),
+ 'name' => $value,
+ 'tmp_name' => $dir . $value,
+ ];
+ }
$errors = [];
$attribute = $this->getAttribute();
$toDelete = !empty($value['delete']) ? true : false;
- $toUpload = !empty($value['tmp_name']) ? true : false;
+ $toUpload = !empty($value['tmp_name']) || is_string($value) && !empty($value) ? true : false;
if (!$toUpload && !$toDelete && $this->getEntity()->getData($attribute->getAttributeCode())) {
return true;
@@ -195,11 +204,13 @@ public function validateValue($value)
}
if ($toUpload) {
- $errors = array_merge($errors, $this->_validateByRules($value));
+ $errors = array_merge($errors, $this->_validateByRules($fileData));
}
if (count($errors) == 0) {
return true;
+ } elseif (is_string($value) && !empty($value)) {
+ $this->_directory->delete($dir . $value);
}
return $errors;
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php
index a5e31c613d17b..740b29c9676f3 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute.php
@@ -287,6 +287,12 @@ public function beforeSave()
}
}
+ if ($this->getFrontendInput() == 'media_image') {
+ if (!$this->getFrontendModel()) {
+ $this->setFrontendModel(\Magento\Catalog\Model\Product\Attribute\Frontend\Image::class);
+ }
+ }
+
if ($this->getBackendType() == 'gallery') {
if (!$this->getBackendModel()) {
$this->setBackendModel(\Magento\Eav\Model\Entity\Attribute\Backend\DefaultBackend::class);
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index 65b60be0d96fd..1f13fe1405273 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -392,7 +392,7 @@ public function getIsVisibleOnFront()
}
/**
- * @return string|int|bool|float
+ * @return string|null
* @codeCoverageIgnore
*/
public function getDefaultValue()
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php
index 38e7b883f4ea5..e4bf1892d7222 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php
@@ -203,12 +203,12 @@ public function getEntityValueId($entity)
/**
* Retrieve default value
*
- * @return mixed
+ * @return string
*/
public function getDefaultValue()
{
if ($this->_defaultValue === null) {
- if ($this->getAttribute()->getDefaultValue()) {
+ if ($this->getAttribute()->getDefaultValue() !== null) {
$this->_defaultValue = $this->getAttribute()->getDefaultValue();
} else {
$this->_defaultValue = "";
@@ -280,7 +280,7 @@ public function afterLoad($object)
public function beforeSave($object)
{
$attrCode = $this->getAttribute()->getAttributeCode();
- if (!$object->hasData($attrCode) && $this->getDefaultValue()) {
+ if (!$object->hasData($attrCode) && $this->getDefaultValue() !== '') {
$object->setData($attrCode, $this->getDefaultValue());
}
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php
index 01bdddc32af90..4a620ed5f35e5 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php
@@ -132,7 +132,7 @@ public function getItems($entityType, $attributeCode)
*/
protected function validateOption($attribute, $optionId)
{
- if (!$attribute->getSource()->getOptionText($optionId)) {
+ if ($attribute->getSource()->getOptionText($optionId) === false) {
throw new NoSuchEntityException(
__('Attribute %1 does not contain option with Id %2', $attribute->getAttributeCode(), $optionId)
);
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
index 0f3b8be32b988..59164a1dd0922 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
@@ -10,6 +10,8 @@
use Magento\Framework\Escaper;
/**
+ * Eav attribute default source when values are coming from another table
+ *
* @api
* @since 100.0.2
*/
@@ -136,12 +138,14 @@ public function getSpecificOptions($ids, $withEmpty = true)
}
/**
+ * Add an empty option to the array
+ *
* @param array $options
* @return array
*/
private function addEmptyOption(array $options)
{
- array_unshift($options, ['label' => $this->getAttribute()->getIsRequired() ? '' : ' ', 'value' => '']);
+ array_unshift($options, ['label' => ' ', 'value' => '']);
return $options;
}
diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
index 77b4ce1c8eae8..2177686a4a6be 100644
--- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
+++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
@@ -1233,7 +1233,7 @@ protected function _getLoadAttributesSelect($table, $attributeIds = [])
if ($entity->getEntityTable() == \Magento\Eav\Model\Entity::DEFAULT_ENTITY_TABLE && $entity->getTypeId()) {
$select->where(
- 'entity_type_id =?',
+ 't_d.entity_type_id =?',
$entity->getTypeId()
);
}
diff --git a/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesEditSection.xml b/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesEditSection.xml
new file mode 100644
index 0000000000000..da48db84f99ed
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesEditSection.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesGridSection.xml b/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesGridSection.xml
new file mode 100644
index 0000000000000..36360a0ebc565
--- /dev/null
+++ b/app/code/Magento/Eav/Test/Mftf/Section/AdminAttributesGridSection.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json
index 2f0a7fa3c79a9..b1eec7fcaa602 100644
--- a/app/code/Magento/Eav/composer.json
+++ b/app/code/Magento/Eav/composer.json
@@ -11,7 +11,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "101.0.5",
+ "version": "101.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Email/Model/AbstractTemplate.php b/app/code/Magento/Email/Model/AbstractTemplate.php
index 81e993fad76df..a6ecdaf24ebbb 100644
--- a/app/code/Magento/Email/Model/AbstractTemplate.php
+++ b/app/code/Magento/Email/Model/AbstractTemplate.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Email\Model;
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -289,7 +290,7 @@ public function loadDefault($templateId)
/**
* trim copyright message
*/
- if (preg_match('/^/m', $templateText, $matches) && strpos($matches[0], 'Copyright') > 0) {
+ if (preg_match('/^/m', $templateText, $matches) && strpos($matches[0], 'Copyright') !== false) {
$templateText = str_replace($matches[0], '', $templateText);
}
@@ -530,13 +531,13 @@ protected function cancelDesignConfig()
*
* @param string $templateId
* @return $this
- * @throws \Magento\Framework\Exception\MailException
*/
public function setForcedArea($templateId)
{
- if (!isset($this->area)) {
+ if ($this->area === null) {
$this->area = $this->emailConfig->getTemplateArea($templateId);
}
+
return $this;
}
@@ -604,7 +605,9 @@ public function getDesignConfig()
public function setDesignConfig(array $config)
{
if (!isset($config['area']) || !isset($config['store'])) {
- throw new LocalizedException(__('Design config must have area and store.'));
+ throw new LocalizedException(
+ __('The design config needs an area and a store. Verify that both are set and try again.')
+ );
}
$this->getDesignConfig()->setData($config);
return $this;
diff --git a/app/code/Magento/Email/Model/Transport.php b/app/code/Magento/Email/Model/Transport.php
index 7e966a9a5a28d..dc7824a228e34 100644
--- a/app/code/Magento/Email/Model/Transport.php
+++ b/app/code/Magento/Email/Model/Transport.php
@@ -7,13 +7,16 @@
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\MailException;
-use Magento\Framework\Mail\MessageInterface;
+use Magento\Framework\Mail\Message;
use Magento\Framework\Mail\TransportInterface;
+use Magento\Framework\Phrase;
use Magento\Store\Model\ScopeInterface;
+use Zend\Mail\Message as ZendMessage;
+use Zend\Mail\Transport\Sendmail;
/**
* Class that responsible for filling some message data before transporting it.
- * @see Zend_Mail_Transport_Sendmail is used for transport
+ * @see \Zend\Mail\Transport\Sendmail is used for transport
*/
class Transport implements TransportInterface
{
@@ -29,79 +32,81 @@ class Transport implements TransportInterface
const XML_PATH_SENDING_RETURN_PATH_EMAIL = 'system/smtp/return_path_email';
/**
- * Object for sending eMails
+ * Whether return path should be set or no.
*
- * @var \Zend_Mail_Transport_Sendmail
+ * Possible values are:
+ * 0 - no
+ * 1 - yes (set value as FROM address)
+ * 2 - use custom value
+ *
+ * @var int
*/
- private $transport;
+ private $isSetReturnPath;
/**
- * Email message object that should be instance of \Zend_Mail
- *
- * @var MessageInterface
+ * @var string|null
+ */
+ private $returnPathValue;
+
+ /**
+ * @var Sendmail
+ */
+ private $zendTransport;
+
+ /**
+ * @var Message
*/
private $message;
/**
- * Core store config
- *
- * @var ScopeConfigInterface
+ * @var ZendMessage
*/
- private $scopeConfig;
+ private $zendMessage;
/**
- * @param \Zend_Mail_Transport_Sendmail $transport
- * @param MessageInterface $message Email message object
+ * @param Message $message Email message object
* @param ScopeConfigInterface $scopeConfig Core store config
- * @param string|array|\Zend_Config|null $parameters Config options for sendmail parameters
- *
- * @throws \InvalidArgumentException when $message is not an instance of \Zend_Mail
+ * @param ZendMessage $zendMessage
+ * @param null|string|array|\Traversable $parameters Config options for sendmail parameters
*/
public function __construct(
- \Zend_Mail_Transport_Sendmail $transport,
- MessageInterface $message,
- ScopeConfigInterface $scopeConfig
+ Message $message,
+ ScopeConfigInterface $scopeConfig,
+ ZendMessage $zendMessage,
+ $parameters = null
) {
- if (!$message instanceof \Zend_Mail) {
- throw new \InvalidArgumentException('The message should be an instance of \Zend_Mail');
- }
- $this->transport = $transport;
+ $this->isSetReturnPath = (int) $scopeConfig->getValue(
+ self::XML_PATH_SENDING_SET_RETURN_PATH,
+ ScopeInterface::SCOPE_STORE
+ );
+ $this->returnPathValue = $scopeConfig->getValue(
+ self::XML_PATH_SENDING_RETURN_PATH_EMAIL,
+ ScopeInterface::SCOPE_STORE
+ );
+
+ $this->zendTransport = new Sendmail($parameters);
$this->message = $message;
- $this->scopeConfig = $scopeConfig;
+ $this->zendMessage = $zendMessage;
}
/**
- * Sets Return-Path to email if necessary, and sends email if it is allowed by System Configurations
- *
- * @return void
- * @throws MailException
+ * @inheritdoc
*/
public function sendMessage()
{
try {
- /* configuration of whether return path should be set or no. Possible values are:
- * 0 - no
- * 1 - yes (set value as FROM address)
- * 2 - use custom value
- * @see Magento\Config\Model\Config\Source\Yesnocustom
- */
- $isSetReturnPath = $this->scopeConfig->getValue(
- self::XML_PATH_SENDING_SET_RETURN_PATH,
- ScopeInterface::SCOPE_STORE
- );
- $returnPathValue = $this->scopeConfig->getValue(
- self::XML_PATH_SENDING_RETURN_PATH_EMAIL,
- ScopeInterface::SCOPE_STORE
- );
-
- if ($isSetReturnPath == '1') {
- $this->message->setReturnPath($this->message->getFrom());
- } elseif ($isSetReturnPath == '2' && $returnPathValue !== null) {
- $this->message->setReturnPath($returnPathValue);
+ $message = $this->zendMessage->fromString($this->message->getRawMessage());
+ if (2 === $this->isSetReturnPath && $this->returnPathValue) {
+ $message->setSender($this->returnPathValue);
+ } elseif (1 === $this->isSetReturnPath && $message->getFrom()->count()) {
+ $fromAddressList = $message->getFrom();
+ $fromAddressList->rewind();
+ $message->setSender($fromAddressList->current()->getEmail());
}
- $this->transport->send($this->message);
+
+ $this->zendTransport->send($message);
} catch (\Exception $e) {
- throw new MailException(__($e->getMessage()), $e);
+ throw new MailException(new Phrase($e->getMessage()), $e);
}
}
diff --git a/app/code/Magento/Email/Test/Unit/Model/Plugin/WindowsSmtpConfigTest.php b/app/code/Magento/Email/Test/Unit/Model/Plugin/WindowsSmtpConfigTest.php
new file mode 100644
index 0000000000000..b06dc3cb48cbc
--- /dev/null
+++ b/app/code/Magento/Email/Test/Unit/Model/Plugin/WindowsSmtpConfigTest.php
@@ -0,0 +1,100 @@
+osInfoMock = $this->createMock(OsInfo::class);
+ $this->configMock = $this->createMock(ReinitableConfigInterface::class);
+ $this->transportMock = $this->createMock(TransportInterface::class);
+
+ $this->windowsSmtpConfig = $objectManager->getObject(
+ WindowsSmtpConfig::class,
+ [
+ 'config' => $this->configMock,
+ 'osInfo' => $this->osInfoMock
+ ]
+ );
+ }
+
+ /**
+ * Test if SMTP settings if windows server
+ *
+ * @return void
+ */
+ public function testBeforeSendMessageOsWindows()
+ {
+ $this->osInfoMock->expects($this->once())
+ ->method('isWindows')
+ ->willReturn(true);
+
+ $this->configMock->expects($this->exactly(2))
+ ->method('getValue')
+ ->willReturnMap([
+ [WindowsSmtpConfig::XML_SMTP_HOST, '127.0.0.1'],
+ [WindowsSmtpConfig::XML_SMTP_PORT, '80']
+ ]);
+
+ $this->windowsSmtpConfig->beforeSendMessage($this->transportMock);
+ }
+
+ /**
+ * Test if SMTP settings if not windows server
+ *
+ * @return void
+ */
+ public function testBeforeSendMessageOsIsWindows()
+ {
+ $this->osInfoMock->expects($this->once())
+ ->method('isWindows')
+ ->willReturn(false);
+
+ $this->configMock->expects($this->never())
+ ->method('getValue');
+
+ $this->windowsSmtpConfig->beforeSendMessage($this->transportMock);
+ }
+}
diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/SenderResolverTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/SenderResolverTest.php
new file mode 100644
index 0000000000000..8d2931f3e38f5
--- /dev/null
+++ b/app/code/Magento/Email/Test/Unit/Model/Template/SenderResolverTest.php
@@ -0,0 +1,112 @@
+scopeConfig = $this->createMock(ScopeConfigInterface::class);
+
+ $this->senderResolver = $objectManager->getObject(
+ SenderResolver::class,
+ [
+ 'scopeConfig' => $this->scopeConfig
+ ]
+ );
+ }
+
+ /**
+ * Test returned information for given sender's name and email
+ *
+ * @return void
+ */
+ public function testResolve()
+ {
+ $sender = 'general';
+ $scopeId = null;
+
+ $this->scopeConfig->expects($this->exactly(2))
+ ->method('getValue')
+ ->willReturnMap([
+ [
+ 'trans_email/ident_' . $sender . '/name',
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+ $scopeId,
+ 'Test Name'
+ ],
+ [
+ 'trans_email/ident_' . $sender . '/email',
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+ $scopeId,
+ 'test@email.com'
+ ]
+ ]);
+
+ $result = $this->senderResolver->resolve($sender);
+
+ $this->assertTrue(isset($result['name']));
+ $this->assertEquals('Test Name', $result['name']);
+
+ $this->assertTrue(isset($result['email']));
+ $this->assertEquals('test@email.com', $result['email']);
+ }
+
+ /**
+ * Test if exception is thrown in case there is no name or email in result
+ *
+ * @dataProvider dataProvidedSenderArray
+ * @param array $sender
+ *
+ * @return void
+ */
+ public function testResolveThrowException(array $sender)
+ {
+ $this->expectExceptionMessage('Invalid sender data');
+ $this->expectException(MailException::class);
+ $this->senderResolver->resolve($sender);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProvidedSenderArray()
+ {
+ return [
+ [
+ ['name' => 'Name']
+ ],
+ [
+ ['email' => 'test@email.com']
+ ]
+ ];
+ }
+}
diff --git a/app/code/Magento/Email/Test/Unit/Model/TransportTest.php b/app/code/Magento/Email/Test/Unit/Model/TransportTest.php
deleted file mode 100644
index 3589e43996936..0000000000000
--- a/app/code/Magento/Email/Test/Unit/Model/TransportTest.php
+++ /dev/null
@@ -1,192 +0,0 @@
-transportMock = $this->createMock(\Zend_Mail_Transport_Sendmail::class);
-
- $this->messageMock = $this->createMock(Message::class);
-
- $this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class);
-
- $this->model = new Transport($this->transportMock, $this->messageMock, $this->scopeConfigMock);
- }
-
- /**
- * Tests that if any exception was caught, \Magento\Framework\Exception\MailException will thrown
- *
- * @expectedException \Magento\Framework\Exception\MailException
- */
- public function testSendMessageException()
- {
- $this->scopeConfigMock->expects($this->once())
- ->method('getValue')
- ->willThrowException(new \Exception('some exception'));
- $this->model->sendMessage();
- }
-
- /**
- * Tests that if sending Return-Path was disabled or email was not provided, - this header won't be set
- *
- * @param string|int|null $returnPathSet
- * @param string|null $returnPathEmail
- *
- * @dataProvider sendMessageWithoutReturnPathDataProvider
- */
- public function testSendMessageWithoutReturnPath($returnPathSet, $returnPathEmail = null)
- {
- $this->prepareSendingMessage($returnPathSet, $returnPathEmail);
-
- $this->messageMock->expects($this->never())
- ->method('setReturnPath');
- $this->transportMock->expects($this->once())
- ->method('send');
- $this->model->sendMessage();
- }
-
- /**
- * Tests that if sending Return-Path was disabled, this header won't be set
- *
- * @param string|int|null $returnPathSet
- * @param string|null $emailFrom
- *
- * @dataProvider sendMessageWithDefaultReturnPathDataProvider
- */
- public function testSendMessageWithDefaultReturnPath($returnPathSet, $emailFrom)
- {
- $this->prepareSendingMessage($returnPathSet, null);
-
- $this->messageMock->expects($this->once())
- ->method('setReturnPath')
- ->with($emailFrom);
- $this->messageMock->expects($this->once())
- ->method('getFrom')
- ->willReturn($emailFrom);
- $this->transportMock->expects($this->once())
- ->method('send');
- $this->model->sendMessage();
- }
-
- /**
- * Tests that if sending Return-Path was disabled, this header won't be set
- *
- * @param string|int|null $returnPathSet
- * @param string|null $emailFrom
- *
- * @dataProvider sendMessageWithCustomReturnPathDataProvider
- */
- public function testSendMessageWithCustomReturnPath($returnPathSet, $emailFrom)
- {
- $this->prepareSendingMessage($returnPathSet, $emailFrom);
-
- $this->messageMock->expects($this->once())
- ->method('setReturnPath')
- ->with($emailFrom);
- $this->messageMock->expects($this->never())
- ->method('getFrom')
- ->willReturn($emailFrom);
- $this->transportMock->expects($this->once())
- ->method('send');
- $this->model->sendMessage();
- }
-
- /**
- * Tests retrieving message object
- */
- public function testGetMessage()
- {
- $this->assertEquals($this->messageMock, $this->model->getMessage());
- }
-
- /**
- * Executes all main sets for sending message
- *
- * @param string|int|null $returnPathSet
- * @param string|null $returnPathEmail
- */
- private function prepareSendingMessage($returnPathSet, $returnPathEmail)
- {
- $map = [
- [Transport::XML_PATH_SENDING_SET_RETURN_PATH, ScopeInterface::SCOPE_STORE, null, $returnPathSet],
- [Transport::XML_PATH_SENDING_RETURN_PATH_EMAIL, ScopeInterface::SCOPE_STORE, null, $returnPathEmail]
- ];
- $this->scopeConfigMock->expects($this->exactly(2))
- ->method('getValue')
- ->willReturnMap($map);
- }
-
- /**
- * Data provider for testSendMessageWithoutReturnPath
- * @return array
- */
- public function sendMessageWithoutReturnPathDataProvider()
- {
- return [
- [0],
- ['0'],
- [3],
- ['2', null],
- [2, null],
- ];
- }
-
- /**
- * Data provider for testSendMessageWithDefaultReturnPath
- * @return array
- */
- public function sendMessageWithDefaultReturnPathDataProvider()
- {
- return [
- [1, 'test@exemple.com'],
- ['1', 'test@exemple.com'],
- ['1', '']
- ];
- }
-
- /**
- * Data provider for testSendMessageWithCustomReturnPath
- * @return array
- */
- public function sendMessageWithCustomReturnPathDataProvider()
- {
- return [
- [2, 'test@exemple.com'],
- ['2', 'test@exemple.com'],
- ['2', '']
- ];
- }
-}
diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json
index bffc825a4c872..482b63a2a34d7 100644
--- a/app/code/Magento/Email/composer.json
+++ b/app/code/Magento/Email/composer.json
@@ -15,7 +15,7 @@
"magento/module-theme": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Email/view/frontend/email/header.html b/app/code/Magento/Email/view/frontend/email/header.html
index a6895f629b641..c4f49698dc69b 100644
--- a/app/code/Magento/Email/view/frontend/email/header.html
+++ b/app/code/Magento/Email/view/frontend/email/header.html
@@ -43,8 +43,6 @@
{{if logo_height}}
height="{{var logo_height}}"
- {{else}}
- height="52"
{{/if}}
src="{{var logo_url}}"
diff --git a/app/code/Magento/Email/view/frontend/web/logo_email.png b/app/code/Magento/Email/view/frontend/web/logo_email.png
index d01b530456e81..215e9d06edcdc 100644
Binary files a/app/code/Magento/Email/view/frontend/web/logo_email.png and b/app/code/Magento/Email/view/frontend/web/logo_email.png differ
diff --git a/app/code/Magento/EncryptionKey/composer.json b/app/code/Magento/EncryptionKey/composer.json
index 57298d2a9736b..1044173d8921d 100644
--- a/app/code/Magento/EncryptionKey/composer.json
+++ b/app/code/Magento/EncryptionKey/composer.json
@@ -8,7 +8,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"proprietary"
],
diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json
index 55ff9fb83eb68..9211bcffb0f71 100644
--- a/app/code/Magento/Fedex/composer.json
+++ b/app/code/Magento/Fedex/composer.json
@@ -15,7 +15,7 @@
"lib-libxml": "*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php
index ec8a8841f6477..608bef3ee091b 100644
--- a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php
+++ b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php
@@ -128,7 +128,7 @@ public function testAfterSaveGiftMessages()
/**
* @expectedException \Magento\Framework\Exception\CouldNotSaveException
- * @expectedMessage Could not add gift message to order:Test message
+ * @expectedExceptionMessage Could not add gift message to order: "Test message"
*/
public function testAfterSaveIfGiftMessagesNotExist()
{
@@ -146,7 +146,7 @@ public function testAfterSaveIfGiftMessagesNotExist()
$this->giftMessageOrderRepositoryMock
->expects($this->once())
->method('save')
- ->willThrowException(new \Exception('TestMessage'));
+ ->willThrowException(new \Exception('Test message'));
// save Gift Messages on item level
$this->orderMock->expects($this->never())->method('getItems');
@@ -155,7 +155,7 @@ public function testAfterSaveIfGiftMessagesNotExist()
/**
* @expectedException \Magento\Framework\Exception\CouldNotSaveException
- * @expectedMessage Could not add gift message to order:Test message
+ * @expectedExceptionMessage Could not add gift message to order's item: "Test message"
*/
public function testAfterSaveIfItemGiftMessagesNotExist()
{
@@ -185,7 +185,7 @@ public function testAfterSaveIfItemGiftMessagesNotExist()
$this->giftMessageOrderItemRepositoryMock
->expects($this->once())->method('save')
->with($orderId, $orderItemId, $this->giftMessageMock)
- ->willThrowException(new \Exception('TestMessage'));
+ ->willThrowException(new \Exception('Test message'));
$this->plugin->afterSave($this->orderRepositoryMock, $this->orderMock);
}
}
diff --git a/app/code/Magento/GiftMessage/Test/Unit/Observer/SalesEventQuoteMergeTest.php b/app/code/Magento/GiftMessage/Test/Unit/Observer/SalesEventQuoteMergeTest.php
new file mode 100644
index 0000000000000..e7d9277593350
--- /dev/null
+++ b/app/code/Magento/GiftMessage/Test/Unit/Observer/SalesEventQuoteMergeTest.php
@@ -0,0 +1,81 @@
+salesEventQuoteMerge = $objectManger->getObject(SalesEventQuoteMerge::class);
+ }
+
+ /**
+ * @dataProvider dataProviderGiftMessageId
+ *
+ * @param null|int $giftMessageId
+ *
+ * @return void
+ */
+ public function testExecute($giftMessageId)
+ {
+ $sourceQuoteMock = $this->createPartialMock(Quote::class, ['getGiftMessageId']);
+ $sourceQuoteMock->expects($this->once())
+ ->method('getGiftMessageId')
+ ->willReturn($giftMessageId);
+
+ $targetQuoteMock = $this->createPartialMock(Quote::class, ['setGiftMessageId']);
+
+ if ($giftMessageId) {
+ $targetQuoteMock->expects($this->once())
+ ->method('setGiftMessageId');
+ } else {
+ $targetQuoteMock->expects($this->never())
+ ->method('setGiftMessageId');
+ }
+
+ $observer = $this->createMock(Observer::class);
+ $observer->expects($this->exactly(2))
+ ->method('getData')
+ ->willReturnMap([
+ ['quote', null, $targetQuoteMock],
+ ['source', null, $sourceQuoteMock]
+ ]);
+
+ $this->salesEventQuoteMerge->execute($observer);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProviderGiftMessageId(): array
+ {
+ return [
+ [null],
+ [1]
+ ];
+ }
+}
diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json
index 6a098af78e28b..d8fa39fa590a4 100644
--- a/app/code/Magento/GiftMessage/composer.json
+++ b/app/code/Magento/GiftMessage/composer.json
@@ -17,7 +17,7 @@
"magento/module-multishipping": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js b/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js
index d025f6974f35e..4c455c83a77a9 100644
--- a/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js
+++ b/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js
@@ -31,8 +31,9 @@ define([
this.itemId = this.itemId || 'orderLevel';
model = new GiftMessage(this.itemId);
- giftOptions.addOption(model);
this.model = model;
+ this.isResultBlockVisible();
+ giftOptions.addOption(model);
this.model.getObservable('isClear').subscribe(function (value) {
if (value == true) { //eslint-disable-line eqeqeq
@@ -40,8 +41,6 @@ define([
self.model.getObservable('alreadyAdded')(true);
}
});
-
- this.isResultBlockVisible();
},
/**
diff --git a/app/code/Magento/GoogleAdwords/composer.json b/app/code/Magento/GoogleAdwords/composer.json
index da44eb6c785d2..dec1440ecf174 100644
--- a/app/code/Magento/GoogleAdwords/composer.json
+++ b/app/code/Magento/GoogleAdwords/composer.json
@@ -8,7 +8,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json
index a5ab4caff2927..138aa560e8bcd 100644
--- a/app/code/Magento/GoogleAnalytics/composer.json
+++ b/app/code/Magento/GoogleAnalytics/composer.json
@@ -12,7 +12,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GoogleOptimizer/composer.json b/app/code/Magento/GoogleOptimizer/composer.json
index a84645b897298..5d84613c0e13c 100644
--- a/app/code/Magento/GoogleOptimizer/composer.json
+++ b/app/code/Magento/GoogleOptimizer/composer.json
@@ -12,7 +12,7 @@
"magento/module-ui": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GroupedImportExport/composer.json b/app/code/Magento/GroupedImportExport/composer.json
index 09d5f8894b354..092c40d011580 100644
--- a/app/code/Magento/GroupedImportExport/composer.json
+++ b/app/code/Magento/GroupedImportExport/composer.json
@@ -11,7 +11,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
index b6a3aede21ad2..7bdf7c0112795 100644
--- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
+++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
@@ -341,7 +341,7 @@ protected function getProductInfo(\Magento\Framework\DataObject $buyRequest, $pr
if ($isStrictProcessMode && !$subProduct->getQty()) {
return __('Please specify the quantity of product(s).')->render();
}
- $productsInfo[$subProduct->getId()] = (int)$subProduct->getQty();
+ $productsInfo[$subProduct->getId()] = $subProduct->isSalable() ? (float)$subProduct->getQty() : 0;
}
}
diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Data/GroupedProductData.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Data/GroupedProductData.xml
new file mode 100644
index 0000000000000..e760b877fa33d
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Test/Mftf/Data/GroupedProductData.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+ api-grouped-product
+ grouped
+ 4
+ Api Grouped Product
+ 1
+ api-grouped-product
+ EavStockItem
+ ApiProductDescription
+ ApiProductShortDescription
+
+
diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkData.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkData.xml
new file mode 100644
index 0000000000000..362e595593783
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkData.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+ associated
+ simple
+ 1
+ Qty1000
+
+
+ 2
+
+
diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkExtensionAttributeData.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkExtensionAttributeData.xml
new file mode 100644
index 0000000000000..b580c876a6f30
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinkExtensionAttributeData.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ 1000
+
+
diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinksData.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinksData.xml
new file mode 100644
index 0000000000000..68c95e856e2f8
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Test/Mftf/Data/ProductLinksData.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ ProductLinkSimple1
+
+
+ ProductLinkSimple2
+
+
+
+ - ProductLinkSimple1
+ - ProductLinkSimple2
+
+
+
diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Metadata/product-meta.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Metadata/product-meta.xml
new file mode 100644
index 0000000000000..87fa0a6379dd3
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Test/Mftf/Metadata/product-meta.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ application/json
+
+ string
+ string
+ integer
+ number
+ integer
+ integer
+ string
+ string
+ string
+ integer
+ product_extension_attribute
+
+ product_link
+
+
+ custom_attribute_array
+
+
+ product_option
+
+
+
+
+
+ application/json
+
+
+ application/json
+
+
diff --git a/app/code/Magento/GroupedProduct/composer.json b/app/code/Magento/GroupedProduct/composer.json
index c2031fc3332f0..7107903a91a58 100644
--- a/app/code/Magento/GroupedProduct/composer.json
+++ b/app/code/Magento/GroupedProduct/composer.json
@@ -21,7 +21,7 @@
"magento/module-grouped-product-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
index 822795abb0b44..f67a4c5db1317 100644
--- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
+++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
@@ -199,7 +199,10 @@ protected function _prepareForm()
'label' => __('Select File to Import'),
'title' => __('Select File to Import'),
'required' => true,
- 'class' => 'input-file'
+ 'class' => 'input-file',
+ 'note' => __(
+ 'File must be saved in UTF-8 encoding for proper import'
+ ),
]
);
$fieldsets['upload']->addField(
diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php
index df9f63e79b75e..6c99e59d1fe05 100644
--- a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php
+++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php
@@ -42,12 +42,7 @@ public function execute()
/** @var $import \Magento\ImportExport\Model\Import */
$import = $this->getImport()->setData($data);
try {
- $source = ImportAdapter::findAdapterFor(
- $import->uploadSource(),
- $this->_objectManager->create(\Magento\Framework\Filesystem::class)
- ->getDirectoryWrite(DirectoryList::ROOT),
- $data[$import::FIELD_FIELD_SEPARATOR]
- );
+ $source = $import->uploadFileAndGetSource();
$this->processValidationResult($import->validateSource($source), $resultBlock);
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$resultBlock->addError($e->getMessage());
diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php
index 092b721b82435..85efb85a6a7c8 100644
--- a/app/code/Magento/ImportExport/Model/Import.php
+++ b/app/code/Magento/ImportExport/Model/Import.php
@@ -10,6 +10,7 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\HTTP\Adapter\FileTransferFactory;
+use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
@@ -79,6 +80,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
*/
const FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR = '_import_multiple_value_separator';
+ /**
+ * Import empty attribute value constant.
+ */
+ const FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT = '_import_empty_attribute_value_constant';
+
/**
* Allow multiple values wrapping in double quotes for additional attributes.
*/
@@ -91,6 +97,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
*/
const DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR = ',';
+ /**
+ * default empty attribute value constant
+ */
+ const DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT = '__EMPTY__VALUE__';
+
/**#@+
* Import constants
*/
@@ -159,6 +170,16 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
*/
protected $_filesystem;
+ /**
+ * @var History
+ */
+ private $importHistoryModel;
+
+ /**
+ * @var DateTime
+ */
+ private $localeDate;
+
/**
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Filesystem $filesystem
@@ -173,7 +194,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
* @param Source\Import\Behavior\Factory $behaviorFactory
* @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
* @param History $importHistoryModel
- * @param \Magento\Framework\Stdlib\DateTime\DateTime
+ * @param DateTime $localeDate
* @param array $data
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
@@ -191,7 +212,7 @@ public function __construct(
\Magento\ImportExport\Model\Source\Import\Behavior\Factory $behaviorFactory,
\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
\Magento\ImportExport\Model\History $importHistoryModel,
- \Magento\Framework\Stdlib\DateTime\DateTime $localeDate,
+ DateTime $localeDate,
array $data = []
) {
$this->_importExportData = $importExportData;
@@ -234,7 +255,9 @@ protected function _getEntityAdapter()
) {
throw new \Magento\Framework\Exception\LocalizedException(
__(
- 'The entity adapter object must be an instance of %1 or %2.', \Magento\ImportExport\Model\Import\Entity\AbstractEntity::class, \Magento\ImportExport\Model\Import\AbstractEntity::class
+ 'The entity adapter object must be an instance of %1 or %2.',
+ \Magento\ImportExport\Model\Import\Entity\AbstractEntity::class,
+ \Magento\ImportExport\Model\Import\AbstractEntity::class
)
);
}
@@ -513,14 +536,27 @@ public function uploadSource()
}
$this->_removeBom($sourceFile);
$this->createHistoryReport($sourceFileRelative, $entity, $extension, $result);
- // trying to create source adapter for file and catch possible exception to be convinced in its adequacy
+
+ return $sourceFile;
+ }
+
+ /**
+ * Move uploaded file and provide source instance.
+ *
+ * @return Import\AbstractSource
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ public function uploadFileAndGetSource()
+ {
+ $sourceFile = $this->uploadSource();
try {
- $this->_getSourceAdapter($sourceFile);
+ $source = $this->_getSourceAdapter($sourceFile);
} catch (\Exception $e) {
- $this->_varDirectory->delete($sourceFileRelative);
+ $this->_varDirectory->delete($this->_varDirectory->getRelativePath($sourceFile));
throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()));
}
- return $sourceFile;
+
+ return $source;
}
/**
@@ -684,7 +720,9 @@ public function isReportEntityType($entity = null)
try {
$result = $this->_getEntityAdapter()->isNeedToLogInHistory();
} catch (\Exception $e) {
- throw new \Magento\Framework\Exception\LocalizedException(__('Please enter a correct entity model'));
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('Please enter a correct entity model')
+ );
}
} else {
throw new \Magento\Framework\Exception\LocalizedException(__('Please enter a correct entity model'));
@@ -696,11 +734,11 @@ public function isReportEntityType($entity = null)
}
/**
- * Create history report
+ * Create history report.
*
+ * @param string $sourceFileRelative
* @param string $entity
* @param string $extension
- * @param string $sourceFileRelative
* @param array $result
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
@@ -713,7 +751,7 @@ protected function createHistoryReport($sourceFileRelative, $entity, $extension
$sourceFileRelative = $this->_varDirectory->getRelativePath(self::IMPORT_DIR . $fileName);
} elseif (isset($result['name'])) {
$fileName = $result['name'];
- } elseif (!is_null($extension)) {
+ } elseif ($extension !== null) {
$fileName = $entity . $extension;
} else {
$fileName = basename($sourceFileRelative);
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
index e2398e792b817..f61f21b093fd3 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
+++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
@@ -554,6 +554,7 @@ public function getBehavior()
$this->_parameters['behavior']
) ||
$this->_parameters['behavior'] != ImportExport::BEHAVIOR_APPEND &&
+ $this->_parameters['behavior'] != ImportExport::BEHAVIOR_ADD_UPDATE &&
$this->_parameters['behavior'] != ImportExport::BEHAVIOR_REPLACE &&
$this->_parameters['behavior'] != ImportExport::BEHAVIOR_DELETE
) {
diff --git a/app/code/Magento/ImportExport/Model/Import/Source/Zip.php b/app/code/Magento/ImportExport/Model/Import/Source/Zip.php
index b7fafc43ca4ed..8ff46b9509de7 100644
--- a/app/code/Magento/ImportExport/Model/Import/Source/Zip.php
+++ b/app/code/Magento/ImportExport/Model/Import/Source/Zip.php
@@ -5,6 +5,8 @@
*/
namespace Magento\ImportExport\Model\Import\Source;
+use Magento\Framework\Exception\ValidatorException;
+
/**
* Zip import adapter.
*/
@@ -14,6 +16,7 @@ class Zip extends Csv
* @param string $file
* @param \Magento\Framework\Filesystem\Directory\Write $directory
* @param string $options
+ * @throws \Magento\Framework\Exception\ValidatorException
*/
public function __construct(
$file,
@@ -21,10 +24,14 @@ public function __construct(
$options
) {
$zip = new \Magento\Framework\Archive\Zip();
- $file = $zip->unpack(
- $directory->getRelativePath($file),
- $directory->getRelativePath(preg_replace('/\.zip$/i', '.csv', $file))
+ $csvFile = $zip->unpack(
+ $file,
+ preg_replace('/\.zip$/i', '.csv', $file)
);
- parent::__construct($file, $directory, $options);
+ if (!$csvFile) {
+ throw new ValidatorException(__('Sorry, but the data is invalid or the file is not uploaded.'));
+ }
+ $directory->delete($directory->getRelativePath($file));
+ parent::__construct($csvFile, $directory, $options);
}
}
diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json
index affe85aed48bd..7df4f98de95f4 100644
--- a/app/code/Magento/ImportExport/composer.json
+++ b/app/code/Magento/ImportExport/composer.json
@@ -12,7 +12,7 @@
"ext-ctype": "*"
},
"type": "magento2-module",
- "version": "100.2.6",
+ "version": "100.2.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Indexer/composer.json b/app/code/Magento/Indexer/composer.json
index 1667f8a05a5e8..a0fa62c3d7358 100644
--- a/app/code/Magento/Indexer/composer.json
+++ b/app/code/Magento/Indexer/composer.json
@@ -7,7 +7,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/InstantPurchase/composer.json b/app/code/Magento/InstantPurchase/composer.json
index cd7684254e408..d7257c7a46d90 100644
--- a/app/code/Magento/InstantPurchase/composer.json
+++ b/app/code/Magento/InstantPurchase/composer.json
@@ -2,7 +2,7 @@
"name": "magento/module-instant-purchase",
"description": "N/A",
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Integration/Model/CustomerTokenService.php b/app/code/Magento/Integration/Model/CustomerTokenService.php
index 947ca6f9f8821..adacf5ebacf71 100644
--- a/app/code/Magento/Integration/Model/CustomerTokenService.php
+++ b/app/code/Magento/Integration/Model/CustomerTokenService.php
@@ -14,6 +14,7 @@
use Magento\Integration\Model\ResourceModel\Oauth\Token\CollectionFactory as TokenCollectionFactory;
use Magento\Integration\Model\Oauth\Token\RequestThrottler;
use Magento\Framework\Exception\AuthenticationException;
+use Magento\Framework\Event\ManagerInterface;
class CustomerTokenService implements \Magento\Integration\Api\CustomerTokenServiceInterface
{
@@ -48,6 +49,11 @@ class CustomerTokenService implements \Magento\Integration\Api\CustomerTokenServ
*/
private $requestThrottler;
+ /**
+ * @var Magento\Framework\Event\ManagerInterface
+ */
+ private $eventManager;
+
/**
* Initialize service
*
@@ -55,17 +61,21 @@ class CustomerTokenService implements \Magento\Integration\Api\CustomerTokenServ
* @param AccountManagementInterface $accountManagement
* @param TokenCollectionFactory $tokenModelCollectionFactory
* @param \Magento\Integration\Model\CredentialsValidator $validatorHelper
+ * @param \Magento\Framework\Event\ManagerInterface $eventManager
*/
public function __construct(
TokenModelFactory $tokenModelFactory,
AccountManagementInterface $accountManagement,
TokenCollectionFactory $tokenModelCollectionFactory,
- CredentialsValidator $validatorHelper
+ CredentialsValidator $validatorHelper,
+ ManagerInterface $eventManager = null
) {
$this->tokenModelFactory = $tokenModelFactory;
$this->accountManagement = $accountManagement;
$this->tokenModelCollectionFactory = $tokenModelCollectionFactory;
$this->validatorHelper = $validatorHelper;
+ $this->eventManager = $eventManager ?: \Magento\Framework\App\ObjectManager::getInstance()
+ ->get(ManagerInterface::class);
}
/**
@@ -83,6 +93,7 @@ public function createCustomerAccessToken($username, $password)
__('You did not sign in correctly or your account is temporarily disabled.')
);
}
+ $this->eventManager->dispatch('customer_login', ['customer' => $customerDataObject]);
$this->getRequestThrottler()->resetAuthenticationFailuresCount($username, RequestThrottler::USER_TYPE_CUSTOMER);
return $this->tokenModelFactory->create()->createCustomerToken($customerDataObject->getId())->getToken();
}
diff --git a/app/code/Magento/Integration/Plugin/Model/AdminUser.php b/app/code/Magento/Integration/Plugin/Model/AdminUser.php
index df3766250caa7..80a459eda46fb 100644
--- a/app/code/Magento/Integration/Plugin/Model/AdminUser.php
+++ b/app/code/Magento/Integration/Plugin/Model/AdminUser.php
@@ -6,6 +6,8 @@
namespace Magento\Integration\Plugin\Model;
use Magento\Integration\Model\AdminTokenService;
+use Magento\Framework\DataObject;
+use Magento\User\Model\User;
/**
* Plugin to delete admin tokens when admin becomes inactive
@@ -29,16 +31,15 @@ public function __construct(
/**
* Check if admin is inactive - if so, invalidate their tokens
*
- * @param \Magento\User\Model\User $subject
- * @param \Magento\Framework\DataObject $object
- * @return $this
+ * @param User $subject
+ * @param DataObject $object
+ * @return User
+ * @throws \Magento\Framework\Exception\LocalizedException
*/
- public function afterSave(
- \Magento\User\Model\User $subject,
- \Magento\Framework\DataObject $object
- ) {
+ public function afterSave(User $subject, DataObject $object): User
+ {
$isActive = $object->getIsActive();
- if (isset($isActive) && $isActive == 0) {
+ if ($isActive !== null && $isActive == 0) {
$this->adminTokenService->revokeAdminAccessToken($object->getId());
}
return $subject;
diff --git a/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php
index ecd4788545c0a..170e7e42d919e 100644
--- a/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php
+++ b/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php
@@ -32,6 +32,9 @@ class CustomerTokenServiceTest extends \PHPUnit\Framework\TestCase
/** @var \Magento\Integration\Model\Oauth\Token|\PHPUnit_Framework_MockObject_MockObject */
private $_tokenMock;
+ /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
+ protected $manager;
+
protected function setUp()
{
$this->_tokenFactoryMock = $this->getMockBuilder(\Magento\Integration\Model\Oauth\TokenFactory::class)
@@ -67,11 +70,14 @@ protected function setUp()
\Magento\Integration\Model\CredentialsValidator::class
)->disableOriginalConstructor()->getMock();
+ $this->manager = $this->createMock(\Magento\Framework\Event\ManagerInterface::class);
+
$this->_tokenService = new \Magento\Integration\Model\CustomerTokenService(
$this->_tokenFactoryMock,
$this->_accountManagementMock,
$this->_tokenModelCollectionFactoryMock,
- $this->validatorHelperMock
+ $this->validatorHelperMock,
+ $this->manager
);
}
diff --git a/app/code/Magento/Integration/composer.json b/app/code/Magento/Integration/composer.json
index 75bd7a04d0dcc..74f2db3d68238 100644
--- a/app/code/Magento/Integration/composer.json
+++ b/app/code/Magento/Integration/composer.json
@@ -12,7 +12,7 @@
"magento/module-authorization": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Integration/etc/webapi_rest/events.xml b/app/code/Magento/Integration/etc/webapi_rest/events.xml
new file mode 100644
index 0000000000000..e978698734277
--- /dev/null
+++ b/app/code/Magento/Integration/etc/webapi_rest/events.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Integration/etc/webapi_soap/events.xml b/app/code/Magento/Integration/etc/webapi_soap/events.xml
new file mode 100644
index 0000000000000..e978698734277
--- /dev/null
+++ b/app/code/Magento/Integration/etc/webapi_soap/events.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/LayeredNavigation/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserver.php b/app/code/Magento/LayeredNavigation/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserver.php
index fc1edeb1e2392..dc4d3579f4628 100644
--- a/app/code/Magento/LayeredNavigation/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserver.php
+++ b/app/code/Magento/LayeredNavigation/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserver.php
@@ -55,7 +55,11 @@ public function execute(\Magento\Framework\Event\Observer $observer)
'name' => 'is_filterable',
'label' => __("Use in Layered Navigation"),
'title' => __('Can be used only with catalog input type Yes/No, Dropdown, Multiple Select and Price'),
- 'note' => __('Can be used only with catalog input type Yes/No, Dropdown, Multiple Select and Price.'),
+ 'note' => __(
+ 'Can be used only with catalog input type Yes/No, Dropdown, Multiple Select and Price.
+ Price is not compatible with \'Filterable (no results)\' option -
+ it will make no affect on Price filter.'
+ ),
'values' => [
['value' => '0', 'label' => __('No')],
['value' => '1', 'label' => __('Filterable (with results)')],
diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/StorefrontCheckingResultsOfFiltersTest.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/StorefrontCheckingResultsOfFiltersTest.xml
new file mode 100644
index 0000000000000..1d4a861ffe7b8
--- /dev/null
+++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/StorefrontCheckingResultsOfFiltersTest.xml
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/LayeredNavigation/composer.json b/app/code/Magento/LayeredNavigation/composer.json
index b8dfc77532784..8ce17fe30ec35 100644
--- a/app/code/Magento/LayeredNavigation/composer.json
+++ b/app/code/Magento/LayeredNavigation/composer.json
@@ -8,7 +8,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Marketplace/composer.json b/app/code/Magento/Marketplace/composer.json
index 5ce8666ec1bb2..02824a6796fc7 100644
--- a/app/code/Magento/Marketplace/composer.json
+++ b/app/code/Magento/Marketplace/composer.json
@@ -7,7 +7,7 @@
"magento/module-backend": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/MediaStorage/composer.json b/app/code/Magento/MediaStorage/composer.json
index afb290a682274..a891dce37624d 100644
--- a/app/code/Magento/MediaStorage/composer.json
+++ b/app/code/Magento/MediaStorage/composer.json
@@ -9,7 +9,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json
index 97bc64e48ce01..625bec5d6c9d2 100644
--- a/app/code/Magento/Msrp/composer.json
+++ b/app/code/Magento/Msrp/composer.json
@@ -16,7 +16,7 @@
"magento/module-msrp-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Multishipping/composer.json b/app/code/Magento/Multishipping/composer.json
index 111204915e4c8..d32bb1f5bd82a 100644
--- a/app/code/Magento/Multishipping/composer.json
+++ b/app/code/Magento/Multishipping/composer.json
@@ -15,7 +15,7 @@
"magento/module-theme": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/NewRelicReporting/Model/Cron/ReportModulesInfo.php b/app/code/Magento/NewRelicReporting/Model/Cron/ReportModulesInfo.php
index 9cdc90bc46b2a..78c485c5bb6f5 100644
--- a/app/code/Magento/NewRelicReporting/Model/Cron/ReportModulesInfo.php
+++ b/app/code/Magento/NewRelicReporting/Model/Cron/ReportModulesInfo.php
@@ -64,6 +64,7 @@ public function report()
$moduleData = $this->collect->getModuleData();
if (count($moduleData['changes']) > 0) {
foreach ($moduleData['changes'] as $change) {
+ $modelData = [];
switch ($change['type']) {
case Config::ENABLED:
$modelData = [
diff --git a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php
index ec21e06976b8b..9882a1ce9b0b8 100644
--- a/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php
+++ b/app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php
@@ -31,7 +31,7 @@ public function addCustomParameter($param, $value)
/**
* Wrapper for 'newrelic_notice_error' function
*
- * @param Exception $exception
+ * @param \Exception $exception
* @return void
*/
public function reportError($exception)
diff --git a/app/code/Magento/NewRelicReporting/composer.json b/app/code/Magento/NewRelicReporting/composer.json
index 18a1a2df57336..abb2a200ed723 100644
--- a/app/code/Magento/NewRelicReporting/composer.json
+++ b/app/code/Magento/NewRelicReporting/composer.json
@@ -13,7 +13,7 @@
"magento/magento-composer-installer": "*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/Unsubscribe.php b/app/code/Magento/Newsletter/Controller/Subscriber/Unsubscribe.php
index efc469e15deaa..ed415d04450a6 100644
--- a/app/code/Magento/Newsletter/Controller/Subscriber/Unsubscribe.php
+++ b/app/code/Magento/Newsletter/Controller/Subscriber/Unsubscribe.php
@@ -4,13 +4,17 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Newsletter\Controller\Subscriber;
+/**
+ * Controller for unsubscribing customers.
+ */
class Unsubscribe extends \Magento\Newsletter\Controller\Subscriber
{
/**
* Unsubscribe newsletter
- * @return void
+ * @return \Magento\Backend\Model\View\Result\Redirect
*/
public function execute()
{
@@ -27,6 +31,10 @@ public function execute()
$this->messageManager->addException($e, __('Something went wrong while unsubscribing you.'));
}
}
- $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
+ /** @var \Magento\Backend\Model\View\Result\Redirect $redirect */
+ $redirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT);
+ $redirectUrl = $this->_redirect->getRedirectUrl();
+
+ return $redirect->setUrl($redirectUrl);
}
}
diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php
index 58b51009c205a..792dcf2fbe689 100644
--- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php
+++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php
@@ -6,12 +6,13 @@
namespace Magento\Newsletter\Model\Plugin;
use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository;
+use Magento\Customer\Api\Data\CustomerExtensionInterface;
use Magento\Customer\Api\Data\CustomerInterface;
-use Magento\Newsletter\Model\SubscriberFactory;
use Magento\Framework\Api\ExtensionAttributesFactory;
-use Magento\Newsletter\Model\ResourceModel\Subscriber;
-use Magento\Customer\Api\Data\CustomerExtensionInterface;
use Magento\Framework\App\ObjectManager;
+use Magento\Newsletter\Model\ResourceModel\Subscriber;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Store\Model\StoreManagerInterface;
class CustomerPlugin
{
@@ -37,22 +38,30 @@ class CustomerPlugin
*/
private $customerSubscriptionStatus = [];
+ /**
+ * @var StoreManagerInterface
+ */
+ private $storeManager;
+
/**
* Initialize dependencies.
*
* @param SubscriberFactory $subscriberFactory
* @param ExtensionAttributesFactory|null $extensionFactory
* @param Subscriber|null $subscriberResource
+ * @param StoreManagerInterface|null $storeManager
*/
public function __construct(
SubscriberFactory $subscriberFactory,
ExtensionAttributesFactory $extensionFactory = null,
- Subscriber $subscriberResource = null
+ Subscriber $subscriberResource = null,
+ StoreManagerInterface $storeManager = null
) {
$this->subscriberFactory = $subscriberFactory;
$this->extensionFactory = $extensionFactory
?: ObjectManager::getInstance()->get(ExtensionAttributesFactory::class);
$this->subscriberResource = $subscriberResource ?: ObjectManager::getInstance()->get(Subscriber::class);
+ $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
}
/**
@@ -149,6 +158,8 @@ public function afterDelete(CustomerRepository $subject, $result, CustomerInterf
public function afterGetById(CustomerRepository $subject, CustomerInterface $customer)
{
$extensionAttributes = $customer->getExtensionAttributes();
+ $storeId = $this->storeManager->getStore()->getId();
+ $customer->setStoreId($storeId);
if ($extensionAttributes === null) {
/** @var CustomerExtensionInterface $extensionAttributes */
$extensionAttributes = $this->extensionFactory->create(CustomerInterface::class);
diff --git a/app/code/Magento/Newsletter/Model/ResourceModel/Subscriber.php b/app/code/Magento/Newsletter/Model/ResourceModel/Subscriber.php
index c7ce4b2f2f11b..131eca5f33487 100644
--- a/app/code/Magento/Newsletter/Model/ResourceModel/Subscriber.php
+++ b/app/code/Magento/Newsletter/Model/ResourceModel/Subscriber.php
@@ -5,6 +5,9 @@
*/
namespace Magento\Newsletter\Model\ResourceModel;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Framework\App\ObjectManager;
+
/**
* Newsletter subscriber resource model
*
@@ -48,6 +51,13 @@ class Subscriber extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
*/
protected $mathRandom;
+ /**
+ * Store manager
+ *
+ * @var StoreManagerInterface
+ */
+ private $storeManager;
+
/**
* Construct
*
@@ -55,15 +65,19 @@ class Subscriber extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
* @param \Magento\Framework\Stdlib\DateTime\DateTime $date
* @param \Magento\Framework\Math\Random $mathRandom
* @param string $connectionName
+ * @param StoreManagerInterface $storeManager
*/
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context,
\Magento\Framework\Stdlib\DateTime\DateTime $date,
\Magento\Framework\Math\Random $mathRandom,
- $connectionName = null
+ $connectionName = null,
+ StoreManagerInterface $storeManager = null
) {
$this->_date = $date;
$this->mathRandom = $mathRandom;
+ $this->storeManager = $storeManager ?: ObjectManager::getInstance()
+ ->get(StoreManagerInterface::class);
parent::__construct($context, $connectionName);
}
@@ -118,6 +132,9 @@ public function loadByEmail($subscriberEmail)
*/
public function loadByCustomerData(\Magento\Customer\Api\Data\CustomerInterface $customer)
{
+ $storeId = (int)$customer->getStoreId() ?: $this->storeManager
+ ->getWebsite($customer->getWebsiteId())->getDefaultStore()->getId();
+
$select = $this->connection
->select()
->from($this->getMainTable())
@@ -128,7 +145,7 @@ public function loadByCustomerData(\Magento\Customer\Api\Data\CustomerInterface
$select,
[
'customer_id' => $customer->getId(),
- 'store_id' => $customer->getStoreId()
+ 'store_id' => $storeId
]
);
@@ -146,7 +163,7 @@ public function loadByCustomerData(\Magento\Customer\Api\Data\CustomerInterface
$select,
[
'subscriber_email' => $customer->getEmail(),
- 'store_id' => $customer->getStoreId()
+ 'store_id' => $storeId
]
);
diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php
index b916f20dbe770..a1d929d8db7bf 100644
--- a/app/code/Magento/Newsletter/Model/Subscriber.php
+++ b/app/code/Magento/Newsletter/Model/Subscriber.php
@@ -594,6 +594,8 @@ protected function _updateCustomerSubscription($customerId, $subscribe)
} elseif (($this->getStatus() == self::STATUS_UNCONFIRMED) && ($customerData->getConfirmation() === null)) {
$status = self::STATUS_SUBSCRIBED;
$sendInformationEmail = true;
+ } elseif (($this->getStatus() == self::STATUS_NOT_ACTIVE) && ($customerData->getConfirmation() === null)) {
+ $status = self::STATUS_NOT_ACTIVE;
} else {
$status = self::STATUS_UNSUBSCRIBED;
}
@@ -610,16 +612,17 @@ protected function _updateCustomerSubscription($customerId, $subscribe)
$this->setStatus($status);
+ $storeId = $customerData->getStoreId();
+ if ((int)$customerData->getStoreId() === 0) {
+ $storeId = $this->_storeManager->getWebsite($customerData->getWebsiteId())->getDefaultStore()->getId();
+ }
+
if (!$this->getId()) {
- $storeId = $customerData->getStoreId();
- if ($customerData->getStoreId() == 0) {
- $storeId = $this->_storeManager->getWebsite($customerData->getWebsiteId())->getDefaultStore()->getId();
- }
$this->setStoreId($storeId)
->setCustomerId($customerData->getId())
->setEmail($customerData->getEmail());
} else {
- $this->setStoreId($customerData->getStoreId())
+ $this->setStoreId($storeId)
->setEmail($customerData->getEmail());
}
diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php
index 39a9c2a0d95d2..0bc79244bdf1c 100644
--- a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php
+++ b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php
@@ -10,6 +10,8 @@
use Magento\Customer\Api\Data\CustomerExtensionInterface;
use Magento\Framework\Api\ExtensionAttributesFactory;
use Magento\Newsletter\Model\ResourceModel\Subscriber;
+use Magento\Store\Model\Store;
+use Magento\Store\Model\StoreManagerInterface;
class CustomerPluginTest extends \PHPUnit\Framework\TestCase
{
@@ -53,6 +55,11 @@ class CustomerPluginTest extends \PHPUnit\Framework\TestCase
*/
private $customerMock;
+ /**
+ * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $storeManagerMock;
+
protected function setUp()
{
$this->subscriberFactory = $this->getMockBuilder(\Magento\Newsletter\Model\SubscriberFactory::class)
@@ -87,6 +94,8 @@ protected function setUp()
->setMethods(["getExtensionAttributes"])
->disableOriginalConstructor()
->getMockForAbstractClass();
+ $this->storeManagerMock = $this->createMock(StoreManagerInterface::class);
+
$this->subscriberFactory->expects($this->any())->method('create')->willReturn($this->subscriber);
$this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->plugin = $this->objectManager->getObject(
@@ -94,7 +103,8 @@ protected function setUp()
[
'subscriberFactory' => $this->subscriberFactory,
'extensionFactory' => $this->extensionFactoryMock,
- 'subscriberResource' => $this->subscriberResourceMock
+ 'subscriberResource' => $this->subscriberResourceMock,
+ 'storeManager' => $this->storeManagerMock,
]
);
}
@@ -198,6 +208,7 @@ public function testAfterGetByIdCreatesExtensionAttributesIfItIsNotSet(
) {
$subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class);
$subscriber = [$subscriberStatusKey => $subscriberStatusValue];
+ $this->prepareStoreData();
$this->extensionFactoryMock->expects($this->any())
->method('create')
->willReturn($this->customerExtensionMock);
@@ -223,6 +234,7 @@ public function testAfterGetByIdSetsIsSubscribedFlagIfItIsNotSet()
{
$subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class);
$subscriber = ['subscriber_id' => 1, 'subscriber_status' => 1];
+ $this->prepareStoreData();
$this->customerMock->expects($this->any())
->method('getExtensionAttributes')
->willReturn($this->customerExtensionMock);
@@ -255,4 +267,17 @@ public function afterGetByIdDataProvider()
[null, null, false]
];
}
+
+ /**
+ * Prepare store information
+ *
+ * @return void
+ */
+ private function prepareStoreData()
+ {
+ $storeId = 1;
+ $storeMock = $this->createMock(Store::class);
+ $storeMock->expects($this->any())->method('getId')->willReturn($storeId);
+ $this->storeManagerMock->expects($this->any())->method('getStore')->willReturn($storeMock);
+ }
}
diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/ProblemTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/ProblemTest.php
index 889fc11d71d7e..1de3e6096cd96 100644
--- a/app/code/Magento/Newsletter/Test/Unit/Model/ProblemTest.php
+++ b/app/code/Magento/Newsletter/Test/Unit/Model/ProblemTest.php
@@ -68,6 +68,7 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
$this->subscriberFactoryMock = $this->getMockBuilder(SubscriberFactory::class)
+ ->disableOriginalConstructor()
->getMock();
$this->subscriberMock = $this->getMockBuilder(Subscriber::class)
->disableOriginalConstructor()
diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php
index 99b23de5b6b6c..9c543c831ded3 100644
--- a/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php
+++ b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php
@@ -211,6 +211,7 @@ public function testSubscribeNotLoggedIn()
public function testUpdateSubscription()
{
+ $storeId = 2;
$customerId = 1;
$customerDataMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
->getMock();
@@ -232,7 +233,7 @@ public function testUpdateSubscription()
->method('getConfirmationStatus')
->with($customerId)
->willReturn('account_confirmation_required');
- $customerDataMock->expects($this->once())->method('getStoreId')->willReturn('store_id');
+ $customerDataMock->expects($this->exactly(2))->method('getStoreId')->willReturn($storeId);
$customerDataMock->expects($this->once())->method('getEmail')->willReturn('email');
$storeModel = $this->getMockBuilder(\Magento\Store\Model\Store::class)
@@ -246,6 +247,7 @@ public function testUpdateSubscription()
public function testUnsubscribeCustomerById()
{
+ $storeId = 2;
$customerId = 1;
$customerDataMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
->getMock();
@@ -263,7 +265,7 @@ public function testUnsubscribeCustomerById()
);
$customerDataMock->expects($this->atLeastOnce())->method('getId')->willReturn('id');
$this->resource->expects($this->atLeastOnce())->method('save')->willReturnSelf();
- $customerDataMock->expects($this->once())->method('getStoreId')->willReturn('store_id');
+ $customerDataMock->expects($this->exactly(2))->method('getStoreId')->willReturn($storeId);
$customerDataMock->expects($this->once())->method('getEmail')->willReturn('email');
$this->sendEmailCheck();
@@ -272,6 +274,7 @@ public function testUnsubscribeCustomerById()
public function testSubscribeCustomerById()
{
+ $storeId = 2;
$customerId = 1;
$customerDataMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
->getMock();
@@ -289,7 +292,7 @@ public function testSubscribeCustomerById()
);
$customerDataMock->expects($this->atLeastOnce())->method('getId')->willReturn('id');
$this->resource->expects($this->atLeastOnce())->method('save')->willReturnSelf();
- $customerDataMock->expects($this->once())->method('getStoreId')->willReturn('store_id');
+ $customerDataMock->expects($this->exactly(2))->method('getStoreId')->willReturn($storeId);
$customerDataMock->expects($this->once())->method('getEmail')->willReturn('email');
$this->sendEmailCheck();
@@ -298,6 +301,7 @@ public function testSubscribeCustomerById()
public function testSubscribeCustomerById1()
{
+ $storeId = 2;
$customerId = 1;
$customerDataMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
->getMock();
@@ -315,7 +319,7 @@ public function testSubscribeCustomerById1()
);
$customerDataMock->expects($this->atLeastOnce())->method('getId')->willReturn('id');
$this->resource->expects($this->atLeastOnce())->method('save')->willReturnSelf();
- $customerDataMock->expects($this->once())->method('getStoreId')->willReturn('store_id');
+ $customerDataMock->expects($this->exactly(2))->method('getStoreId')->willReturn($storeId);
$customerDataMock->expects($this->once())->method('getEmail')->willReturn('email');
$this->sendEmailCheck();
$this->customerAccountManagement->expects($this->once())
@@ -329,6 +333,7 @@ public function testSubscribeCustomerById1()
public function testSubscribeCustomerByIdAfterConfirmation()
{
+ $storeId = 2;
$customerId = 1;
$customerDataMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
->getMock();
@@ -346,7 +351,7 @@ public function testSubscribeCustomerByIdAfterConfirmation()
);
$customerDataMock->expects($this->atLeastOnce())->method('getId')->willReturn('id');
$this->resource->expects($this->atLeastOnce())->method('save')->willReturnSelf();
- $customerDataMock->expects($this->once())->method('getStoreId')->willReturn('store_id');
+ $customerDataMock->expects($this->exactly(2))->method('getStoreId')->willReturn($storeId);
$customerDataMock->expects($this->once())->method('getEmail')->willReturn('email');
$this->sendEmailCheck();
$this->customerAccountManagement->expects($this->never())->method('getConfirmationStatus');
diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json
index ef6158960aeee..a97d0bca5634d 100644
--- a/app/code/Magento/Newsletter/composer.json
+++ b/app/code/Magento/Newsletter/composer.json
@@ -14,7 +14,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.5",
+ "version": "100.2.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Newsletter/i18n/en_US.csv b/app/code/Magento/Newsletter/i18n/en_US.csv
index c49fdc80da810..388b583f990b1 100644
--- a/app/code/Magento/Newsletter/i18n/en_US.csv
+++ b/app/code/Magento/Newsletter/i18n/en_US.csv
@@ -67,8 +67,8 @@ Subscribers,Subscribers
"Something went wrong while saving this template.","Something went wrong while saving this template."
"Newsletter Subscription","Newsletter Subscription"
"Something went wrong while saving your subscription.","Something went wrong while saving your subscription."
-"We saved the subscription.","We saved the subscription."
-"We removed the subscription.","We removed the subscription."
+"We have saved your subscription.","We have saved your subscription."
+"We have removed your newsletter subscription.","We have removed your newsletter subscription."
"Your subscription has been confirmed.","Your subscription has been confirmed."
"This is an invalid subscription confirmation code.","This is an invalid subscription confirmation code."
"This is an invalid subscription ID.","This is an invalid subscription ID."
@@ -76,7 +76,7 @@ Subscribers,Subscribers
"Sorry, but the administrator denied subscription for guests. Please register.","Sorry, but the administrator denied subscription for guests. Please register."
"Please enter a valid email address.","Please enter a valid email address."
"This email address is already subscribed.","This email address is already subscribed."
-"The confirmation request has been sent.","The confirmation request has been sent."
+"A confirmation request has been sent.","A confirmation request has been sent."
"Thank you for your subscription.","Thank you for your subscription."
"There was a problem with the subscription: %1","There was a problem with the subscription: %1"
"Something went wrong with the subscription.","Something went wrong with the subscription."
@@ -151,3 +151,4 @@ Unconfirmed,Unconfirmed
Store,Store
"Store View","Store View"
"Newsletter Subscriptions","Newsletter Subscriptions"
+"We have updated your subscription.","We have updated your subscription."
diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json
index b737149d30a94..747db3d70602e 100644
--- a/app/code/Magento/OfflinePayments/composer.json
+++ b/app/code/Magento/OfflinePayments/composer.json
@@ -11,7 +11,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
index b67eb1b45fe45..cead9f838f4c0 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
@@ -60,6 +60,7 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
* @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory
* @param \Magento\OfflineShipping\Model\ResourceModel\Carrier\TablerateFactory $tablerateFactory
* @param array $data
+ * @throws LocalizedException
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
public function __construct(
diff --git a/app/code/Magento/OfflineShipping/composer.json b/app/code/Magento/OfflineShipping/composer.json
index 24b5f877c1279..e04816a3b1128 100644
--- a/app/code/Magento/OfflineShipping/composer.json
+++ b/app/code/Magento/OfflineShipping/composer.json
@@ -19,7 +19,7 @@
"magento/module-offline-shipping-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/PageCache/Model/System/Config/Backend/Ttl.php b/app/code/Magento/PageCache/Model/System/Config/Backend/Ttl.php
index dab8d7be16dd7..95b0ebe72ecd1 100644
--- a/app/code/Magento/PageCache/Model/System/Config/Backend/Ttl.php
+++ b/app/code/Magento/PageCache/Model/System/Config/Backend/Ttl.php
@@ -6,15 +6,49 @@
namespace Magento\PageCache\Model\System\Config\Backend;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Escaper;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\Exception\LocalizedException;
+
/**
- * Backend model for processing Public content cache lifetime settings
+ * Backend model for processing Public content cache lifetime settings.
*
* Class Ttl
*/
class Ttl extends \Magento\Framework\App\Config\Value
{
/**
- * Throw exception if Ttl data is invalid or empty
+ * @var Escaper
+ */
+ private $escaper;
+
+ /**
+ * @param \Magento\Framework\Model\Context $context
+ * @param \Magento\Framework\Registry $registry
+ * @param ScopeConfigInterface $config
+ * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
+ * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
+ * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
+ * @param array $data
+ * @param Escaper|null $escaper
+ */
+ public function __construct(
+ \Magento\Framework\Model\Context $context,
+ \Magento\Framework\Registry $registry,
+ ScopeConfigInterface $config,
+ \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
+ \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
+ \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
+ array $data = [],
+ Escaper $escaper = null
+ ) {
+ parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
+ $this->escaper = $escaper ?: ObjectManager::getInstance()->create(Escaper::class);
+ }
+
+ /**
+ * Throw exception if Ttl data is invalid or empty.
*
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
@@ -23,10 +57,14 @@ public function beforeSave()
{
$value = $this->getValue();
if ($value < 0 || !preg_match('/^[0-9]+$/', $value)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __('Ttl value "%1" is not valid. Please use only numbers equal or greater than zero.', $value)
+ throw new LocalizedException(
+ __(
+ 'Ttl value "%1" is not valid. Please use only numbers equal or greater than zero.',
+ $this->escaper->escapeHtml($value)
+ )
);
}
+
return $this;
}
}
diff --git a/app/code/Magento/PageCache/Test/Unit/Model/System/Config/Backend/TtlTest.php b/app/code/Magento/PageCache/Test/Unit/Model/System/Config/Backend/TtlTest.php
new file mode 100644
index 0000000000000..6fd3307de726c
--- /dev/null
+++ b/app/code/Magento/PageCache/Test/Unit/Model/System/Config/Backend/TtlTest.php
@@ -0,0 +1,109 @@
+getMockForAbstractClass(ScopeConfigInterface::class);
+ $configMock->expects($this->any())
+ ->method('getValue')
+ ->with('system/full_page_cache/default')
+ ->willReturn(['ttl' => 86400]);
+
+ $this->escaperMock = $this->getMockBuilder(Escaper::class)->disableOriginalConstructor()->getMock();
+
+ $this->ttl = $objectManager->getObject(
+ Ttl::class,
+ [
+ 'config' => $configMock,
+ 'data' => ['field' => 'ttl'],
+ 'escaper' => $this->escaperMock,
+ ]
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getValidValues(): array
+ {
+ return [
+ ['3600', '3600'],
+ ['10000', '10000'],
+ ['100000', '100000'],
+ ['1000000', '1000000'],
+ ];
+ }
+
+ /**
+ * @param string $value
+ * @param string $expectedValue
+ * @return void
+ * @dataProvider getValidValues
+ */
+ public function testBeforeSave(string $value, string $expectedValue)
+ {
+ $this->ttl->setValue($value);
+ $this->ttl->beforeSave();
+ $this->assertEquals($expectedValue, $this->ttl->getValue());
+ }
+
+ /**
+ * @return array
+ */
+ public function getInvalidValues(): array
+ {
+ return [
+ [''],
+ ['apple'],
+ ['123 street'],
+ ['-123'],
+ ];
+ }
+
+ /**
+ * @param string $value
+ * @return void
+ * @expectedException \Magento\Framework\Exception\LocalizedException
+ * @expectedExceptionMessageRegExp /Ttl value ".+" is not valid. Please .+ only numbers equal or greater than zero./
+ * @dataProvider getInvalidValues
+ */
+ public function testBeforeSaveInvalid(string $value)
+ {
+ $this->ttl->setValue($value);
+ $this->escaperMock->expects($this->any())->method('escapeHtml')->with($value)->willReturn($value);
+ $this->ttl->beforeSave();
+ }
+}
diff --git a/app/code/Magento/PageCache/composer.json b/app/code/Magento/PageCache/composer.json
index d492f3bc23a5f..2b6b62aef2c47 100644
--- a/app/code/Magento/PageCache/composer.json
+++ b/app/code/Magento/PageCache/composer.json
@@ -9,7 +9,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
index fccc8510ffc70..9ae916356d2b9 100644
--- a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
+++ b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
@@ -6,9 +6,10 @@
define([
'jquery',
'domReady',
+ 'consoleLogger',
'jquery/ui',
'mage/cookies'
-], function ($, domReady) {
+], function ($, domReady, consoleLogger) {
'use strict';
/**
@@ -41,7 +42,9 @@ define([
* @param {jQuery} element - Comment holder
*/
(function lookup(element) {
- var iframeHostName;
+ var iframeHostName,
+ contents,
+ elementContents;
// prevent cross origin iframe content reading
if ($(element).prop('tagName') === 'IFRAME') {
@@ -53,7 +56,30 @@ define([
}
}
- $(element).contents().each(function (index, el) {
+ /**
+ * Rewrite jQuery contents method
+ *
+ * @param {Object} el
+ * @returns {Object}
+ * @private
+ */
+ contents = function (el) {
+ return $.map(el, function (elem) {
+ try {
+ return $.nodeName(elem, 'iframe') ?
+ elem.contentDocument || (elem.contentWindow ? elem.contentWindow.document : []) :
+ $.merge([], elem.childNodes);
+ } catch (e) {
+ consoleLogger.error(e);
+
+ return [];
+ }
+ });
+ };
+
+ elementContents = contents($(element));
+
+ $.each(elementContents, function (index, el) {
switch (el.nodeType) {
case 1: // ELEMENT_NODE
lookup(el);
diff --git a/app/code/Magento/Payment/Test/Mftf/Data/ZeroSubtotalCheckoutPaymentMethodData.xml b/app/code/Magento/Payment/Test/Mftf/Data/ZeroSubtotalCheckoutPaymentMethodData.xml
new file mode 100644
index 0000000000000..0a9d6b66af6f9
--- /dev/null
+++ b/app/code/Magento/Payment/Test/Mftf/Data/ZeroSubtotalCheckoutPaymentMethodData.xml
@@ -0,0 +1,29 @@
+
+
+
+
+ Active
+ OrderStatusProcessing
+
+
+
+ 1
+
+
+ processing
+
+
+ pending
+
+
+
+ Active
+ OrderStatusPending
+
+
diff --git a/app/code/Magento/Payment/Test/Mftf/Metadata/payment_method-meta.xml b/app/code/Magento/Payment/Test/Mftf/Metadata/payment_method-meta.xml
new file mode 100644
index 0000000000000..b1e3577b9ccad
--- /dev/null
+++ b/app/code/Magento/Payment/Test/Mftf/Metadata/payment_method-meta.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+ string
+
+
+ string
+
+
+
+
+
+
diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json
index 678aaa01c2ae8..b5e7ecdfdaff9 100644
--- a/app/code/Magento/Payment/composer.json
+++ b/app/code/Magento/Payment/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Payment/etc/config.xml b/app/code/Magento/Payment/etc/config.xml
index 9fe859c96a941..663734fb066c7 100644
--- a/app/code/Magento/Payment/etc/config.xml
+++ b/app/code/Magento/Payment/etc/config.xml
@@ -13,6 +13,7 @@
Magento\Payment\Model\Method\Free
pending
No Payment Information Required
+ authorize
0
1
diff --git a/app/code/Magento/Payment/view/adminhtml/web/transparent.js b/app/code/Magento/Payment/view/adminhtml/web/js/transparent.js
similarity index 100%
rename from app/code/Magento/Payment/view/adminhtml/web/transparent.js
rename to app/code/Magento/Payment/view/adminhtml/web/js/transparent.js
diff --git a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js
index 8fb12093e36e4..785b636d5832f 100644
--- a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js
+++ b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js
@@ -36,7 +36,7 @@ define([
return resultWrapper(null, false, false);
}
- value = value.replace(/\-|\s/g, '');
+ value = value.replace(/|\s/g, '');
if (!/^\d*$/.test(value)) {
return resultWrapper(null, false, false);
diff --git a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js
index c6f1bad31fc07..c41be40cba144 100644
--- a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js
+++ b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js
@@ -23,6 +23,12 @@
}(function ($, cvvValidator, creditCardNumberValidator, yearValidator, monthValidator, creditCardData) {
'use strict';
+ $('.payment-method-content input[type="number"]').on('keyup', function () {
+ if ($(this).val() < 0) {
+ $(this).val($(this).val().replace(/^-/, ''));
+ }
+ });
+
$.each({
'validate-card-type': [
function (number, item, allowedTypes) {
diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php
index 4639a2705a289..f0b86588f1cfa 100644
--- a/app/code/Magento/Paypal/Model/Express/Checkout.php
+++ b/app/code/Magento/Paypal/Model/Express/Checkout.php
@@ -14,8 +14,8 @@
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
/**
- * Wrapper that performs Paypal Express and Checkout communication
- * Use current Paypal Express method instance
+ * Wrapper that performs Paypal Express and Checkout communication.
+ *
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -24,6 +24,7 @@ class Checkout
{
/**
* Cache ID prefix for "pal" lookup
+ *
* @var string
*/
const PAL_CACHE_ID = 'paypal_express_checkout_pal';
@@ -364,8 +365,9 @@ public function __construct(
}
/**
- * Checkout with PayPal image URL getter
- * Spares API calls of getting "pal" variable, by putting it into cache per store view
+ * Checkout with PayPal image URL getter.
+ *
+ * Spares API calls of getting "pal" variable, by putting it into cache per store view.
*
* @return string
*/
@@ -597,8 +599,8 @@ public function canSkipOrderReviewStep()
/**
* Update quote when returned from PayPal
- * rewrite billing address by paypal
- * save old billing address for new customer
+ *
+ * Rewrite billing address by paypal, save old billing address for new customer, and
* export shipping address in case address absence
*
* @param string $token
@@ -614,14 +616,15 @@ public function returnFromPaypal($token)
$this->ignoreAddressValidation();
+ // check if we came from the Express Checkout button
+ $isButton = (bool)$quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
+
// import shipping address
$exportedShippingAddress = $this->_getApi()->getExportedShippingAddress();
if (!$quote->getIsVirtual()) {
$shippingAddress = $quote->getShippingAddress();
if ($shippingAddress) {
- if ($exportedShippingAddress
- && $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1
- ) {
+ if ($exportedShippingAddress && $isButton) {
$this->_setExportedAddressData($shippingAddress, $exportedShippingAddress);
// PayPal doesn't provide detailed shipping info: prefix, middlename, lastname, suffix
$shippingAddress->setPrefix(null);
@@ -649,12 +652,11 @@ public function returnFromPaypal($token)
}
// import billing address
- $portBillingFromShipping = $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1
- && $this->_config->getValue(
- 'requireBillingAddress'
- ) != \Magento\Paypal\Model\Config::REQUIRE_BILLING_ADDRESS_ALL
- && !$quote->isVirtual();
- if ($portBillingFromShipping) {
+ $requireBillingAddress = (int)$this->_config->getValue(
+ 'requireBillingAddress'
+ ) === \Magento\Paypal\Model\Config::REQUIRE_BILLING_ADDRESS_ALL;
+
+ if ($isButton && !$requireBillingAddress && !$quote->isVirtual()) {
$billingAddress = clone $shippingAddress;
$billingAddress->unsAddressId()->unsAddressType()->setCustomerAddressId(null);
$data = $billingAddress->getData();
@@ -662,11 +664,17 @@ public function returnFromPaypal($token)
$quote->getBillingAddress()->addData($data);
$quote->getShippingAddress()->setSameAsBilling(1);
} else {
- $billingAddress = $quote->getBillingAddress();
+ $billingAddress = $quote->getBillingAddress()->setCustomerAddressId(null);
}
$exportedBillingAddress = $this->_getApi()->getExportedBillingAddress();
- $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
+ // Since country is required field for billing and shipping address,
+ // we consider the address information to be empty if country is empty.
+ $isEmptyAddress = ($billingAddress->getCountryId() === null);
+
+ if ($requireBillingAddress || $isEmptyAddress) {
+ $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
+ }
$billingAddress->setCustomerNote($exportedBillingAddress->getData('note'));
$quote->setBillingAddress($billingAddress);
$quote->setCheckoutMethod($this->getCheckoutMethod());
@@ -894,7 +902,7 @@ public function getCheckoutMethod()
}
/**
- * Sets address data from exported address
+ * Sets address data from exported address.
*
* @param Address $address
* @param array $exportedAddress
@@ -902,17 +910,6 @@ public function getCheckoutMethod()
*/
protected function _setExportedAddressData($address, $exportedAddress)
{
- // Exported data is more priority if we came from Express Checkout button
- $isButton = (bool)$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
-
- // Since country is required field for billing and shipping address,
- // we consider the address information to be empty if country is empty.
- $isEmptyAddress = ($address->getCountryId() === null);
-
- if (!$isButton && !$isEmptyAddress) {
- return;
- }
-
foreach ($exportedAddress->getExportedKeys() as $key) {
$data = $exportedAddress->getData($key);
if (!empty($data)) {
@@ -949,9 +946,11 @@ protected function _setBillingAgreementRequest()
}
/**
+ * Get api
+ *
* @return \Magento\Paypal\Model\Api\Nvp
*/
- protected function _getApi()
+ protected function _getApi(): \Magento\Paypal\Model\Api\Nvp
{
if (null === $this->_api) {
$this->_api = $this->_apiTypeFactory->create($this->_apiType)->setConfigObject($this->_config);
@@ -960,9 +959,10 @@ protected function _getApi()
}
/**
- * Attempt to collect address shipping rates and return them for further usage in instant update API
- * Returns empty array if it was impossible to obtain any shipping rate
- * If there are shipping rates obtained, the method must return one of them as default.
+ * Attempt to collect address shipping rates and return them for further usage in instant update API.
+ *
+ * Returns empty array if it was impossible to obtain any shipping rate and
+ * if there are shipping rates obtained, the method must return one of them as default.
*
* @param Address $address
* @param bool $mayReturnEmpty
@@ -1043,22 +1043,23 @@ protected function _prepareShippingOptions(Address $address, $mayReturnEmpty = f
}
/**
- * Compare two shipping options based on their amounts
+ * Compare two shipping options based on their amounts.
*
- * This function is used as a callback comparison function in shipping options sorting process
- * @see self::_prepareShippingOptions()
+ * This function is used as a callback comparison function in shipping options sorting process.
*
+ * @see self::_prepareShippingOptions()
* @param \Magento\Framework\DataObject $option1
* @param \Magento\Framework\DataObject $option2
* @return int
*/
- protected static function cmpShippingOptions(DataObject $option1, DataObject $option2)
+ protected static function cmpShippingOptions(DataObject $option1, DataObject $option2): int
{
return $option1->getAmount() <=> $option2->getAmount();
}
/**
- * Try to find whether the code provided by PayPal corresponds to any of possible shipping rates
+ * Try to find whether the code provided by PayPal corresponds to any of possible shipping rates.
+ *
* This method was created only because PayPal has issues with returning the selected code.
* If in future the issue is fixed, we don't need to attempt to match it. It would be enough to set the method code
* before collecting shipping rates
@@ -1067,7 +1068,7 @@ protected static function cmpShippingOptions(DataObject $option1, DataObject $op
* @param string $selectedCode
* @return string
*/
- protected function _matchShippingMethodCode(Address $address, $selectedCode)
+ protected function _matchShippingMethodCode(Address $address, $selectedCode): string
{
$options = $this->_prepareShippingOptions($address, false);
foreach ($options as $option) {
@@ -1083,7 +1084,8 @@ protected function _matchShippingMethodCode(Address $address, $selectedCode)
}
/**
- * Create payment redirect url
+ * Create payment redirect url.
+ *
* @param bool|null $button
* @param string $token
* @return void
@@ -1106,7 +1108,8 @@ public function getCustomerSession()
}
/**
- * Set shipping options to api
+ * Set shipping options to api.
+ *
* @param \Magento\Paypal\Model\Cart $cart
* @param \Magento\Quote\Model\Quote\Address|null $address
* @return void
diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php
index f6fb4ae8e078a..855ab88de5038 100644
--- a/app/code/Magento/Paypal/Model/Payflowpro.php
+++ b/app/code/Magento/Paypal/Model/Payflowpro.php
@@ -419,6 +419,7 @@ public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
$request->setTrxtype(self::TRXTYPE_SALE);
$request->setOrigid($payment->getAdditionalInformation(self::PNREF));
$payment->unsAdditionalInformation(self::PNREF);
+ $request->setData('currency', $payment->getOrder()->getBaseCurrencyCode());
} elseif ($payment->getParentTransactionId()) {
$request = $this->buildBasicRequest();
$request->setOrigid($payment->getParentTransactionId());
diff --git a/app/code/Magento/Paypal/composer.json b/app/code/Magento/Paypal/composer.json
index 281b7084e7f1b..331198b474783 100644
--- a/app/code/Magento/Paypal/composer.json
+++ b/app/code/Magento/Paypal/composer.json
@@ -26,7 +26,7 @@
"magento/module-checkout-agreements": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"proprietary"
],
diff --git a/app/code/Magento/Persistent/Observer/SetCheckoutSessionPersistentDataObserver.php b/app/code/Magento/Persistent/Observer/SetCheckoutSessionPersistentDataObserver.php
new file mode 100644
index 0000000000000..030eca854c801
--- /dev/null
+++ b/app/code/Magento/Persistent/Observer/SetCheckoutSessionPersistentDataObserver.php
@@ -0,0 +1,88 @@
+persistentSession = $persistentSession;
+ $this->customerSession = $customerSession;
+ $this->persistentData = $persistentData;
+ $this->customerRepository = $customerRepository;
+ }
+
+ /**
+ * Pass customer data from persistent session to checkout session and set quote to be loaded even if not active.
+ *
+ * @param \Magento\Framework\Event\Observer $observer
+ * @return void
+ */
+ public function execute(\Magento\Framework\Event\Observer $observer)
+ {
+ /** @var $checkoutSession \Magento\Checkout\Model\Session */
+ $checkoutSession = $observer->getEvent()->getData('checkout_session');
+ if ($this->persistentData->isShoppingCartPersist() && $this->persistentSession->isPersistent()) {
+ $checkoutSession->setCustomerData(
+ $this->customerRepository->getById($this->persistentSession->getSession()->getCustomerId())
+ );
+ }
+ if (!(($this->persistentSession->isPersistent() && !$this->customerSession->isLoggedIn())
+ && !$this->persistentData->isShoppingCartPersist()
+ )) {
+ return;
+ }
+ if ($checkoutSession) {
+ $checkoutSession->setLoadInactive();
+ }
+ }
+}
diff --git a/app/code/Magento/Persistent/Observer/SetLoadPersistentQuoteObserver.php b/app/code/Magento/Persistent/Observer/SetLoadPersistentQuoteObserver.php
deleted file mode 100644
index 6eeab94a91cca..0000000000000
--- a/app/code/Magento/Persistent/Observer/SetLoadPersistentQuoteObserver.php
+++ /dev/null
@@ -1,78 +0,0 @@
-_persistentSession = $persistentSession;
- $this->_customerSession = $customerSession;
- $this->_checkoutSession = $checkoutSession;
- $this->_persistentData = $persistentData;
- }
-
- /**
- * Set quote to be loaded even if not active
- *
- * @param \Magento\Framework\Event\Observer $observer
- * @return void
- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
- */
- public function execute(\Magento\Framework\Event\Observer $observer)
- {
- if (!(($this->_persistentSession->isPersistent() && !$this->_customerSession->isLoggedIn())
- && !$this->_persistentData->isShoppingCartPersist()
- )) {
- return;
- }
-
- if ($this->_checkoutSession) {
- $this->_checkoutSession->setLoadInactive();
- }
- }
-}
diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCheckShoppingCartBehaviorAfterSessionExpiredTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCheckShoppingCartBehaviorAfterSessionExpiredTest.xml
new file mode 100644
index 0000000000000..de09d4a02fc3e
--- /dev/null
+++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontCheckShoppingCartBehaviorAfterSessionExpiredTest.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/SetCheckoutSessionPersistentDataObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/SetCheckoutSessionPersistentDataObserverTest.php
new file mode 100644
index 0000000000000..2f0e90e330a1e
--- /dev/null
+++ b/app/code/Magento/Persistent/Test/Unit/Observer/SetCheckoutSessionPersistentDataObserverTest.php
@@ -0,0 +1,147 @@
+helperMock = $this->createMock(\Magento\Persistent\Helper\Data::class);
+ $this->sessionHelperMock = $this->createMock(\Magento\Persistent\Helper\Session::class);
+ $this->checkoutSessionMock = $this->createMock(\Magento\Checkout\Model\Session::class);
+ $this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class);
+ $this->observerMock = $this->createMock(\Magento\Framework\Event\Observer::class);
+ $this->eventMock = $this->createPartialMock(\Magento\Framework\Event::class, ['getData']);
+ $this->persistentSessionMock = $this->createPartialMock(
+ \Magento\Persistent\Model\Session::class,
+ ['getCustomerId']
+ );
+ $this->customerRepositoryMock = $this->createMock(
+ \Magento\Customer\Api\CustomerRepositoryInterface::class
+ );
+ $this->model = new \Magento\Persistent\Observer\SetCheckoutSessionPersistentDataObserver(
+ $this->sessionHelperMock,
+ $this->customerSessionMock,
+ $this->helperMock,
+ $this->customerRepositoryMock
+ );
+ }
+
+ /**
+ * Test execute method when session is not persistent.
+ *
+ * @return void
+ */
+ public function testExecuteWhenSessionIsNotPersistent()
+ {
+ $this->observerMock->expects($this->once())
+ ->method('getEvent')
+ ->willReturn($this->eventMock);
+ $this->eventMock->expects($this->once())
+ ->method('getData')
+ ->willReturn($this->checkoutSessionMock);
+ $this->sessionHelperMock->expects($this->once())
+ ->method('isPersistent')
+ ->willReturn(false);
+ $this->checkoutSessionMock->expects($this->never())
+ ->method('setLoadInactive');
+ $this->checkoutSessionMock->expects($this->never())
+ ->method('setCustomerData');
+ $this->model->execute($this->observerMock);
+ }
+
+ /**
+ * Test execute method when session is persistent.
+ *
+ * @return void
+ */
+ public function testExecute()
+ {
+ $this->observerMock->expects($this->once())
+ ->method('getEvent')
+ ->willReturn($this->eventMock);
+ $this->eventMock->expects($this->once())
+ ->method('getData')
+ ->willReturn($this->checkoutSessionMock);
+ $this->sessionHelperMock->expects($this->exactly(2))
+ ->method('isPersistent')
+ ->willReturn(true);
+ $this->customerSessionMock->expects($this->once())
+ ->method('isLoggedIn')
+ ->willReturn(false);
+ $this->helperMock->expects($this->exactly(2))
+ ->method('isShoppingCartPersist')
+ ->willReturn(true);
+ $this->persistentSessionMock->expects($this->once())
+ ->method('getCustomerId')
+ ->willReturn(123);
+ $this->sessionHelperMock->expects($this->once())
+ ->method('getSession')
+ ->willReturn($this->persistentSessionMock);
+ $this->customerRepositoryMock->expects($this->once())
+ ->method('getById')
+ ->willReturn(1);
+ $this->checkoutSessionMock->expects($this->never())
+ ->method('setLoadInactive');
+ $this->checkoutSessionMock->expects($this->once())
+ ->method('setCustomerData');
+ $this->model->execute($this->observerMock);
+ }
+}
diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/SetLoadPersistentQuoteObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/SetLoadPersistentQuoteObserverTest.php
deleted file mode 100644
index fd78a6852ea59..0000000000000
--- a/app/code/Magento/Persistent/Test/Unit/Observer/SetLoadPersistentQuoteObserverTest.php
+++ /dev/null
@@ -1,73 +0,0 @@
-helperMock = $this->createMock(\Magento\Persistent\Helper\Data::class);
- $this->sessionHelperMock = $this->createMock(\Magento\Persistent\Helper\Session::class);
- $this->checkoutSessionMock = $this->createMock(\Magento\Checkout\Model\Session::class);
- $this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class);
- $this->observerMock = $this->createMock(\Magento\Framework\Event\Observer::class);
-
- $this->model = new \Magento\Persistent\Observer\SetLoadPersistentQuoteObserver(
- $this->sessionHelperMock,
- $this->helperMock,
- $this->customerSessionMock,
- $this->checkoutSessionMock
- );
- }
-
- public function testExecuteWhenSessionIsNotPersistent()
- {
- $this->sessionHelperMock->expects($this->once())->method('isPersistent')->will($this->returnValue(false));
- $this->checkoutSessionMock->expects($this->never())->method('setLoadInactive');
- $this->model->execute($this->observerMock);
- }
-
- public function testExecute()
- {
- $this->sessionHelperMock->expects($this->once())->method('isPersistent')->will($this->returnValue(true));
- $this->customerSessionMock->expects($this->once())->method('isLoggedIn')->will($this->returnValue(false));
- $this->helperMock->expects($this->once())->method('isShoppingCartPersist')->will($this->returnValue(true));
- $this->checkoutSessionMock->expects($this->never())->method('setLoadInactive');
- $this->model->execute($this->observerMock);
- }
-}
diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json
index 9debadd193a9d..73184a0648d24 100644
--- a/app/code/Magento/Persistent/composer.json
+++ b/app/code/Magento/Persistent/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Persistent/etc/frontend/events.xml b/app/code/Magento/Persistent/etc/frontend/events.xml
index 193b9a10818e4..79720695ea6f6 100644
--- a/app/code/Magento/Persistent/etc/frontend/events.xml
+++ b/app/code/Magento/Persistent/etc/frontend/events.xml
@@ -49,7 +49,7 @@
-
+
diff --git a/app/code/Magento/Persistent/etc/webapi_rest/events.xml b/app/code/Magento/Persistent/etc/webapi_rest/events.xml
index 1eff845386bf4..79dffa1834563 100644
--- a/app/code/Magento/Persistent/etc/webapi_rest/events.xml
+++ b/app/code/Magento/Persistent/etc/webapi_rest/events.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/app/code/Magento/Persistent/etc/webapi_soap/events.xml b/app/code/Magento/Persistent/etc/webapi_soap/events.xml
index 1eff845386bf4..79dffa1834563 100644
--- a/app/code/Magento/Persistent/etc/webapi_soap/events.xml
+++ b/app/code/Magento/Persistent/etc/webapi_soap/events.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json
index 11dc94edcbcd3..d2b7a8014d9a6 100644
--- a/app/code/Magento/ProductAlert/composer.json
+++ b/app/code/Magento/ProductAlert/composer.json
@@ -13,7 +13,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ProductVideo/composer.json b/app/code/Magento/ProductVideo/composer.json
index 811422d160d8d..7c5017eef4a5a 100644
--- a/app/code/Magento/ProductVideo/composer.json
+++ b/app/code/Magento/ProductVideo/composer.json
@@ -16,7 +16,7 @@
"magento/module-config": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.4",
+ "version": "100.2.5",
"license": [
"proprietary"
],
diff --git a/app/code/Magento/ProductVideo/i18n/de_DE.csv b/app/code/Magento/ProductVideo/i18n/de_DE.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/de_DE.csv
+++ b/app/code/Magento/ProductVideo/i18n/de_DE.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/en_US.csv b/app/code/Magento/ProductVideo/i18n/en_US.csv
index 2d226c6daefa3..debcab151cc91 100644
--- a/app/code/Magento/ProductVideo/i18n/en_US.csv
+++ b/app/code/Magento/ProductVideo/i18n/en_US.csv
@@ -40,3 +40,4 @@ Delete,Delete
"Autostart base video","Autostart base video"
"Show related video","Show related video"
"Auto restart video","Auto restart video"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/es_ES.csv b/app/code/Magento/ProductVideo/i18n/es_ES.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/es_ES.csv
+++ b/app/code/Magento/ProductVideo/i18n/es_ES.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/fr_FR.csv b/app/code/Magento/ProductVideo/i18n/fr_FR.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/fr_FR.csv
+++ b/app/code/Magento/ProductVideo/i18n/fr_FR.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/nl_NL.csv b/app/code/Magento/ProductVideo/i18n/nl_NL.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/nl_NL.csv
+++ b/app/code/Magento/ProductVideo/i18n/nl_NL.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/pt_BR.csv b/app/code/Magento/ProductVideo/i18n/pt_BR.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/pt_BR.csv
+++ b/app/code/Magento/ProductVideo/i18n/pt_BR.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv b/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv
index 7047317396999..ca24668bb8d16 100644
--- a/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv
+++ b/app/code/Magento/ProductVideo/i18n/zh_Hans_CN.csv
@@ -7,3 +7,4 @@
"Preview Image","Preview Image"
"Get Video Information","Get Video Information"
"Youtube or Vimeo supported","Youtube or Vimeo supported"
+"Delete image in all store views","Delete image in all store views"
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/layout/catalog_product_new.xml b/app/code/Magento/ProductVideo/view/adminhtml/layout/catalog_product_new.xml
index f5a22c50e6d0d..63bd5321ad30b 100644
--- a/app/code/Magento/ProductVideo/view/adminhtml/layout/catalog_product_new.xml
+++ b/app/code/Magento/ProductVideo/view/adminhtml/layout/catalog_product_new.xml
@@ -6,6 +6,9 @@
*/
-->
+
+
+
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml b/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml
index f0ae057bc724d..2ceb9e9c9d4f2 100755
--- a/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml
+++ b/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml
@@ -34,7 +34,7 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to
class="gallery"
data-mage-init='{"openVideoModal":{}}'
data-parent-component="= $block->escapeHtml($block->getData('config/parentComponent')) ?>"
- data-images="= $block->escapeHtml($block->getImagesJson()) ?>"
+ data-images="= $block->escapeHtmlAttr($block->getImagesJson()) ?>"
data-types="= $block->escapeHtml(
$this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes())
) ?>"
@@ -140,30 +140,37 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to
alt="<%- data.label %>"/>
-
+
= $block->escapeHtml(
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/css/gallery-delete-tooltip.css b/app/code/Magento/ProductVideo/view/adminhtml/web/css/gallery-delete-tooltip.css
new file mode 100644
index 0000000000000..835a22683b157
--- /dev/null
+++ b/app/code/Magento/ProductVideo/view/adminhtml/web/css/gallery-delete-tooltip.css
@@ -0,0 +1,20 @@
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+.gallery .tooltip .delete-tooltiptext {
+ visibility: hidden;
+ width: 112px;
+ background-color: #373330;
+ color: #F7F3EB;
+ text-align: center;
+ padding: 5px 0;
+ position: absolute;
+ z-index: 1;
+ left: 30px;
+ top: 91px;
+}
+
+.gallery .tooltip:hover .delete-tooltiptext {
+ visibility: visible;
+}
diff --git a/app/code/Magento/Quote/Model/BillingAddressManagement.php b/app/code/Magento/Quote/Model/BillingAddressManagement.php
index 2cbca917c26a1..c89fc37b44689 100644
--- a/app/code/Magento/Quote/Model/BillingAddressManagement.php
+++ b/app/code/Magento/Quote/Model/BillingAddressManagement.php
@@ -76,6 +76,7 @@ public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $addres
{
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->quoteRepository->getActive($cartId);
+ $address->setCustomerId($quote->getCustomerId());
$quote->removeAddress($quote->getBillingAddress()->getId());
$quote->setBillingAddress($address);
try {
diff --git a/app/code/Magento/Quote/Model/Product/Plugin/MarkQuotesRecollectMassDisabled.php b/app/code/Magento/Quote/Model/Product/Plugin/MarkQuotesRecollectMassDisabled.php
new file mode 100644
index 0000000000000..f18bb46fa63fb
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Product/Plugin/MarkQuotesRecollectMassDisabled.php
@@ -0,0 +1,55 @@
+quoteResource = $quoteResource;
+ }
+
+ /**
+ * Clean quote items after mass disabling product
+ *
+ * @param \Magento\Catalog\Model\Product\Action $subject
+ * @param \Magento\Catalog\Model\Product\Action $result
+ * @param int[] $productIds
+ * @param int[] $attrData
+ * @param int $storeId
+ * @return \Magento\Catalog\Model\Product\Action
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterUpdateAttributes(
+ ProductAction $subject,
+ ProductAction $result,
+ $productIds,
+ $attrData,
+ $storeId
+ ): ProductAction {
+ if (isset($attrData['status']) && $attrData['status'] === Status::STATUS_DISABLED) {
+ $this->quoteResource->markQuotesRecollect($productIds);
+ }
+
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php
index a738f844c8d8d..f0419c7f96095 100644
--- a/app/code/Magento/Quote/Model/Quote/Address.php
+++ b/app/code/Magento/Quote/Model/Quote/Address.php
@@ -965,6 +965,7 @@ public function collectShippingRates()
/**
* Request shipping rates for entire address or specified address item
+ *
* Returns true if current selected shipping method code corresponds to one of the found rates
*
* @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
@@ -1003,8 +1004,14 @@ public function requestShippingRates(\Magento\Quote\Model\Quote\Item\AbstractIte
* Store and website identifiers specified from StoreManager
*/
$request->setQuoteStoreId($this->getQuote()->getStoreId());
- $request->setStoreId($this->storeManager->getStore()->getId());
- $request->setWebsiteId($this->storeManager->getWebsite()->getId());
+ 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());
/**
* Currencies need to convert in free shipping
@@ -1349,7 +1356,7 @@ public function getAllBaseTotalAmounts()
/******************************* End Total Collector Interface *******************************************/
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
protected function _getValidationRulesBeforeSave()
{
@@ -1357,7 +1364,7 @@ protected function _getValidationRulesBeforeSave()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getCountryId()
{
@@ -1365,7 +1372,7 @@ public function getCountryId()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCountryId($countryId)
{
@@ -1373,7 +1380,7 @@ public function setCountryId($countryId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getStreet()
{
@@ -1382,7 +1389,7 @@ public function getStreet()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStreet($street)
{
@@ -1390,7 +1397,7 @@ public function setStreet($street)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getCompany()
{
@@ -1398,7 +1405,7 @@ public function getCompany()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCompany($company)
{
@@ -1406,7 +1413,7 @@ public function setCompany($company)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getTelephone()
{
@@ -1414,7 +1421,7 @@ public function getTelephone()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTelephone($telephone)
{
@@ -1422,7 +1429,7 @@ public function setTelephone($telephone)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getFax()
{
@@ -1430,7 +1437,7 @@ public function getFax()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setFax($fax)
{
@@ -1438,7 +1445,7 @@ public function setFax($fax)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getPostcode()
{
@@ -1446,7 +1453,7 @@ public function getPostcode()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setPostcode($postcode)
{
@@ -1454,7 +1461,7 @@ public function setPostcode($postcode)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getCity()
{
@@ -1462,7 +1469,7 @@ public function getCity()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCity($city)
{
@@ -1470,7 +1477,7 @@ public function setCity($city)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getFirstname()
{
@@ -1478,7 +1485,7 @@ public function getFirstname()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setFirstname($firstname)
{
@@ -1486,7 +1493,7 @@ public function setFirstname($firstname)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getLastname()
{
@@ -1494,7 +1501,7 @@ public function getLastname()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setLastname($lastname)
{
@@ -1502,7 +1509,7 @@ public function setLastname($lastname)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getMiddlename()
{
@@ -1510,7 +1517,7 @@ public function getMiddlename()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setMiddlename($middlename)
{
@@ -1518,7 +1525,7 @@ public function setMiddlename($middlename)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getPrefix()
{
@@ -1526,7 +1533,7 @@ public function getPrefix()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setPrefix($prefix)
{
@@ -1534,7 +1541,7 @@ public function setPrefix($prefix)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getSuffix()
{
@@ -1542,7 +1549,7 @@ public function getSuffix()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSuffix($suffix)
{
@@ -1550,7 +1557,7 @@ public function setSuffix($suffix)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getVatId()
{
@@ -1558,7 +1565,7 @@ public function getVatId()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setVatId($vatId)
{
@@ -1566,7 +1573,7 @@ public function setVatId($vatId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getCustomerId()
{
@@ -1574,7 +1581,7 @@ public function getCustomerId()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerId($customerId)
{
@@ -1582,7 +1589,7 @@ public function setCustomerId($customerId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getEmail()
{
@@ -1595,7 +1602,7 @@ public function getEmail()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setEmail($email)
{
@@ -1603,7 +1610,7 @@ public function setEmail($email)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRegion($region)
{
@@ -1611,7 +1618,7 @@ public function setRegion($region)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRegionId($regionId)
{
@@ -1619,7 +1626,7 @@ public function setRegionId($regionId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRegionCode($regionCode)
{
@@ -1627,7 +1634,7 @@ public function setRegionCode($regionCode)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getSameAsBilling()
{
@@ -1635,7 +1642,7 @@ public function getSameAsBilling()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSameAsBilling($sameAsBilling)
{
@@ -1643,7 +1650,7 @@ public function setSameAsBilling($sameAsBilling)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getCustomerAddressId()
{
@@ -1651,7 +1658,7 @@ public function getCustomerAddressId()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerAddressId($customerAddressId)
{
@@ -1682,9 +1689,7 @@ public function setSaveInAddressBook($saveInAddressBook)
//@codeCoverageIgnoreEnd
/**
- * {@inheritdoc}
- *
- * @return \Magento\Quote\Api\Data\AddressExtensionInterface|null
+ * @inheritdoc
*/
public function getExtensionAttributes()
{
@@ -1692,10 +1697,7 @@ public function getExtensionAttributes()
}
/**
- * {@inheritdoc}
- *
- * @param \Magento\Quote\Api\Data\AddressExtensionInterface $extensionAttributes
- * @return $this
+ * @inheritdoc
*/
public function setExtensionAttributes(\Magento\Quote\Api\Data\AddressExtensionInterface $extensionAttributes)
{
@@ -1713,7 +1715,7 @@ public function getShippingMethod()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
protected function getCustomAttributesCodes()
{
diff --git a/app/code/Magento/Quote/Model/Quote/Item/Processor.php b/app/code/Magento/Quote/Model/Quote/Item/Processor.php
index f9dac1779ad27..757b81b984a46 100644
--- a/app/code/Magento/Quote/Model/Quote/Item/Processor.php
+++ b/app/code/Magento/Quote/Model/Quote/Item/Processor.php
@@ -97,6 +97,7 @@ public function prepare(Item $item, DataObject $request, Product $candidate)
$item->addQty($candidate->getCartQty());
$customPrice = $request->getCustomPrice();
+ $item->setPrice($candidate->getFinalPrice());
if (!empty($customPrice)) {
$item->setCustomPrice($customPrice);
$item->setOriginalCustomPrice($customPrice);
diff --git a/app/code/Magento/Quote/Model/Quote/TotalsCollector.php b/app/code/Magento/Quote/Model/Quote/TotalsCollector.php
index 8fa03232a0e8d..8f18a04a102fa 100644
--- a/app/code/Magento/Quote/Model/Quote/TotalsCollector.php
+++ b/app/code/Magento/Quote/Model/Quote/TotalsCollector.php
@@ -203,11 +203,12 @@ protected function _validateCouponCode(\Magento\Quote\Model\Quote $quote)
*/
protected function _collectItemsQtys(\Magento\Quote\Model\Quote $quote)
{
+ $quoteItems = $quote->getAllVisibleItems();
$quote->setItemsCount(0);
$quote->setItemsQty(0);
$quote->setVirtualItemsQty(0);
- foreach ($quote->getAllVisibleItems() as $item) {
+ foreach ($quoteItems as $item) {
if ($item->getParentItem()) {
continue;
}
diff --git a/app/code/Magento/Quote/Model/ResourceModel/Quote/Item/Collection.php b/app/code/Magento/Quote/Model/ResourceModel/Quote/Item/Collection.php
index ef1705e0ad100..309c89e3702f5 100644
--- a/app/code/Magento/Quote/Model/ResourceModel/Quote/Item/Collection.php
+++ b/app/code/Magento/Quote/Model/ResourceModel/Quote/Item/Collection.php
@@ -3,9 +3,16 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Quote\Model\ResourceModel\Quote\Item;
-use \Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
+use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
+use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\Quote\Item as QuoteItem;
+use Magento\Quote\Model\ResourceModel\Quote\Item as ResourceQuoteItem;
/**
* Quote item resource collection
@@ -50,6 +57,11 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\VersionContro
*/
private $storeManager;
+ /**
+ * @var bool $recollectQuote
+ */
+ private $recollectQuote = false;
+
/**
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
* @param \Psr\Log\LoggerInterface $logger
@@ -102,7 +114,7 @@ public function __construct(
*/
protected function _construct()
{
- $this->_init(\Magento\Quote\Model\Quote\Item::class, \Magento\Quote\Model\ResourceModel\Quote\Item::class);
+ $this->_init(QuoteItem::class, ResourceQuoteItem::class);
}
/**
@@ -110,7 +122,7 @@ protected function _construct()
*
* @return int
*/
- public function getStoreId()
+ public function getStoreId(): int
{
// Fallback to current storeId if no quote is provided
// (see https://github.com/magento/magento2/commit/9d3be732a88884a66d667b443b3dc1655ddd0721)
@@ -119,12 +131,12 @@ public function getStoreId()
}
/**
- * Set Quote object to Collection
+ * Set Quote object to Collection.
*
- * @param \Magento\Quote\Model\Quote $quote
+ * @param Quote $quote
* @return $this
*/
- public function setQuote($quote)
+ public function setQuote($quote): self
{
$this->_quote = $quote;
$quoteId = $quote->getId();
@@ -138,14 +150,15 @@ public function setQuote($quote)
}
/**
- * Reset the collection and inner join it to quotes table
+ * Reset the collection and inner join it to quotes table.
+ *
* Optionally can select items with specified product id only
*
* @param string $quotesTableName
* @param int $productId
* @return $this
*/
- public function resetJoinQuotes($quotesTableName, $productId = null)
+ public function resetJoinQuotes($quotesTableName, $productId = null): self
{
$this->getSelect()->reset()->from(
['qi' => $this->getResource()->getMainTable()],
@@ -162,11 +175,11 @@ public function resetJoinQuotes($quotesTableName, $productId = null)
}
/**
- * After load processing
+ * After load processing.
*
* @return $this
*/
- protected function _afterLoad()
+ protected function _afterLoad(): self
{
parent::_afterLoad();
@@ -195,11 +208,11 @@ protected function _afterLoad()
}
/**
- * Add options to items
+ * Add options to items.
*
* @return $this
*/
- protected function _assignOptions()
+ protected function _assignOptions(): self
{
$itemIds = array_keys($this->_items);
$optionCollection = $this->_itemOptionCollectionFactory->create()->addItemFilter($itemIds);
@@ -213,12 +226,12 @@ protected function _assignOptions()
}
/**
- * Add products to items and item options
+ * Add products to items and item options.
*
* @return $this
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
- protected function _assignProducts()
+ protected function _assignProducts(): self
{
\Magento\Framework\Profiler::start('QUOTE:' . __METHOD__, ['group' => 'QUOTE', 'method' => __METHOD__]);
$productCollection = $this->_productCollectionFactory->create()->setStoreId(
@@ -240,46 +253,30 @@ protected function _assignProducts()
['collection' => $productCollection]
);
- $recollectQuote = false;
foreach ($this as $item) {
+ /** @var ProductInterface $product */
$product = $productCollection->getItemById($item->getProductId());
- if ($product) {
+ $isValidProduct = $this->isValidProduct($product);
+ $qtyOptions = [];
+ if ($isValidProduct) {
$product->setCustomOptions([]);
- $qtyOptions = [];
- $optionProductIds = [];
- foreach ($item->getOptions() as $option) {
- /**
- * Call type-specific logic for product associated with quote item
- */
- $product->getTypeInstance()->assignProductToOption(
- $productCollection->getItemById($option->getProductId()),
- $option,
- $product
- );
-
- if (is_object($option->getProduct()) && $option->getProduct()->getId() != $product->getId()) {
- $optionProductIds[$option->getProduct()->getId()] = $option->getProduct()->getId();
- }
- }
-
- if ($optionProductIds) {
- foreach ($optionProductIds as $optionProductId) {
- $qtyOption = $item->getOptionByCode('product_qty_' . $optionProductId);
- if ($qtyOption) {
- $qtyOptions[$optionProductId] = $qtyOption;
- }
+ $optionProductIds = $this->getOptionProductIds($item, $product, $productCollection);
+ foreach ($optionProductIds as $optionProductId) {
+ $qtyOption = $item->getOptionByCode('product_qty_' . $optionProductId);
+ if ($qtyOption) {
+ $qtyOptions[$optionProductId] = $qtyOption;
}
}
-
- $item->setQtyOptions($qtyOptions)->setProduct($product);
} else {
$item->isDeleted(true);
- $recollectQuote = true;
+ $this->recollectQuote = true;
+ }
+ if (!$item->isDeleted()) {
+ $item->setQtyOptions($qtyOptions)->setProduct($product);
+ $item->checkData();
}
- $item->checkData();
}
-
- if ($recollectQuote && $this->_quote) {
+ if ($this->recollectQuote && $this->_quote) {
$this->_quote->collectTotals();
}
\Magento\Framework\Profiler::stop('QUOTE:' . __METHOD__);
@@ -287,6 +284,57 @@ protected function _assignProducts()
return $this;
}
+ /**
+ * Get product Ids from option.
+ *
+ * @param QuoteItem $item
+ * @param ProductInterface $product
+ * @param ProductCollection $productCollection
+ * @return array
+ */
+ private function getOptionProductIds(
+ QuoteItem $item,
+ ProductInterface $product,
+ ProductCollection $productCollection
+ ): array {
+ $optionProductIds = [];
+ foreach ($item->getOptions() as $option) {
+ /**
+ * Call type-specific logic for product associated with quote item
+ */
+ $product->getTypeInstance()->assignProductToOption(
+ $productCollection->getItemById($option->getProductId()),
+ $option,
+ $product
+ );
+
+ if (is_object($option->getProduct()) && $option->getProduct()->getId() != $product->getId()) {
+ $isValidProduct = $this->isValidProduct($option->getProduct());
+ if (!$isValidProduct && !$item->isDeleted()) {
+ $item->isDeleted(true);
+ $this->recollectQuote = true;
+ continue;
+ }
+ $optionProductIds[$option->getProduct()->getId()] = $option->getProduct()->getId();
+ }
+ }
+
+ return $optionProductIds;
+ }
+
+ /**
+ * Check is valid product.
+ *
+ * @param ProductInterface $product
+ * @return bool
+ */
+ private function isValidProduct(ProductInterface $product): bool
+ {
+ $result = ($product && (int)$product->getStatus() !== ProductStatus::STATUS_DISABLED);
+
+ return $result;
+ }
+
/**
* Prevents adding stock status filter to the collection of products.
*
diff --git a/app/code/Magento/Quote/Model/ValidationRules/AllowedCountryValidationRule.php b/app/code/Magento/Quote/Model/ValidationRules/AllowedCountryValidationRule.php
index 840e94e3ece1f..2498e9976f009 100644
--- a/app/code/Magento/Quote/Model/ValidationRules/AllowedCountryValidationRule.php
+++ b/app/code/Magento/Quote/Model/ValidationRules/AllowedCountryValidationRule.php
@@ -10,6 +10,7 @@
use Magento\Directory\Model\AllowedCountries;
use Magento\Framework\Validation\ValidationResultFactory;
use Magento\Quote\Model\Quote;
+use Magento\Store\Model\ScopeInterface;
/**
* @inheritdoc
@@ -54,10 +55,15 @@ public function validate(Quote $quote): array
$validationErrors = [];
if (!$quote->isVirtual()) {
+ $shippingAddress = $quote->getShippingAddress();
+ $shippingAddress->setStoreId($quote->getStoreId());
$validationResult =
in_array(
- $quote->getShippingAddress()->getCountryId(),
- $this->allowedCountryReader->getAllowedCountries()
+ $shippingAddress->getCountryId(),
+ $this->allowedCountryReader->getAllowedCountries(
+ ScopeInterface::SCOPE_STORE,
+ $quote->getStoreId()
+ )
);
if (!$validationResult) {
$validationErrors = [__($this->generalMessage)];
diff --git a/app/code/Magento/Quote/Model/ValidationRules/BillingAddressValidationRule.php b/app/code/Magento/Quote/Model/ValidationRules/BillingAddressValidationRule.php
index fbacbf1c8d30c..2c02c9f9eacc4 100644
--- a/app/code/Magento/Quote/Model/ValidationRules/BillingAddressValidationRule.php
+++ b/app/code/Magento/Quote/Model/ValidationRules/BillingAddressValidationRule.php
@@ -43,7 +43,11 @@ public function __construct(
public function validate(Quote $quote): array
{
$validationErrors = [];
- $validationResult = $quote->getBillingAddress()->validate();
+
+ $billingAddress = $quote->getBillingAddress();
+ $billingAddress->setStoreId($quote->getStoreId());
+ $validationResult = $billingAddress->validate();
+
if ($validationResult !== true) {
$validationErrors = [__($this->generalMessage)];
}
diff --git a/app/code/Magento/Quote/Model/ValidationRules/ShippingAddressValidationRule.php b/app/code/Magento/Quote/Model/ValidationRules/ShippingAddressValidationRule.php
index f5eebe241acc9..1ced36b9bccf3 100644
--- a/app/code/Magento/Quote/Model/ValidationRules/ShippingAddressValidationRule.php
+++ b/app/code/Magento/Quote/Model/ValidationRules/ShippingAddressValidationRule.php
@@ -45,7 +45,10 @@ public function validate(Quote $quote): array
$validationErrors = [];
if (!$quote->isVirtual()) {
- $validationResult = $quote->getShippingAddress()->validate();
+ $shippingAddress = $quote->getShippingAddress();
+ $shippingAddress->setStoreId($quote->getStoreId());
+ $validationResult = $shippingAddress->validate();
+
if ($validationResult !== true) {
$validationErrors = [__($this->generalMessage)];
}
diff --git a/app/code/Magento/Quote/Model/ValidationRules/ShippingMethodValidationRule.php b/app/code/Magento/Quote/Model/ValidationRules/ShippingMethodValidationRule.php
index 6df7f663b0630..3ef079f5a019a 100644
--- a/app/code/Magento/Quote/Model/ValidationRules/ShippingMethodValidationRule.php
+++ b/app/code/Magento/Quote/Model/ValidationRules/ShippingMethodValidationRule.php
@@ -45,8 +45,10 @@ public function validate(Quote $quote): array
$validationErrors = [];
if (!$quote->isVirtual()) {
- $shippingMethod = $quote->getShippingAddress()->getShippingMethod();
- $shippingRate = $quote->getShippingAddress()->getShippingRateByCode($shippingMethod);
+ $shippingAddress = $quote->getShippingAddress();
+ $shippingAddress->setStoreId($quote->getStoreId());
+ $shippingMethod = $shippingAddress->getShippingMethod();
+ $shippingRate = $shippingAddress->getShippingRateByCode($shippingMethod);
$validationResult = $shippingMethod && $shippingRate;
if (!$validationResult) {
$validationErrors = [__($this->generalMessage)];
diff --git a/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml
new file mode 100644
index 0000000000000..a2f08353a4f3b
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SimpleTwoOption
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php b/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php
index 9cde4bbc19184..d67ebdd5a0fc2 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php
@@ -36,7 +36,7 @@ protected function setUp()
/**
* @expectedException \Magento\Framework\Exception\StateException
- * @expectedMessage Cannot assign customer to the given cart. You don't have permission for this operation.
+ * @expectedExceptionMessage Cannot assign customer to the given cart. You don't have permission for this operation.
*/
public function testBeforeAssignCustomer()
{
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
index a56de35b70f75..e8cfb05ca89b9 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
@@ -76,7 +76,8 @@ protected function setUp()
'addQty',
'setCustomPrice',
'setOriginalCustomPrice',
- 'setData'
+ 'setData',
+ 'setprice'
]);
$this->quoteItemFactoryMock->expects($this->any())
->method('create')
@@ -98,7 +99,13 @@ protected function setUp()
$this->productMock = $this->createPartialMock(
\Magento\Catalog\Model\Product::class,
- ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty', 'getStickWithinParent']
+ [
+ 'getCustomOptions',
+ '__wakeup',
+ 'getParentProductId',
+ 'getCartQty',
+ 'getStickWithinParent',
+ 'getFinalPrice']
);
$this->objectMock = $this->createPartialMock(
\Magento\Framework\DataObject::class,
@@ -239,6 +246,7 @@ public function testPrepare()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -246,6 +254,9 @@ public function testPrepare()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -255,6 +266,9 @@ public function testPrepare()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -282,6 +296,7 @@ public function testPrepareWithResetCountAndStick()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -289,6 +304,9 @@ public function testPrepareWithResetCountAndStick()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(true));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -298,6 +316,9 @@ public function testPrepareWithResetCountAndStick()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -325,6 +346,7 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 2;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -332,6 +354,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -341,6 +366,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -368,6 +396,7 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->objectMock->expects($this->any())
->method('getResetCount')
@@ -386,10 +415,16 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
->with($qty);
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/UpdaterTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/UpdaterTest.php
index af47f6276705b..7933da7c5fe37 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/UpdaterTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/UpdaterTest.php
@@ -92,7 +92,7 @@ protected function setUp()
/**
* @expectedException \InvalidArgumentException
- * @ExceptedExceptionMessage The qty value is required to update quote item.
+ * @expectedExceptionMessage The qty value is required to update quote item.
*/
public function testUpdateNoQty()
{
diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
index 1870fa9dc81ba..59445c3999899 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php
@@ -100,7 +100,7 @@ protected function setUp()
/**
* @expectedException \Magento\Framework\Exception\NoSuchEntityException
- * @expected ExceptionMessage error345
+ * @expectedExceptionMessage error345
*/
public function testSetAddressValidationFailed()
{
diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json
index 0d67eaaf6ec74..5391d7779b420 100644
--- a/app/code/Magento/Quote/composer.json
+++ b/app/code/Magento/Quote/composer.json
@@ -23,7 +23,7 @@
"magento/module-webapi": "100.2.*"
},
"type": "magento2-module",
- "version": "101.0.5",
+ "version": "101.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml
index ecc6426855679..8add3786eb9a3 100644
--- a/app/code/Magento/Quote/etc/di.xml
+++ b/app/code/Magento/Quote/etc/di.xml
@@ -96,6 +96,9 @@
+
+
+
diff --git a/app/code/Magento/QuoteAnalytics/composer.json b/app/code/Magento/QuoteAnalytics/composer.json
index 65978de6d0785..bc43c38421650 100644
--- a/app/code/Magento/QuoteAnalytics/composer.json
+++ b/app/code/Magento/QuoteAnalytics/composer.json
@@ -7,7 +7,7 @@
"magento/module-quote": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ReleaseNotification/composer.json b/app/code/Magento/ReleaseNotification/composer.json
index 45452997757cd..d16734d45f048 100644
--- a/app/code/Magento/ReleaseNotification/composer.json
+++ b/app/code/Magento/ReleaseNotification/composer.json
@@ -8,7 +8,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php
index 671acc9701012..7b3e165687bac 100644
--- a/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php
+++ b/app/code/Magento/Reports/Model/ResourceModel/Quote/Collection.php
@@ -5,7 +5,11 @@
*/
namespace Magento\Reports\Model\ResourceModel\Quote;
+use Magento\Store\Model\Store;
+
/**
+ * Collection of abandoned quotes with reports join.
+ *
* @api
* @since 100.0.2
*/
@@ -48,6 +52,24 @@ public function __construct(
$this->customerResource = $customerResource;
}
+ /**
+ * Filter collections by stores.
+ *
+ * @param array $storeIds
+ * @param bool $withAdmin
+ * @return $this
+ */
+ public function addStoreFilter(array $storeIds, bool $withAdmin = true)
+ {
+ if ($withAdmin) {
+ $storeIds[] = Store::DEFAULT_STORE_ID;
+ }
+
+ $this->addFieldToFilter('store_id', ['in' => $storeIds]);
+
+ return $this;
+ }
+
/**
* Prepare for abandoned report
*
diff --git a/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminReviewOrderActionGroup.xml b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminReviewOrderActionGroup.xml
new file mode 100644
index 0000000000000..90ea72ce9dda9
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminReviewOrderActionGroup.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Reports/Test/Mftf/Page/AdminOrderedProductsPage.xml b/app/code/Magento/Reports/Test/Mftf/Page/AdminOrderedProductsPage.xml
new file mode 100644
index 0000000000000..fc9784498cbb3
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Mftf/Page/AdminOrderedProductsPage.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Reports/Test/Mftf/Section/AdminMenuSection.xml b/app/code/Magento/Reports/Test/Mftf/Section/AdminMenuSection.xml
new file mode 100644
index 0000000000000..b8f0f0750bbf4
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Mftf/Section/AdminMenuSection.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Reports/Test/Mftf/Section/AdminOrderedProductsSection.xml b/app/code/Magento/Reports/Test/Mftf/Section/AdminOrderedProductsSection.xml
new file mode 100644
index 0000000000000..dd4e78f4ee3f9
--- /dev/null
+++ b/app/code/Magento/Reports/Test/Mftf/Section/AdminOrderedProductsSection.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json
index 6b5a43f040109..1abd03339a22a 100644
--- a/app/code/Magento/Reports/composer.json
+++ b/app/code/Magento/Reports/composer.json
@@ -22,7 +22,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.6",
+ "version": "100.2.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/RequireJs/composer.json b/app/code/Magento/RequireJs/composer.json
index 4c6afcd77b4fa..5c947c8d8e85d 100644
--- a/app/code/Magento/RequireJs/composer.json
+++ b/app/code/Magento/RequireJs/composer.json
@@ -6,7 +6,7 @@
"magento/framework": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php
index 99c963501a9d4..4e55484e5dd94 100644
--- a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php
+++ b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Review\Model\ResourceModel\Review\Product;
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
@@ -403,12 +404,20 @@ public function getAllIds($limit = null, $offset = null)
public function getResultingIds()
{
$idsSelect = clone $this->getSelect();
- $idsSelect->reset(Select::LIMIT_COUNT);
- $idsSelect->reset(Select::LIMIT_OFFSET);
- $idsSelect->reset(Select::COLUMNS);
- $idsSelect->reset(Select::ORDER);
- $idsSelect->columns('rt.review_id');
- return $this->getConnection()->fetchCol($idsSelect);
+ $data = $this->getConnection()
+ ->fetchAll(
+ $idsSelect
+ ->reset(Select::LIMIT_COUNT)
+ ->reset(Select::LIMIT_OFFSET)
+ ->columns('rt.review_id')
+ );
+
+ return array_map(
+ function ($value) {
+ return $value['review_id'];
+ },
+ $data
+ );
}
/**
diff --git a/app/code/Magento/Review/Model/Review.php b/app/code/Magento/Review/Model/Review.php
index c00af3fc61407..e689d4ed460ac 100644
--- a/app/code/Magento/Review/Model/Review.php
+++ b/app/code/Magento/Review/Model/Review.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Review\Model;
+use Magento\Framework\DataObject;
use Magento\Catalog\Model\Product;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Review\Model\ResourceModel\Review\Product\Collection as ProductCollection;
@@ -327,6 +328,9 @@ public function appendSummary($collection)
$item->setRatingSummary($summary);
}
}
+ if (!$item->getRatingSummary()) {
+ $item->setRatingSummary(new DataObject());
+ }
}
return $this;
diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json
index c6c8c920ed138..c1d687c665199 100644
--- a/app/code/Magento/Review/composer.json
+++ b/app/code/Magento/Review/composer.json
@@ -18,7 +18,7 @@
"magento/module-review-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "100.2.6",
+ "version": "100.2.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/ReviewAnalytics/composer.json b/app/code/Magento/ReviewAnalytics/composer.json
index 229b486e3f8d4..b95b473c0af70 100644
--- a/app/code/Magento/ReviewAnalytics/composer.json
+++ b/app/code/Magento/ReviewAnalytics/composer.json
@@ -7,7 +7,7 @@
"magento/module-review": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Robots/composer.json b/app/code/Magento/Robots/composer.json
index ccf8356419581..9cf847e152ae7 100644
--- a/app/code/Magento/Robots/composer.json
+++ b/app/code/Magento/Robots/composer.json
@@ -10,7 +10,7 @@
"magento/module-theme": "100.2.*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Rss/composer.json b/app/code/Magento/Rss/composer.json
index d75274856e793..0a8acfe4981e1 100644
--- a/app/code/Magento/Rss/composer.json
+++ b/app/code/Magento/Rss/composer.json
@@ -9,7 +9,7 @@
"magento/module-customer": "101.0.*"
},
"type": "magento2-module",
- "version": "100.2.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
index a1987f67e47f2..dcf742ee91103 100644
--- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
+++ b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
@@ -615,6 +615,9 @@ public function getValueElement()
// date format intentionally hard-coded
$elementParams['input_format'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT;
$elementParams['date_format'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT;
+ $elementParams['placeholder'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT;
+ $elementParams['autocomplete'] = 'off';
+ $elementParams['readonly'] = 'true';
}
return $this->getForm()->addField(
$this->getPrefix() . '__' . $this->getId() . '__value',
diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json
index 2589db8fe86e6..e37274c19a969 100644
--- a/app/code/Magento/Rule/composer.json
+++ b/app/code/Magento/Rule/composer.json
@@ -11,7 +11,7 @@
"lib-libxml": "*"
},
"type": "magento2-module",
- "version": "100.2.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js
index b094b9818364a..8e36562ebd7fe 100644
--- a/app/code/Magento/Rule/view/adminhtml/web/rules.js
+++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js
@@ -220,6 +220,8 @@ define([
var elem = Element.down(elemContainer, 'input.input-text');
+ jQuery(elem).trigger('contentUpdated');
+
if (elem) {
elem.focus();
diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php
index 1912655a9292d..10b80b6f4e527 100644
--- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php
+++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php
@@ -88,7 +88,8 @@ public function getStatuses()
*/
public function canSendCommentEmail()
{
- return $this->_salesData->canSendOrderCommentEmail($this->getOrder()->getStore()->getId());
+ return $this->_salesData->canSendOrderCommentEmail($this->getOrder()->getStore()->getId())
+ && $this->_authorization->isAllowed('Magento_Sales::email');
}
/**
diff --git a/app/code/Magento/Sales/Block/Order/Items.php b/app/code/Magento/Sales/Block/Order/Items.php
index 028544cd56219..0b67e9a0746d3 100644
--- a/app/code/Magento/Sales/Block/Order/Items.php
+++ b/app/code/Magento/Sales/Block/Order/Items.php
@@ -71,7 +71,6 @@ protected function _prepareLayout()
$this->itemCollection = $this->itemCollectionFactory->create();
$this->itemCollection->setOrderFilter($this->getOrder());
- $this->itemCollection->filterByParent(null);
/** @var \Magento\Theme\Block\Html\Pager $pagerBlock */
$pagerBlock = $this->getChildBlock('sales_order_item_pager');
diff --git a/app/code/Magento/Sales/Controller/AbstractController/Reorder.php b/app/code/Magento/Sales/Controller/AbstractController/Reorder.php
index d7ab99377e1b5..619b0828ed33d 100644
--- a/app/code/Magento/Sales/Controller/AbstractController/Reorder.php
+++ b/app/code/Magento/Sales/Controller/AbstractController/Reorder.php
@@ -7,7 +7,11 @@
namespace Magento\Sales\Controller\AbstractController;
use Magento\Framework\App\Action;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Framework\Registry;
+use Magento\Framework\Exception\NotFoundException;
+use Magento\Framework\Controller\ResultFactory;
abstract class Reorder extends Action\Action
{
@@ -21,18 +25,26 @@ abstract class Reorder extends Action\Action
*/
protected $_coreRegistry;
+ /**
+ * @var Validator
+ */
+ private $formKeyValidator;
+
/**
* @param Action\Context $context
* @param OrderLoaderInterface $orderLoader
* @param Registry $registry
+ * @param Validator|null $formKeyValidator
*/
public function __construct(
Action\Context $context,
OrderLoaderInterface $orderLoader,
- Registry $registry
+ Registry $registry,
+ Validator $formKeyValidator = null
) {
$this->orderLoader = $orderLoader;
$this->_coreRegistry = $registry;
+ $this->formKeyValidator = $formKeyValidator ?: ObjectManager::getInstance()->create(Validator::class);
parent::__construct($context);
}
@@ -43,6 +55,20 @@ public function __construct(
*/
public function execute()
{
+ if ($this->getRequest()->isPost()) {
+ if (!$this->formKeyValidator->validate($this->getRequest())) {
+ $this->messageManager->addErrorMessage(__('Invalid Form Key. Please refresh the page.'));
+
+ /** @var \Magento\Framework\Controller\Result\Redirect $redirect */
+ $redirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+ $redirect->setPath('*/*/history');
+
+ return $redirect;
+ }
+ } else {
+ throw new NotFoundException(__('Page not found.'));
+ }
+
$result = $this->orderLoader->load($this->_request);
if ($result instanceof \Magento\Framework\Controller\ResultInterface) {
return $result;
diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php
index 45a6dd1252ba3..3cdc8f4bca210 100644
--- a/app/code/Magento/Sales/Helper/Admin.php
+++ b/app/code/Magento/Sales/Helper/Admin.php
@@ -3,8 +3,12 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Sales\Helper;
+/**
+ * Sales admin helper.
+ */
class Admin extends \Magento\Framework\App\Helper\AbstractHelper
{
/**
@@ -148,22 +152,15 @@ public function escapeHtmlWithLinks($data, $allowedTags = null)
$links = [];
$i = 1;
$data = str_replace('%', '%%', $data);
- $regexp = "/]*href\s*?=\s*?([\"\']??)([^\" >]*?)\\1[^>]*>(.*)<\/a>/siU";
+ $regexp = "#(?J).*?)\\1\s*)|(?:\S+\s*=\s*(['\"])(.*?)\\3)\s*)*)|>)"
+ .">?(?:(?:(?.*?)(?:<\/a\s*>?|(?=<\w))|(?.*)))#si";
while (preg_match($regexp, $data, $matches)) {
- //Revert the sprintf escaping
- $url = str_replace('%%', '%', $matches[2]);
- $text = str_replace('%%', '%', $matches[3]);
- //Check for an valid url
- if ($url) {
- $urlScheme = strtolower(parse_url($url, PHP_URL_SCHEME));
- if ($urlScheme !== 'http' && $urlScheme !== 'https') {
- $url = null;
- }
- }
- //Use hash tag as fallback
- if (!$url) {
- $url = '#';
+ $text = '';
+ if (!empty($matches['text'])) {
+ $text = str_replace('%%', '%', $matches['text']);
}
+ $url = $this->filterUrl($matches['link'] ?? '');
//Recreate a minimalistic secure a tag
$links[] = sprintf(
'%s',
@@ -178,4 +175,29 @@ public function escapeHtmlWithLinks($data, $allowedTags = null)
}
return $this->escaper->escapeHtml($data, $allowedTags);
}
+
+ /**
+ * Filter the URL for allowed protocols.
+ *
+ * @param string $url
+ * @return string
+ */
+ private function filterUrl(string $url): string
+ {
+ if ($url) {
+ //Revert the sprintf escaping
+ $url = str_replace('%%', '%', $url);
+ $urlScheme = parse_url($url, PHP_URL_SCHEME);
+ $urlScheme = $urlScheme ? strtolower($urlScheme) : '';
+ if ($urlScheme !== 'http' && $urlScheme !== 'https') {
+ $url = null;
+ }
+ }
+
+ if (!$url) {
+ $url = '#';
+ }
+
+ return $url;
+ }
}
diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php
index c30bb5e328e8b..12d2a5396ddc4 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/Create.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php
@@ -16,6 +16,7 @@
use Magento\Quote\Model\Quote\Item;
use Magento\Sales\Api\Data\OrderAddressInterface;
use Magento\Sales\Model\Order;
+use Magento\Store\Model\StoreManagerInterface;
/**
* Order create model
@@ -243,6 +244,11 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\
*/
private $dataObjectConverter;
+ /**
+ * @var StoreManagerInterface
+ */
+ private $storeManager;
+
/**
* @param \Magento\Framework\ObjectManagerInterface $objectManager
* @param \Magento\Framework\Event\ManagerInterface $eventManager
@@ -274,6 +280,7 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\
* @param array $data
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
* @param ExtensibleDataObjectConverter|null $dataObjectConverter
+ * @param StoreManagerInterface $storeManager
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -306,7 +313,8 @@ public function __construct(
\Magento\Quote\Model\QuoteFactory $quoteFactory,
array $data = [],
\Magento\Framework\Serialize\Serializer\Json $serializer = null,
- ExtensibleDataObjectConverter $dataObjectConverter = null
+ ExtensibleDataObjectConverter $dataObjectConverter = null,
+ StoreManagerInterface $storeManager = null
) {
$this->_objectManager = $objectManager;
$this->_eventManager = $eventManager;
@@ -340,6 +348,7 @@ public function __construct(
parent::__construct($data);
$this->dataObjectConverter = $dataObjectConverter ?: ObjectManager::getInstance()
->get(ExtensibleDataObjectConverter::class);
+ $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
}
/**
@@ -417,7 +426,8 @@ public function setRecollect($flag)
/**
* Recollect totals for customer cart.
- * Set recollect totals flag for quote
+ *
+ * Set recollect totals flag for quote.
*
* @return $this
*/
@@ -1327,6 +1337,7 @@ protected function _createCustomerForm(\Magento\Customer\Api\Data\CustomerInterf
/**
* Set and validate Quote address
+ *
* All errors added to _errors
*
* @param \Magento\Quote\Model\Quote\Address $address
@@ -1530,6 +1541,8 @@ public function resetShippingMethod()
*/
public function collectShippingRates()
{
+ $store = $this->getQuote()->getStore();
+ $this->storeManager->setCurrentStore($store);
$this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
$this->collectRates();
diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php
index a1bbd4856df16..d20493060c3fd 100644
--- a/app/code/Magento/Sales/Model/Order.php
+++ b/app/code/Magento/Sales/Model/Order.php
@@ -8,11 +8,13 @@
use Magento\Directory\Model\Currency;
use Magento\Framework\Api\AttributeValueFactory;
use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Locale\ResolverInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderStatusHistoryInterface;
use Magento\Sales\Model\Order\Payment;
+use Magento\Sales\Model\Order\ProductOption;
use Magento\Sales\Model\ResourceModel\Order\Address\Collection;
use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Collection as CreditmemoCollection;
use Magento\Sales\Model\ResourceModel\Order\Invoice\Collection as InvoiceCollection;
@@ -274,6 +276,11 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
*/
private $localeResolver;
+ /**
+ * @var ProductOption
+ */
+ private $productOption;
+
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
@@ -303,6 +310,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
* @param ResolverInterface $localeResolver
+ * @param ProductOption|null $productOption
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
@@ -334,7 +342,8 @@ public function __construct(
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = [],
- ResolverInterface $localeResolver = null
+ ResolverInterface $localeResolver = null,
+ ProductOption $productOption = null
) {
$this->_storeManager = $storeManager;
$this->_orderConfig = $orderConfig;
@@ -356,6 +365,7 @@ public function __construct(
$this->salesOrderCollectionFactory = $salesOrderCollectionFactory;
$this->priceCurrency = $priceCurrency;
$this->localeResolver = $localeResolver ?: ObjectManager::getInstance()->get(ResolverInterface::class);
+ $this->productOption = $productOption ?: ObjectManager::getInstance()->get(ProductOption::class);
parent::__construct(
$context,
@@ -541,7 +551,14 @@ public function canCancel()
break;
}
}
- if ($allInvoiced) {
+
+ $allRefunded = true;
+ foreach ($this->getAllItems() as $orderItem) {
+ $allRefunded = $allRefunded
+ && ((float)$orderItem->getQtyRefunded() === (float)$orderItem->getQtyInvoiced());
+ }
+
+ if ($allInvoiced && !$allRefunded) {
return false;
}
@@ -559,6 +576,7 @@ public function canCancel()
/**
* Getter whether the payment can be voided
+ *
* @return bool
*/
public function canVoidPayment()
@@ -615,11 +633,11 @@ public function canCreditmemo()
return $this->getForcedCanCreditmemo();
}
- if ($this->canUnhold() || $this->isPaymentReview()) {
- return false;
- }
-
- if ($this->isCanceled() || $this->getState() === self::STATE_CLOSED) {
+ if ($this->canUnhold()
+ || $this->isPaymentReview()
+ || $this->isCanceled()
+ || $this->getState() === self::STATE_CLOSED
+ ) {
return false;
}
@@ -629,17 +647,55 @@ public function canCreditmemo()
* TotalPaid - contains amount, that were not rounded.
*/
$totalRefunded = $this->priceCurrency->round($this->getTotalPaid()) - $this->getTotalRefunded();
- if (abs($totalRefunded) < .0001) {
- return false;
+ if (abs($this->getGrandTotal()) < .0001) {
+ return $this->canCreditmemoForZeroTotal($totalRefunded);
}
+
+ return $this->canCreditmemoForZeroTotalRefunded($totalRefunded);
+ }
+
+ /**
+ * Retrieve credit memo for zero total refunded availability.
+ *
+ * @param float $totalRefunded
+ * @return bool
+ */
+ private function canCreditmemoForZeroTotalRefunded(float $totalRefunded): bool
+ {
+ $isRefundZero = abs($totalRefunded) < .0001;
// Case when Adjustment Fee (adjustment_negative) has been used for first creditmemo
- if (abs($totalRefunded - $this->getAdjustmentNegative()) < .0001) {
+ $hasAdjustmentFee = abs($totalRefunded - $this->getAdjustmentNegative()) < .0001;
+ $hasActinFlag = $this->getActionFlag(self::ACTION_FLAG_EDIT) === false;
+ if ($isRefundZero || $hasAdjustmentFee || $hasActinFlag) {
return false;
}
- if ($this->getActionFlag(self::ACTION_FLAG_EDIT) === false) {
+ return true;
+ }
+
+ /**
+ * Retrieve credit memo for zero total availability.
+ *
+ * @param float $totalRefunded
+ * @return bool
+ */
+ private function canCreditmemoForZeroTotal(float $totalRefunded): bool
+ {
+ $totalPaid = $this->getTotalPaid();
+ //check if total paid is less than grandtotal
+ $checkAmtTotalPaid = $totalPaid <= $this->getGrandTotal();
+ //case when amount is due for invoice
+ $dueAmountCondition = $this->canInvoice() && $checkAmtTotalPaid;
+ //case when paid amount is refunded and order has creditmemo created
+ $creditmemos = ($this->getCreditmemosCollection() === false) ?
+ true : (count($this->getCreditmemosCollection()) > 0);
+ $paidAmtIsRefunded = $this->getTotalRefunded() == $totalPaid && $creditmemos;
+ if (($dueAmountCondition || $paidAmtIsRefunded)
+ || (!$checkAmtTotalPaid && abs($totalRefunded - $this->getAdjustmentNegative()) < .0001)
+ ) {
return false;
}
+
return true;
}
@@ -875,7 +931,7 @@ protected function _placePayment()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getPayment()
{
@@ -977,10 +1033,21 @@ public function setState($state)
return $this->setData(self::STATE, $state);
}
+ /**
+ * Retrieve frontend label of order status
+ *
+ * @return string
+ */
+ public function getFrontendStatusLabel()
+ {
+ return $this->getConfig()->getStatusFrontendLabel($this->getStatus());
+ }
+
/**
* Retrieve label of order status
*
* @return string
+ * @throws LocalizedException
*/
public function getStatusLabel()
{
@@ -1083,13 +1150,15 @@ public function place()
}
/**
+ * Hold order.
+ *
* @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws LocalizedException
*/
public function hold()
{
if (!$this->canHold()) {
- throw new \Magento\Framework\Exception\LocalizedException(__('A hold action is not available.'));
+ throw new LocalizedException(__('A hold action is not available.'));
}
$this->setHoldBeforeState($this->getState());
$this->setHoldBeforeStatus($this->getStatus());
@@ -1102,12 +1171,12 @@ public function hold()
* Attempt to unhold the order
*
* @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws LocalizedException
*/
public function unhold()
{
if (!$this->canUnhold()) {
- throw new \Magento\Framework\Exception\LocalizedException(__('You cannot remove the hold.'));
+ throw new LocalizedException(__('You cannot remove the hold.'));
}
$this->setState($this->getHoldBeforeState())
@@ -1151,7 +1220,7 @@ public function isFraudDetected()
* @param string $comment
* @param bool $graceful
* @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws LocalizedException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function registerCancellation($comment = '', $graceful = true)
@@ -1190,7 +1259,7 @@ public function registerCancellation($comment = '', $graceful = true)
$this->addStatusHistoryComment($comment, false);
}
} elseif (!$graceful) {
- throw new \Magento\Framework\Exception\LocalizedException(__('We cannot cancel this order.'));
+ throw new LocalizedException(__('We cannot cancel this order.'));
}
return $this;
}
@@ -1228,6 +1297,8 @@ public function getShippingMethod($asObject = false)
/*********************** ADDRESSES ***************************/
/**
+ * Get addresses collection.
+ *
* @return Collection
*/
public function getAddressesCollection()
@@ -1242,6 +1313,8 @@ public function getAddressesCollection()
}
/**
+ * Get address by id.
+ *
* @param mixed $addressId
* @return false
*/
@@ -1256,6 +1329,8 @@ public function getAddressById($addressId)
}
/**
+ * Add address.
+ *
* @param \Magento\Sales\Model\Order\Address $address
* @return $this
*/
@@ -1270,6 +1345,8 @@ public function addAddress(\Magento\Sales\Model\Order\Address $address)
}
/**
+ * Get items collection.
+ *
* @param array $filterByTypes
* @param bool $nonChildrenOnly
* @return ItemCollection
@@ -1288,6 +1365,7 @@ public function getItemsCollection($filterByTypes = [], $nonChildrenOnly = false
if ($this->getId()) {
foreach ($collection as $item) {
$item->setOrder($this);
+ $this->productOption->add($item);
}
}
return $collection;
@@ -1342,6 +1420,8 @@ protected function _getItemsRandomCollection($limit, $nonChildrenOnly = false)
}
/**
+ * Get all items.
+ *
* @return \Magento\Sales\Model\Order\Item[]
*/
public function getAllItems()
@@ -1356,6 +1436,8 @@ public function getAllItems()
}
/**
+ * Get all visible items.
+ *
* @return array
*/
public function getAllVisibleItems()
@@ -1387,6 +1469,8 @@ public function getItemById($itemId)
}
/**
+ * Get item by quote item id.
+ *
* @param mixed $quoteItemId
* @return \Magento\Framework\DataObject|null
*/
@@ -1401,6 +1485,8 @@ public function getItemByQuoteItemId($quoteItemId)
}
/**
+ * Add item.
+ *
* @param \Magento\Sales\Model\Order\Item $item
* @return $this
*/
@@ -1416,6 +1502,8 @@ public function addItem(\Magento\Sales\Model\Order\Item $item)
/*********************** PAYMENTS ***************************/
/**
+ * Get payments collection.
+ *
* @return PaymentCollection
*/
public function getPaymentsCollection()
@@ -1430,6 +1518,8 @@ public function getPaymentsCollection()
}
/**
+ * Get all payments.
+ *
* @return array
*/
public function getAllPayments()
@@ -1444,6 +1534,8 @@ public function getAllPayments()
}
/**
+ * Get payment by id.
+ *
* @param mixed $paymentId
* @return Payment|false
*/
@@ -1458,7 +1550,7 @@ public function getPaymentById($paymentId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setPayment(\Magento\Sales\Api\Data\OrderPaymentInterface $payment = null)
{
@@ -1525,6 +1617,8 @@ public function getVisibleStatusHistory()
}
/**
+ * Get status history by id.
+ *
* @param mixed $statusId
* @return string|false
*/
@@ -1550,7 +1644,10 @@ public function getStatusHistoryById($statusId)
public function addStatusHistory(\Magento\Sales\Model\Order\Status\History $history)
{
$history->setOrder($this);
- $this->setStatus($history->getStatus());
+ $status = $history->getStatus();
+ if (null !== $status) {
+ $this->setStatus($status);
+ }
if (!$history->getId()) {
$this->setStatusHistories(array_merge($this->getStatusHistories(), [$history]));
$this->setDataChanges(true);
@@ -1559,6 +1656,8 @@ public function addStatusHistory(\Magento\Sales\Model\Order\Status\History $hist
}
/**
+ * Get real order id.
+ *
* @return string
*/
public function getRealOrderId()
@@ -1587,9 +1686,9 @@ public function getOrderCurrency()
/**
* Get formatted price value including order currency rate to order website currency
*
- * @param float $price
- * @param bool $addBrackets
- * @return string
+ * @param float $price
+ * @param bool $addBrackets
+ * @return string
*/
public function formatPrice($price, $addBrackets = false)
{
@@ -1597,6 +1696,8 @@ public function formatPrice($price, $addBrackets = false)
}
/**
+ * Format price precision.
+ *
* @param float $price
* @param int $precision
* @param bool $addBrackets
@@ -1610,8 +1711,8 @@ public function formatPricePrecision($price, $precision, $addBrackets = false)
/**
* Retrieve text formatted price value including order rate
*
- * @param float $price
- * @return string
+ * @param float $price
+ * @return string
*/
public function formatPriceTxt($price)
{
@@ -1632,6 +1733,8 @@ public function getBaseCurrency()
}
/**
+ * Format base price.
+ *
* @param float $price
* @return string
*/
@@ -1641,6 +1744,8 @@ public function formatBasePrice($price)
}
/**
+ * Format Base Price Precision.
+ *
* @param float $price
* @param int $precision
* @return string
@@ -1651,6 +1756,8 @@ public function formatBasePricePrecision($price, $precision)
}
/**
+ * Is currency different.
+ *
* @return bool
*/
public function isCurrencyDifferent()
@@ -1683,6 +1790,8 @@ public function getBaseTotalDue()
}
/**
+ * Get data.
+ *
* @param string $key
* @param null|string|int $index
* @return mixed
@@ -1823,6 +1932,8 @@ public function getRelatedObjects()
}
/**
+ * Get customer name.
+ *
* @return string
*/
public function getCustomerName()
@@ -1850,8 +1961,8 @@ public function addRelatedObject(\Magento\Framework\Model\AbstractModel $object)
/**
* Get formatted order created date in store timezone
*
- * @param string $format date format type (short|medium|long|full)
- * @return string
+ * @param string $format date format type (short|medium|long|full)
+ * @return string
*/
public function getCreatedAtFormatted($format)
{
@@ -1865,6 +1976,8 @@ public function getCreatedAtFormatted($format)
}
/**
+ * Get email customer note.
+ *
* @return string
*/
public function getEmailCustomerNote()
@@ -1876,6 +1989,8 @@ public function getEmailCustomerNote()
}
/**
+ * Get store group name.
+ *
* @return string
*/
public function getStoreGroupName()
@@ -1888,8 +2003,7 @@ public function getStoreGroupName()
}
/**
- * Resets all data in object
- * so after another load it will be complete new object
+ * Reset all data in object so after another load it will be complete new object.
*
* @return $this
*/
@@ -1913,6 +2027,8 @@ public function reset()
}
/**
+ * Get order is not virtual.
+ *
* @return bool
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
*/
@@ -1943,7 +2059,7 @@ public function isCanceled()
}
/**
- * Returns increment id
+ * Return increment id
*
* @codeCoverageIgnore
*
@@ -1955,6 +2071,8 @@ public function getIncrementId()
}
/**
+ * Get Items.
+ *
* @return \Magento\Sales\Api\Data\OrderItemInterface[]
*/
public function getItems()
@@ -1969,7 +2087,7 @@ public function getItems()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
* @codeCoverageIgnore
*/
public function setItems($items)
@@ -1978,6 +2096,8 @@ public function setItems($items)
}
/**
+ * Get addresses.
+ *
* @return \Magento\Sales\Api\Data\OrderAddressInterface[]
*/
public function getAddresses()
@@ -1992,6 +2112,8 @@ public function getAddresses()
}
/**
+ * Get status History.
+ *
* @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[]|null
*/
public function getStatusHistories()
@@ -2006,7 +2128,7 @@ public function getStatusHistories()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*
* @return \Magento\Sales\Api\Data\OrderExtensionInterface|null
*/
@@ -2016,7 +2138,7 @@ public function getExtensionAttributes()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*
* @param \Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes
* @return $this
@@ -2029,7 +2151,7 @@ public function setExtensionAttributes(\Magento\Sales\Api\Data\OrderExtensionInt
//@codeCoverageIgnoreStart
/**
- * Returns adjustment_negative
+ * Return adjustment_negative.
*
* @return float|null
*/
@@ -2039,7 +2161,7 @@ public function getAdjustmentNegative()
}
/**
- * Returns adjustment_positive
+ * Return adjustment_positive.
*
* @return float|null
*/
@@ -2049,7 +2171,7 @@ public function getAdjustmentPositive()
}
/**
- * Returns applied_rule_ids
+ * Return applied_rule_ids.
*
* @return string|null
*/
@@ -2059,7 +2181,7 @@ public function getAppliedRuleIds()
}
/**
- * Returns base_adjustment_negative
+ * Return base_adjustment_negative.
*
* @return float|null
*/
@@ -2069,7 +2191,7 @@ public function getBaseAdjustmentNegative()
}
/**
- * Returns base_adjustment_positive
+ * Return base_adjustment_positive.
*
* @return float|null
*/
@@ -2079,7 +2201,7 @@ public function getBaseAdjustmentPositive()
}
/**
- * Returns base_currency_code
+ * Return base_currency_code.
*
* @return string|null
*/
@@ -2089,7 +2211,7 @@ public function getBaseCurrencyCode()
}
/**
- * Returns base_discount_amount
+ * Return base_discount_amount.
*
* @return float|null
*/
@@ -2099,7 +2221,7 @@ public function getBaseDiscountAmount()
}
/**
- * Returns base_discount_canceled
+ * Return base_discount_canceled.
*
* @return float|null
*/
@@ -2109,7 +2231,7 @@ public function getBaseDiscountCanceled()
}
/**
- * Returns base_discount_invoiced
+ * Return base_discount_invoiced.
*
* @return float|null
*/
@@ -2119,7 +2241,7 @@ public function getBaseDiscountInvoiced()
}
/**
- * Returns base_discount_refunded
+ * Return base_discount_refunded.
*
* @return float|null
*/
@@ -2129,7 +2251,7 @@ public function getBaseDiscountRefunded()
}
/**
- * Returns base_grand_total
+ * Return base_grand_total.
*
* @return float
*/
@@ -2139,7 +2261,7 @@ public function getBaseGrandTotal()
}
/**
- * Returns base_discount_tax_compensation_amount
+ * Return base_discount_tax_compensation_amount.
*
* @return float|null
*/
@@ -2149,7 +2271,7 @@ public function getBaseDiscountTaxCompensationAmount()
}
/**
- * Returns base_discount_tax_compensation_invoiced
+ * Return base_discount_tax_compensation_invoiced.
*
* @return float|null
*/
@@ -2159,7 +2281,7 @@ public function getBaseDiscountTaxCompensationInvoiced()
}
/**
- * Returns base_discount_tax_compensation_refunded
+ * Return base_discount_tax_compensation_refunded.
*
* @return float|null
*/
@@ -2169,7 +2291,7 @@ public function getBaseDiscountTaxCompensationRefunded()
}
/**
- * Returns base_shipping_amount
+ * Return base_shipping_amount.
*
* @return float|null
*/
@@ -2179,7 +2301,7 @@ public function getBaseShippingAmount()
}
/**
- * Returns base_shipping_canceled
+ * Return base_shipping_canceled.
*
* @return float|null
*/
@@ -2189,7 +2311,7 @@ public function getBaseShippingCanceled()
}
/**
- * Returns base_shipping_discount_amount
+ * Return base_shipping_discount_amount.
*
* @return float|null
*/
@@ -2199,7 +2321,7 @@ public function getBaseShippingDiscountAmount()
}
/**
- * Returns base_shipping_discount_tax_compensation_amnt
+ * Return base_shipping_discount_tax_compensation_amnt.
*
* @return float|null
*/
@@ -2209,7 +2331,7 @@ public function getBaseShippingDiscountTaxCompensationAmnt()
}
/**
- * Returns base_shipping_incl_tax
+ * Return base_shipping_incl_tax.
*
* @return float|null
*/
@@ -2219,7 +2341,7 @@ public function getBaseShippingInclTax()
}
/**
- * Returns base_shipping_invoiced
+ * Return base_shipping_invoiced.
*
* @return float|null
*/
@@ -2229,7 +2351,7 @@ public function getBaseShippingInvoiced()
}
/**
- * Returns base_shipping_refunded
+ * Return base_shipping_refunded.
*
* @return float|null
*/
@@ -2239,7 +2361,7 @@ public function getBaseShippingRefunded()
}
/**
- * Returns base_shipping_tax_amount
+ * Return base_shipping_tax_amount.
*
* @return float|null
*/
@@ -2249,7 +2371,7 @@ public function getBaseShippingTaxAmount()
}
/**
- * Returns base_shipping_tax_refunded
+ * Return base_shipping_tax_refunded.
*
* @return float|null
*/
@@ -2259,7 +2381,7 @@ public function getBaseShippingTaxRefunded()
}
/**
- * Returns base_subtotal
+ * Return base_subtotal.
*
* @return float|null
*/
@@ -2269,7 +2391,7 @@ public function getBaseSubtotal()
}
/**
- * Returns base_subtotal_canceled
+ * Return base_subtotal_canceled.
*
* @return float|null
*/
@@ -2279,7 +2401,7 @@ public function getBaseSubtotalCanceled()
}
/**
- * Returns base_subtotal_incl_tax
+ * Return base_subtotal_incl_tax.
*
* @return float|null
*/
@@ -2289,7 +2411,7 @@ public function getBaseSubtotalInclTax()
}
/**
- * Returns base_subtotal_invoiced
+ * Return base_subtotal_invoiced.
*
* @return float|null
*/
@@ -2299,7 +2421,7 @@ public function getBaseSubtotalInvoiced()
}
/**
- * Returns base_subtotal_refunded
+ * Return base_subtotal_refunded.
*
* @return float|null
*/
@@ -2309,7 +2431,7 @@ public function getBaseSubtotalRefunded()
}
/**
- * Returns base_tax_amount
+ * Return base_tax_amount.
*
* @return float|null
*/
@@ -2319,7 +2441,7 @@ public function getBaseTaxAmount()
}
/**
- * Returns base_tax_canceled
+ * Return base_tax_canceled.
*
* @return float|null
*/
@@ -2329,7 +2451,7 @@ public function getBaseTaxCanceled()
}
/**
- * Returns base_tax_invoiced
+ * Return base_tax_invoiced.
*
* @return float|null
*/
@@ -2339,7 +2461,7 @@ public function getBaseTaxInvoiced()
}
/**
- * Returns base_tax_refunded
+ * Return base_tax_refunded.
*
* @return float|null
*/
@@ -2349,7 +2471,7 @@ public function getBaseTaxRefunded()
}
/**
- * Returns base_total_canceled
+ * Return base_total_canceled.
*
* @return float|null
*/
@@ -2359,7 +2481,7 @@ public function getBaseTotalCanceled()
}
/**
- * Returns base_total_invoiced
+ * Return base_total_invoiced.
*
* @return float|null
*/
@@ -2369,7 +2491,7 @@ public function getBaseTotalInvoiced()
}
/**
- * Returns base_total_invoiced_cost
+ * Return base_total_invoiced_cost.
*
* @return float|null
*/
@@ -2379,7 +2501,7 @@ public function getBaseTotalInvoicedCost()
}
/**
- * Returns base_total_offline_refunded
+ * Return base_total_offline_refunded.
*
* @return float|null
*/
@@ -2389,7 +2511,7 @@ public function getBaseTotalOfflineRefunded()
}
/**
- * Returns base_total_online_refunded
+ * Return base_total_online_refunded.
*
* @return float|null
*/
@@ -2399,7 +2521,7 @@ public function getBaseTotalOnlineRefunded()
}
/**
- * Returns base_total_paid
+ * Return base_total_paid.
*
* @return float|null
*/
@@ -2409,7 +2531,7 @@ public function getBaseTotalPaid()
}
/**
- * Returns base_total_qty_ordered
+ * Return base_total_qty_ordered.
*
* @return float|null
*/
@@ -2419,7 +2541,7 @@ public function getBaseTotalQtyOrdered()
}
/**
- * Returns base_total_refunded
+ * Return base_total_refunded.
*
* @return float|null
*/
@@ -2429,7 +2551,7 @@ public function getBaseTotalRefunded()
}
/**
- * Returns base_to_global_rate
+ * Return base_to_global_rate.
*
* @return float|null
*/
@@ -2439,7 +2561,7 @@ public function getBaseToGlobalRate()
}
/**
- * Returns base_to_order_rate
+ * Return base_to_order_rate.
*
* @return float|null
*/
@@ -2449,7 +2571,7 @@ public function getBaseToOrderRate()
}
/**
- * Returns billing_address_id
+ * Return billing_address_id.
*
* @return int|null
*/
@@ -2459,7 +2581,7 @@ public function getBillingAddressId()
}
/**
- * Returns can_ship_partially
+ * Return can_ship_partially.
*
* @return int|null
*/
@@ -2469,7 +2591,7 @@ public function getCanShipPartially()
}
/**
- * Returns can_ship_partially_item
+ * Return can_ship_partially_item.
*
* @return int|null
*/
@@ -2479,7 +2601,7 @@ public function getCanShipPartiallyItem()
}
/**
- * Returns coupon_code
+ * Return coupon_code.
*
* @return string|null
*/
@@ -2489,7 +2611,7 @@ public function getCouponCode()
}
/**
- * Returns created_at
+ * Return created_at.
*
* @return string|null
*/
@@ -2499,7 +2621,7 @@ public function getCreatedAt()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCreatedAt($createdAt)
{
@@ -2507,7 +2629,7 @@ public function setCreatedAt($createdAt)
}
/**
- * Returns customer_dob
+ * Return customer_dob.
*
* @return string|null
*/
@@ -2517,7 +2639,7 @@ public function getCustomerDob()
}
/**
- * Returns customer_email
+ * Return customer_email.
*
* @return string
*/
@@ -2527,7 +2649,7 @@ public function getCustomerEmail()
}
/**
- * Returns customer_firstname
+ * Return customer_firstname.
*
* @return string|null
*/
@@ -2537,7 +2659,7 @@ public function getCustomerFirstname()
}
/**
- * Returns customer_gender
+ * Return customer_gender.
*
* @return int|null
*/
@@ -2547,7 +2669,7 @@ public function getCustomerGender()
}
/**
- * Returns customer_group_id
+ * Return customer_group_id.
*
* @return int|null
*/
@@ -2557,7 +2679,7 @@ public function getCustomerGroupId()
}
/**
- * Returns customer_id
+ * Return customer_id.
*
* @return int|null
*/
@@ -2567,7 +2689,7 @@ public function getCustomerId()
}
/**
- * Returns customer_is_guest
+ * Return customer_is_guest.
*
* @return int|null
*/
@@ -2577,7 +2699,7 @@ public function getCustomerIsGuest()
}
/**
- * Returns customer_lastname
+ * Return customer_lastname.
*
* @return string|null
*/
@@ -2587,7 +2709,7 @@ public function getCustomerLastname()
}
/**
- * Returns customer_middlename
+ * Return customer_middlename.
*
* @return string|null
*/
@@ -2597,7 +2719,7 @@ public function getCustomerMiddlename()
}
/**
- * Returns customer_note
+ * Return customer_note.
*
* @return string|null
*/
@@ -2607,7 +2729,7 @@ public function getCustomerNote()
}
/**
- * Returns customer_note_notify
+ * Return customer_note_notify.
*
* @return int|null
*/
@@ -2617,7 +2739,7 @@ public function getCustomerNoteNotify()
}
/**
- * Returns customer_prefix
+ * Return customer_prefix.
*
* @return string|null
*/
@@ -2627,7 +2749,7 @@ public function getCustomerPrefix()
}
/**
- * Returns customer_suffix
+ * Return customer_suffix.
*
* @return string|null
*/
@@ -2637,7 +2759,7 @@ public function getCustomerSuffix()
}
/**
- * Returns customer_taxvat
+ * Return customer_taxvat.
*
* @return string|null
*/
@@ -2647,7 +2769,7 @@ public function getCustomerTaxvat()
}
/**
- * Returns discount_amount
+ * Return discount_amount.
*
* @return float|null
*/
@@ -2657,7 +2779,7 @@ public function getDiscountAmount()
}
/**
- * Returns discount_canceled
+ * Return discount_canceled.
*
* @return float|null
*/
@@ -2667,7 +2789,7 @@ public function getDiscountCanceled()
}
/**
- * Returns discount_description
+ * Return discount_description.
*
* @return string|null
*/
@@ -2677,7 +2799,7 @@ public function getDiscountDescription()
}
/**
- * Returns discount_invoiced
+ * Return discount_invoiced.
*
* @return float|null
*/
@@ -2687,7 +2809,7 @@ public function getDiscountInvoiced()
}
/**
- * Returns discount_refunded
+ * Return discount_refunded.
*
* @return float|null
*/
@@ -2697,7 +2819,7 @@ public function getDiscountRefunded()
}
/**
- * Returns edit_increment
+ * Return edit_increment.
*
* @return int|null
*/
@@ -2707,7 +2829,7 @@ public function getEditIncrement()
}
/**
- * Returns email_sent
+ * Return email_sent.
*
* @return int|null
*/
@@ -2717,7 +2839,7 @@ public function getEmailSent()
}
/**
- * Returns ext_customer_id
+ * Return ext_customer_id.
*
* @return string|null
*/
@@ -2727,7 +2849,7 @@ public function getExtCustomerId()
}
/**
- * Returns ext_order_id
+ * Return ext_order_id.
*
* @return string|null
*/
@@ -2737,7 +2859,7 @@ public function getExtOrderId()
}
/**
- * Returns forced_shipment_with_invoice
+ * Return forced_shipment_with_invoice.
*
* @return int|null
*/
@@ -2747,7 +2869,7 @@ public function getForcedShipmentWithInvoice()
}
/**
- * Returns global_currency_code
+ * Return global_currency_code.
*
* @return string|null
*/
@@ -2757,7 +2879,7 @@ public function getGlobalCurrencyCode()
}
/**
- * Returns grand_total
+ * Return grand_total.
*
* @return float
*/
@@ -2767,7 +2889,7 @@ public function getGrandTotal()
}
/**
- * Returns discount_tax_compensation_amount
+ * Return discount_tax_compensation_amount.
*
* @return float|null
*/
@@ -2777,7 +2899,7 @@ public function getDiscountTaxCompensationAmount()
}
/**
- * Returns discount_tax_compensation_invoiced
+ * Return discount_tax_compensation_invoiced.
*
* @return float|null
*/
@@ -2787,7 +2909,7 @@ public function getDiscountTaxCompensationInvoiced()
}
/**
- * Returns discount_tax_compensation_refunded
+ * Return discount_tax_compensation_refunded.
*
* @return float|null
*/
@@ -2797,7 +2919,7 @@ public function getDiscountTaxCompensationRefunded()
}
/**
- * Returns hold_before_state
+ * Return hold_before_state.
*
* @return string|null
*/
@@ -2807,7 +2929,7 @@ public function getHoldBeforeState()
}
/**
- * Returns hold_before_status
+ * Return hold_before_status.
*
* @return string|null
*/
@@ -2817,7 +2939,7 @@ public function getHoldBeforeStatus()
}
/**
- * Returns is_virtual
+ * Return is_virtual.
*
* @return int|null
*/
@@ -2827,7 +2949,7 @@ public function getIsVirtual()
}
/**
- * Returns order_currency_code
+ * Return order_currency_code.
*
* @return string|null
*/
@@ -2837,7 +2959,7 @@ public function getOrderCurrencyCode()
}
/**
- * Returns original_increment_id
+ * Return original_increment_id.
*
* @return string|null
*/
@@ -2847,7 +2969,7 @@ public function getOriginalIncrementId()
}
/**
- * Returns payment_authorization_amount
+ * Return payment_authorization_amount.
*
* @return float|null
*/
@@ -2857,7 +2979,7 @@ public function getPaymentAuthorizationAmount()
}
/**
- * Returns payment_auth_expiration
+ * Return payment_auth_expiration.
*
* @return int|null
*/
@@ -2867,7 +2989,7 @@ public function getPaymentAuthExpiration()
}
/**
- * Returns protect_code
+ * Return protect_code.
*
* @return string|null
*/
@@ -2877,7 +2999,7 @@ public function getProtectCode()
}
/**
- * Returns quote_address_id
+ * Return quote_address_id.
*
* @return int|null
*/
@@ -2887,7 +3009,7 @@ public function getQuoteAddressId()
}
/**
- * Returns quote_id
+ * Return quote_id.
*
* @return int|null
*/
@@ -2897,7 +3019,7 @@ public function getQuoteId()
}
/**
- * Returns relation_child_id
+ * Return relation_child_id.
*
* @return string|null
*/
@@ -2907,7 +3029,7 @@ public function getRelationChildId()
}
/**
- * Returns relation_child_real_id
+ * Return relation_child_real_id.
*
* @return string|null
*/
@@ -2917,7 +3039,7 @@ public function getRelationChildRealId()
}
/**
- * Returns relation_parent_id
+ * Return relation_parent_id.
*
* @return string|null
*/
@@ -2927,7 +3049,7 @@ public function getRelationParentId()
}
/**
- * Returns relation_parent_real_id
+ * Return relation_parent_real_id.
*
* @return string|null
*/
@@ -2937,7 +3059,7 @@ public function getRelationParentRealId()
}
/**
- * Returns remote_ip
+ * Return remote_ip.
*
* @return string|null
*/
@@ -2947,7 +3069,7 @@ public function getRemoteIp()
}
/**
- * Returns shipping_amount
+ * Return shipping_amount.
*
* @return float|null
*/
@@ -2957,7 +3079,7 @@ public function getShippingAmount()
}
/**
- * Returns shipping_canceled
+ * Return shipping_canceled.
*
* @return float|null
*/
@@ -2967,7 +3089,7 @@ public function getShippingCanceled()
}
/**
- * Returns shipping_description
+ * Return shipping_description.
*
* @return string|null
*/
@@ -2977,7 +3099,7 @@ public function getShippingDescription()
}
/**
- * Returns shipping_discount_amount
+ * Return shipping_discount_amount.
*
* @return float|null
*/
@@ -2987,7 +3109,7 @@ public function getShippingDiscountAmount()
}
/**
- * Returns shipping_discount_tax_compensation_amount
+ * Return shipping_discount_tax_compensation_amount.
*
* @return float|null
*/
@@ -2997,7 +3119,7 @@ public function getShippingDiscountTaxCompensationAmount()
}
/**
- * Returns shipping_incl_tax
+ * Return shipping_incl_tax.
*
* @return float|null
*/
@@ -3007,7 +3129,7 @@ public function getShippingInclTax()
}
/**
- * Returns shipping_invoiced
+ * Return shipping_invoiced.
*
* @return float|null
*/
@@ -3017,7 +3139,7 @@ public function getShippingInvoiced()
}
/**
- * Returns shipping_refunded
+ * Return shipping_refunded.
*
* @return float|null
*/
@@ -3027,7 +3149,7 @@ public function getShippingRefunded()
}
/**
- * Returns shipping_tax_amount
+ * Return shipping_tax_amount.
*
* @return float|null
*/
@@ -3037,7 +3159,7 @@ public function getShippingTaxAmount()
}
/**
- * Returns shipping_tax_refunded
+ * Return shipping_tax_refunded.
*
* @return float|null
*/
@@ -3047,7 +3169,7 @@ public function getShippingTaxRefunded()
}
/**
- * Returns state
+ * Return state.
*
* @return string|null
*/
@@ -3057,7 +3179,7 @@ public function getState()
}
/**
- * Returns status
+ * Return status.
*
* @return string|null
*/
@@ -3067,7 +3189,7 @@ public function getStatus()
}
/**
- * Returns store_currency_code
+ * Return store_currency_code.
*
* @return string|null
*/
@@ -3077,7 +3199,7 @@ public function getStoreCurrencyCode()
}
/**
- * Returns store_id
+ * Return store_id.
*
* @return int|null
*/
@@ -3087,7 +3209,7 @@ public function getStoreId()
}
/**
- * Returns store_name
+ * Return store_name.
*
* @return string|null
*/
@@ -3097,7 +3219,7 @@ public function getStoreName()
}
/**
- * Returns store_to_base_rate
+ * Return store_to_base_rate.
*
* @return float|null
*/
@@ -3107,7 +3229,7 @@ public function getStoreToBaseRate()
}
/**
- * Returns store_to_order_rate
+ * Return store_to_order_rate.
*
* @return float|null
*/
@@ -3117,7 +3239,7 @@ public function getStoreToOrderRate()
}
/**
- * Returns subtotal
+ * Return subtotal.
*
* @return float|null
*/
@@ -3127,7 +3249,7 @@ public function getSubtotal()
}
/**
- * Returns subtotal_canceled
+ * Return subtotal_canceled.
*
* @return float|null
*/
@@ -3137,7 +3259,7 @@ public function getSubtotalCanceled()
}
/**
- * Returns subtotal_incl_tax
+ * Return subtotal_incl_tax.
*
* @return float|null
*/
@@ -3147,7 +3269,7 @@ public function getSubtotalInclTax()
}
/**
- * Returns subtotal_invoiced
+ * Return subtotal_invoiced.
*
* @return float|null
*/
@@ -3157,7 +3279,7 @@ public function getSubtotalInvoiced()
}
/**
- * Returns subtotal_refunded
+ * Return subtotal_refunded.
*
* @return float|null
*/
@@ -3167,7 +3289,7 @@ public function getSubtotalRefunded()
}
/**
- * Returns tax_amount
+ * Return tax_amount.
*
* @return float|null
*/
@@ -3177,7 +3299,7 @@ public function getTaxAmount()
}
/**
- * Returns tax_canceled
+ * Return tax_canceled.
*
* @return float|null
*/
@@ -3187,7 +3309,7 @@ public function getTaxCanceled()
}
/**
- * Returns tax_invoiced
+ * Return tax_invoiced.
*
* @return float|null
*/
@@ -3197,7 +3319,7 @@ public function getTaxInvoiced()
}
/**
- * Returns tax_refunded
+ * Return tax_refunded.
*
* @return float|null
*/
@@ -3207,7 +3329,7 @@ public function getTaxRefunded()
}
/**
- * Returns total_canceled
+ * Return total_canceled.
*
* @return float|null
*/
@@ -3217,7 +3339,7 @@ public function getTotalCanceled()
}
/**
- * Returns total_invoiced
+ * Return total_invoiced.
*
* @return float|null
*/
@@ -3227,7 +3349,7 @@ public function getTotalInvoiced()
}
/**
- * Returns total_item_count
+ * Return total_item_count.
*
* @return int|null
*/
@@ -3237,7 +3359,7 @@ public function getTotalItemCount()
}
/**
- * Returns total_offline_refunded
+ * Return total_offline_refunded.
*
* @return float|null
*/
@@ -3247,7 +3369,7 @@ public function getTotalOfflineRefunded()
}
/**
- * Returns total_online_refunded
+ * Return total_online_refunded.
*
* @return float|null
*/
@@ -3257,7 +3379,7 @@ public function getTotalOnlineRefunded()
}
/**
- * Returns total_paid
+ * Return total_paid.
*
* @return float|null
*/
@@ -3267,7 +3389,7 @@ public function getTotalPaid()
}
/**
- * Returns total_qty_ordered
+ * Return total_qty_ordered.
*
* @return float|null
*/
@@ -3277,7 +3399,7 @@ public function getTotalQtyOrdered()
}
/**
- * Returns total_refunded
+ * Return total_refunded.
*
* @return float|null
*/
@@ -3287,7 +3409,7 @@ public function getTotalRefunded()
}
/**
- * Returns updated_at
+ * Return updated_at.
*
* @return string|null
*/
@@ -3297,7 +3419,7 @@ public function getUpdatedAt()
}
/**
- * Returns weight
+ * Return weight.
*
* @return float|null
*/
@@ -3307,7 +3429,7 @@ public function getWeight()
}
/**
- * Returns x_forwarded_for
+ * Return x_forwarded_for.
*
* @return string|null
*/
@@ -3317,7 +3439,7 @@ public function getXForwardedFor()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStatusHistories(array $statusHistories = null)
{
@@ -3325,7 +3447,7 @@ public function setStatusHistories(array $statusHistories = null)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStatus($status)
{
@@ -3333,7 +3455,7 @@ public function setStatus($status)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCouponCode($code)
{
@@ -3341,7 +3463,7 @@ public function setCouponCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setProtectCode($code)
{
@@ -3349,7 +3471,7 @@ public function setProtectCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingDescription($description)
{
@@ -3357,7 +3479,7 @@ public function setShippingDescription($description)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setIsVirtual($isVirtual)
{
@@ -3365,7 +3487,7 @@ public function setIsVirtual($isVirtual)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreId($id)
{
@@ -3373,7 +3495,7 @@ public function setStoreId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerId($id)
{
@@ -3381,7 +3503,7 @@ public function setCustomerId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountAmount($amount)
{
@@ -3389,7 +3511,7 @@ public function setBaseDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountCanceled($baseDiscountCanceled)
{
@@ -3397,7 +3519,7 @@ public function setBaseDiscountCanceled($baseDiscountCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountInvoiced($baseDiscountInvoiced)
{
@@ -3405,7 +3527,7 @@ public function setBaseDiscountInvoiced($baseDiscountInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountRefunded($baseDiscountRefunded)
{
@@ -3413,7 +3535,7 @@ public function setBaseDiscountRefunded($baseDiscountRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseGrandTotal($amount)
{
@@ -3421,7 +3543,7 @@ public function setBaseGrandTotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingAmount($amount)
{
@@ -3429,7 +3551,7 @@ public function setBaseShippingAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingCanceled($baseShippingCanceled)
{
@@ -3437,7 +3559,7 @@ public function setBaseShippingCanceled($baseShippingCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingInvoiced($baseShippingInvoiced)
{
@@ -3445,7 +3567,7 @@ public function setBaseShippingInvoiced($baseShippingInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingRefunded($baseShippingRefunded)
{
@@ -3453,7 +3575,7 @@ public function setBaseShippingRefunded($baseShippingRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingTaxAmount($amount)
{
@@ -3461,7 +3583,7 @@ public function setBaseShippingTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingTaxRefunded($baseShippingTaxRefunded)
{
@@ -3469,7 +3591,7 @@ public function setBaseShippingTaxRefunded($baseShippingTaxRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotal($amount)
{
@@ -3477,7 +3599,7 @@ public function setBaseSubtotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotalCanceled($baseSubtotalCanceled)
{
@@ -3485,7 +3607,7 @@ public function setBaseSubtotalCanceled($baseSubtotalCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotalInvoiced($baseSubtotalInvoiced)
{
@@ -3493,7 +3615,7 @@ public function setBaseSubtotalInvoiced($baseSubtotalInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotalRefunded($baseSubtotalRefunded)
{
@@ -3501,7 +3623,7 @@ public function setBaseSubtotalRefunded($baseSubtotalRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTaxAmount($amount)
{
@@ -3509,7 +3631,7 @@ public function setBaseTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTaxCanceled($baseTaxCanceled)
{
@@ -3517,7 +3639,7 @@ public function setBaseTaxCanceled($baseTaxCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTaxInvoiced($baseTaxInvoiced)
{
@@ -3525,7 +3647,7 @@ public function setBaseTaxInvoiced($baseTaxInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTaxRefunded($baseTaxRefunded)
{
@@ -3533,7 +3655,7 @@ public function setBaseTaxRefunded($baseTaxRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseToGlobalRate($rate)
{
@@ -3541,7 +3663,7 @@ public function setBaseToGlobalRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseToOrderRate($rate)
{
@@ -3549,7 +3671,7 @@ public function setBaseToOrderRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalCanceled($baseTotalCanceled)
{
@@ -3557,7 +3679,7 @@ public function setBaseTotalCanceled($baseTotalCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalInvoiced($baseTotalInvoiced)
{
@@ -3565,7 +3687,7 @@ public function setBaseTotalInvoiced($baseTotalInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalInvoicedCost($baseTotalInvoicedCost)
{
@@ -3573,7 +3695,7 @@ public function setBaseTotalInvoicedCost($baseTotalInvoicedCost)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded)
{
@@ -3581,7 +3703,7 @@ public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded)
{
@@ -3589,7 +3711,7 @@ public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalPaid($baseTotalPaid)
{
@@ -3597,7 +3719,7 @@ public function setBaseTotalPaid($baseTotalPaid)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalQtyOrdered($baseTotalQtyOrdered)
{
@@ -3605,7 +3727,7 @@ public function setBaseTotalQtyOrdered($baseTotalQtyOrdered)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalRefunded($baseTotalRefunded)
{
@@ -3613,7 +3735,7 @@ public function setBaseTotalRefunded($baseTotalRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountAmount($amount)
{
@@ -3621,7 +3743,7 @@ public function setDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountCanceled($discountCanceled)
{
@@ -3629,7 +3751,7 @@ public function setDiscountCanceled($discountCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountInvoiced($discountInvoiced)
{
@@ -3637,7 +3759,7 @@ public function setDiscountInvoiced($discountInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountRefunded($discountRefunded)
{
@@ -3645,7 +3767,7 @@ public function setDiscountRefunded($discountRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setGrandTotal($amount)
{
@@ -3653,7 +3775,7 @@ public function setGrandTotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingAmount($amount)
{
@@ -3661,7 +3783,7 @@ public function setShippingAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingCanceled($shippingCanceled)
{
@@ -3669,7 +3791,7 @@ public function setShippingCanceled($shippingCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingInvoiced($shippingInvoiced)
{
@@ -3677,7 +3799,7 @@ public function setShippingInvoiced($shippingInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingRefunded($shippingRefunded)
{
@@ -3685,7 +3807,7 @@ public function setShippingRefunded($shippingRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingTaxAmount($amount)
{
@@ -3693,7 +3815,7 @@ public function setShippingTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingTaxRefunded($shippingTaxRefunded)
{
@@ -3701,7 +3823,7 @@ public function setShippingTaxRefunded($shippingTaxRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreToBaseRate($rate)
{
@@ -3709,7 +3831,7 @@ public function setStoreToBaseRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreToOrderRate($rate)
{
@@ -3717,7 +3839,7 @@ public function setStoreToOrderRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotal($amount)
{
@@ -3725,7 +3847,7 @@ public function setSubtotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotalCanceled($subtotalCanceled)
{
@@ -3733,7 +3855,7 @@ public function setSubtotalCanceled($subtotalCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotalInvoiced($subtotalInvoiced)
{
@@ -3741,7 +3863,7 @@ public function setSubtotalInvoiced($subtotalInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotalRefunded($subtotalRefunded)
{
@@ -3749,7 +3871,7 @@ public function setSubtotalRefunded($subtotalRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTaxAmount($amount)
{
@@ -3757,7 +3879,7 @@ public function setTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTaxCanceled($taxCanceled)
{
@@ -3765,7 +3887,7 @@ public function setTaxCanceled($taxCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTaxInvoiced($taxInvoiced)
{
@@ -3773,7 +3895,7 @@ public function setTaxInvoiced($taxInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTaxRefunded($taxRefunded)
{
@@ -3781,7 +3903,7 @@ public function setTaxRefunded($taxRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalCanceled($totalCanceled)
{
@@ -3789,7 +3911,7 @@ public function setTotalCanceled($totalCanceled)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalInvoiced($totalInvoiced)
{
@@ -3797,7 +3919,7 @@ public function setTotalInvoiced($totalInvoiced)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalOfflineRefunded($totalOfflineRefunded)
{
@@ -3805,7 +3927,7 @@ public function setTotalOfflineRefunded($totalOfflineRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalOnlineRefunded($totalOnlineRefunded)
{
@@ -3813,7 +3935,7 @@ public function setTotalOnlineRefunded($totalOnlineRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalPaid($totalPaid)
{
@@ -3821,7 +3943,7 @@ public function setTotalPaid($totalPaid)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalQtyOrdered($totalQtyOrdered)
{
@@ -3829,7 +3951,7 @@ public function setTotalQtyOrdered($totalQtyOrdered)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalRefunded($totalRefunded)
{
@@ -3837,7 +3959,7 @@ public function setTotalRefunded($totalRefunded)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCanShipPartially($flag)
{
@@ -3845,7 +3967,7 @@ public function setCanShipPartially($flag)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCanShipPartiallyItem($flag)
{
@@ -3853,7 +3975,7 @@ public function setCanShipPartiallyItem($flag)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerIsGuest($customerIsGuest)
{
@@ -3861,7 +3983,7 @@ public function setCustomerIsGuest($customerIsGuest)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerNoteNotify($customerNoteNotify)
{
@@ -3869,7 +3991,7 @@ public function setCustomerNoteNotify($customerNoteNotify)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBillingAddressId($id)
{
@@ -3877,7 +3999,7 @@ public function setBillingAddressId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerGroupId($id)
{
@@ -3885,7 +4007,7 @@ public function setCustomerGroupId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setEditIncrement($editIncrement)
{
@@ -3893,7 +4015,7 @@ public function setEditIncrement($editIncrement)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setEmailSent($emailSent)
{
@@ -3901,7 +4023,7 @@ public function setEmailSent($emailSent)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice)
{
@@ -3909,7 +4031,7 @@ public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setPaymentAuthExpiration($paymentAuthExpiration)
{
@@ -3917,7 +4039,7 @@ public function setPaymentAuthExpiration($paymentAuthExpiration)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setQuoteAddressId($id)
{
@@ -3925,7 +4047,7 @@ public function setQuoteAddressId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setQuoteId($id)
{
@@ -3933,7 +4055,7 @@ public function setQuoteId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setAdjustmentNegative($adjustmentNegative)
{
@@ -3941,7 +4063,7 @@ public function setAdjustmentNegative($adjustmentNegative)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setAdjustmentPositive($adjustmentPositive)
{
@@ -3949,7 +4071,7 @@ public function setAdjustmentPositive($adjustmentPositive)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseAdjustmentNegative($baseAdjustmentNegative)
{
@@ -3957,7 +4079,7 @@ public function setBaseAdjustmentNegative($baseAdjustmentNegative)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseAdjustmentPositive($baseAdjustmentPositive)
{
@@ -3965,7 +4087,7 @@ public function setBaseAdjustmentPositive($baseAdjustmentPositive)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingDiscountAmount($amount)
{
@@ -3973,7 +4095,7 @@ public function setBaseShippingDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotalInclTax($amount)
{
@@ -3981,7 +4103,7 @@ public function setBaseSubtotalInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTotalDue($baseTotalDue)
{
@@ -3989,7 +4111,7 @@ public function setBaseTotalDue($baseTotalDue)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setPaymentAuthorizationAmount($amount)
{
@@ -3997,7 +4119,7 @@ public function setPaymentAuthorizationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingDiscountAmount($amount)
{
@@ -4005,7 +4127,7 @@ public function setShippingDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotalInclTax($amount)
{
@@ -4013,7 +4135,7 @@ public function setSubtotalInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalDue($totalDue)
{
@@ -4021,7 +4143,7 @@ public function setTotalDue($totalDue)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setWeight($weight)
{
@@ -4029,7 +4151,7 @@ public function setWeight($weight)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerDob($customerDob)
{
@@ -4037,7 +4159,7 @@ public function setCustomerDob($customerDob)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setIncrementId($id)
{
@@ -4045,7 +4167,7 @@ public function setIncrementId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setAppliedRuleIds($appliedRuleIds)
{
@@ -4053,7 +4175,7 @@ public function setAppliedRuleIds($appliedRuleIds)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseCurrencyCode($code)
{
@@ -4061,7 +4183,7 @@ public function setBaseCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerEmail($customerEmail)
{
@@ -4069,7 +4191,7 @@ public function setCustomerEmail($customerEmail)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerFirstname($customerFirstname)
{
@@ -4077,7 +4199,7 @@ public function setCustomerFirstname($customerFirstname)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerLastname($customerLastname)
{
@@ -4085,7 +4207,7 @@ public function setCustomerLastname($customerLastname)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerMiddlename($customerMiddlename)
{
@@ -4093,7 +4215,7 @@ public function setCustomerMiddlename($customerMiddlename)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerPrefix($customerPrefix)
{
@@ -4101,7 +4223,7 @@ public function setCustomerPrefix($customerPrefix)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerSuffix($customerSuffix)
{
@@ -4109,7 +4231,7 @@ public function setCustomerSuffix($customerSuffix)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerTaxvat($customerTaxvat)
{
@@ -4117,7 +4239,7 @@ public function setCustomerTaxvat($customerTaxvat)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountDescription($description)
{
@@ -4125,7 +4247,7 @@ public function setDiscountDescription($description)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setExtCustomerId($id)
{
@@ -4133,7 +4255,7 @@ public function setExtCustomerId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setExtOrderId($id)
{
@@ -4141,7 +4263,7 @@ public function setExtOrderId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setGlobalCurrencyCode($code)
{
@@ -4149,7 +4271,7 @@ public function setGlobalCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setHoldBeforeState($holdBeforeState)
{
@@ -4157,7 +4279,7 @@ public function setHoldBeforeState($holdBeforeState)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setHoldBeforeStatus($holdBeforeStatus)
{
@@ -4165,7 +4287,7 @@ public function setHoldBeforeStatus($holdBeforeStatus)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setOrderCurrencyCode($code)
{
@@ -4173,7 +4295,7 @@ public function setOrderCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setOriginalIncrementId($id)
{
@@ -4181,7 +4303,7 @@ public function setOriginalIncrementId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRelationChildId($id)
{
@@ -4189,7 +4311,7 @@ public function setRelationChildId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRelationChildRealId($realId)
{
@@ -4197,7 +4319,7 @@ public function setRelationChildRealId($realId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRelationParentId($id)
{
@@ -4205,7 +4327,7 @@ public function setRelationParentId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRelationParentRealId($realId)
{
@@ -4213,7 +4335,7 @@ public function setRelationParentRealId($realId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setRemoteIp($remoteIp)
{
@@ -4221,7 +4343,7 @@ public function setRemoteIp($remoteIp)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreCurrencyCode($code)
{
@@ -4229,7 +4351,7 @@ public function setStoreCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreName($storeName)
{
@@ -4237,7 +4359,7 @@ public function setStoreName($storeName)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setXForwardedFor($xForwardedFor)
{
@@ -4245,7 +4367,7 @@ public function setXForwardedFor($xForwardedFor)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerNote($customerNote)
{
@@ -4253,7 +4375,7 @@ public function setCustomerNote($customerNote)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setUpdatedAt($timestamp)
{
@@ -4261,7 +4383,7 @@ public function setUpdatedAt($timestamp)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTotalItemCount($totalItemCount)
{
@@ -4269,7 +4391,7 @@ public function setTotalItemCount($totalItemCount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCustomerGender($customerGender)
{
@@ -4277,7 +4399,7 @@ public function setCustomerGender($customerGender)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountTaxCompensationAmount($amount)
{
@@ -4285,7 +4407,7 @@ public function setDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountTaxCompensationAmount($amount)
{
@@ -4293,7 +4415,7 @@ public function setBaseDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingDiscountTaxCompensationAmount($amount)
{
@@ -4301,7 +4423,7 @@ public function setShippingDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingDiscountTaxCompensationAmnt($amnt)
{
@@ -4309,7 +4431,7 @@ public function setBaseShippingDiscountTaxCompensationAmnt($amnt)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced)
{
@@ -4317,7 +4439,7 @@ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoi
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced)
{
@@ -4328,7 +4450,7 @@ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensat
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded)
{
@@ -4339,7 +4461,7 @@ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefun
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded)
{
@@ -4350,7 +4472,7 @@ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensat
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingInclTax($amount)
{
@@ -4358,7 +4480,7 @@ public function setShippingInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingInclTax($amount)
{
diff --git a/app/code/Magento/Sales/Model/Order/Config.php b/app/code/Magento/Sales/Model/Order/Config.php
index e00eda647dc8d..8999fca174de9 100644
--- a/app/code/Magento/Sales/Model/Order/Config.php
+++ b/app/code/Magento/Sales/Model/Order/Config.php
@@ -5,6 +5,8 @@
*/
namespace Magento\Sales\Model\Order;
+use Magento\Framework\Exception\LocalizedException;
+
/**
* Order configuration model
*
@@ -85,7 +87,7 @@ protected function _getCollection()
/**
* @param string $state
- * @return Status|null
+ * @return Status
*/
protected function _getState($state)
{
@@ -101,7 +103,7 @@ protected function _getState($state)
* Retrieve default status for state
*
* @param string $state
- * @return string
+ * @return string|null
*/
public function getStateDefaultStatus($state)
{
@@ -115,24 +117,48 @@ public function getStateDefaultStatus($state)
}
/**
- * Retrieve status label
+ * Get status label for a specified area
*
- * @param string $code
- * @return string
+ * @param string $code
+ * @param string $area
+ * @return string
*/
- public function getStatusLabel($code)
+ private function getStatusLabelForArea(string $code, string $area): string
{
- $area = $this->state->getAreaCode();
$code = $this->maskStatusForArea($area, $code);
$status = $this->orderStatusFactory->create()->load($code);
- if ($area == 'adminhtml') {
+ if ($area === 'adminhtml') {
return $status->getLabel();
}
return $status->getStoreLabel();
}
+ /**
+ * Retrieve status label for detected area
+ *
+ * @param string $code
+ * @return string
+ * @throws LocalizedException
+ */
+ public function getStatusLabel($code)
+ {
+ $area = $this->state->getAreaCode() ?: \Magento\Framework\App\Area::AREA_FRONTEND;
+ return $this->getStatusLabelForArea($code, $area);
+ }
+
+ /**
+ * Retrieve status label for area
+ *
+ * @param string $code
+ * @return string
+ */
+ public function getStatusFrontendLabel(string $code): string
+ {
+ return $this->getStatusLabelForArea($code, \Magento\Framework\App\Area::AREA_FRONTEND);
+ }
+
/**
* Mask status for order for specified area
*
diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php
index a9a293e0fc073..49b9f78d06828 100644
--- a/app/code/Magento/Sales/Model/Order/Creditmemo.php
+++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php
@@ -15,6 +15,7 @@
use Magento\Sales\Model\AbstractModel;
use Magento\Sales\Model\EntityInterface;
use Magento\Sales\Model\Order\InvoiceFactory;
+use Magento\Framework\App\Config\ScopeConfigInterface;
/**
* Order creditmemo model
@@ -28,6 +29,7 @@
* @SuppressWarnings(PHPMD.ExcessivePublicCount)
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.TooManyFields)
* @since 100.0.2
*/
class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInterface
@@ -42,6 +44,11 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt
const REPORT_DATE_TYPE_REFUND_CREATED = 'refund_created';
+ /**
+ * Allow Zero Grandtotal for Creditmemo path
+ */
+ const XML_PATH_ALLOW_ZERO_GRANDTOTAL = 'sales/zerograndtotal_creditmemo/allow_zero_grandtotal';
+
/**
* Identifier for order history item
*
@@ -121,6 +128,11 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt
*/
private $invoiceFactory;
+ /**
+ * @var ScopeConfigInterface;
+ */
+ private $scopeConfig;
+
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
@@ -138,6 +150,7 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
* @param InvoiceFactory $invoiceFactory
+ * @param ScopeConfigInterface $scopeConfig
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -156,7 +169,8 @@ public function __construct(
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = [],
- InvoiceFactory $invoiceFactory = null
+ InvoiceFactory $invoiceFactory = null,
+ ScopeConfigInterface $scopeConfig = null
) {
$this->_creditmemoConfig = $creditmemoConfig;
$this->_orderFactory = $orderFactory;
@@ -167,6 +181,7 @@ public function __construct(
$this->_commentCollectionFactory = $commentCollectionFactory;
$this->priceCurrency = $priceCurrency;
$this->invoiceFactory = $invoiceFactory ?: ObjectManager::getInstance()->get(InvoiceFactory::class);
+ $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class);
parent::__construct(
$context,
$registry,
@@ -265,6 +280,8 @@ public function getShippingAddress()
}
/**
+ * Retrieve collection if items.
+ *
* @return mixed
*/
public function getItemsCollection()
@@ -280,6 +297,8 @@ public function getItemsCollection()
}
/**
+ * Retrieve all items.
+ *
* @return \Magento\Sales\Model\Order\Creditmemo\Item[]
*/
public function getAllItems()
@@ -294,6 +313,8 @@ public function getAllItems()
}
/**
+ * Retrieve item by id.
+ *
* @param mixed $itemId
* @return mixed
*/
@@ -324,6 +345,8 @@ public function getItemByOrderId($orderId)
}
/**
+ * Add an item to credit memo.
+ *
* @param \Magento\Sales\Model\Order\Creditmemo\Item $item
* @return $this
*/
@@ -369,6 +392,8 @@ public function roundPrice($price, $type = 'regular', $negative = false)
}
/**
+ * Check if credit memo can be refunded.
+ *
* @return bool
*/
public function canRefund()
@@ -466,6 +491,8 @@ public function getStateName($stateId = null)
}
/**
+ * Set shipping amount.
+ *
* @param float $amount
* @return $this
*/
@@ -475,6 +502,8 @@ public function setShippingAmount($amount)
}
/**
+ * Set adjustment positive amount.
+ *
* @param string $amount
* @return $this
*/
@@ -495,6 +524,8 @@ public function setAdjustmentPositive($amount)
}
/**
+ * Set adjustment negative amount.
+ *
* @param string $amount
* @return $this
*/
@@ -543,6 +574,8 @@ public function isLast()
}
/**
+ * Add comment to credit memo.
+ *
* Adds comment to credit memo with additional possibility to send it to customer via email
* and show it in customer account
*
@@ -569,6 +602,8 @@ public function addComment($comment, $notify = false, $visibleOnFront = false)
}
/**
+ * Retrieve collection of comments.
+ *
* @param bool $reload
* @return \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Comment\Collection
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
@@ -608,11 +643,28 @@ public function getIncrementId()
}
/**
+ * Check if grand total is valid.
+ *
* @return bool
*/
public function isValidGrandTotal()
{
- return !($this->getGrandTotal() <= 0 && !$this->getAllowZeroGrandTotal());
+ return !($this->getGrandTotal() <= 0 && !$this->isAllowZeroGrandTotal());
+ }
+
+ /**
+ * Return Zero GrandTotal availability.
+ *
+ * @return bool
+ */
+ private function isAllowZeroGrandTotal(): bool
+ {
+ $isAllowed = $this->scopeConfig->getValue(
+ self::XML_PATH_ALLOW_ZERO_GRANDTOTAL,
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+ );
+
+ return $isAllowed;
}
/**
@@ -660,7 +712,7 @@ public function getDiscountDescription()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setItems($items)
{
@@ -900,7 +952,7 @@ public function getCreatedAt()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCreatedAt($createdAt)
{
@@ -1159,7 +1211,7 @@ public function getUpdatedAt()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setComments($comments)
{
@@ -1167,7 +1219,7 @@ public function setComments($comments)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreId($id)
{
@@ -1175,7 +1227,7 @@ public function setStoreId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingTaxAmount($amount)
{
@@ -1183,7 +1235,7 @@ public function setBaseShippingTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreToOrderRate($rate)
{
@@ -1191,7 +1243,7 @@ public function setStoreToOrderRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountAmount($amount)
{
@@ -1199,7 +1251,7 @@ public function setBaseDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseToOrderRate($rate)
{
@@ -1207,7 +1259,7 @@ public function setBaseToOrderRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setGrandTotal($amount)
{
@@ -1215,7 +1267,7 @@ public function setGrandTotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotalInclTax($amount)
{
@@ -1223,7 +1275,7 @@ public function setBaseSubtotalInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotalInclTax($amount)
{
@@ -1231,7 +1283,7 @@ public function setSubtotalInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingAmount($amount)
{
@@ -1239,7 +1291,7 @@ public function setBaseShippingAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreToBaseRate($rate)
{
@@ -1247,7 +1299,7 @@ public function setStoreToBaseRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseToGlobalRate($rate)
{
@@ -1255,7 +1307,7 @@ public function setBaseToGlobalRate($rate)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseAdjustment($baseAdjustment)
{
@@ -1263,7 +1315,7 @@ public function setBaseAdjustment($baseAdjustment)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseSubtotal($amount)
{
@@ -1271,7 +1323,7 @@ public function setBaseSubtotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountAmount($amount)
{
@@ -1279,7 +1331,7 @@ public function setDiscountAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setSubtotal($amount)
{
@@ -1287,7 +1339,7 @@ public function setSubtotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setAdjustment($adjustment)
{
@@ -1295,7 +1347,7 @@ public function setAdjustment($adjustment)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseGrandTotal($amount)
{
@@ -1303,7 +1355,7 @@ public function setBaseGrandTotal($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseTaxAmount($amount)
{
@@ -1311,7 +1363,7 @@ public function setBaseTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingTaxAmount($amount)
{
@@ -1319,7 +1371,7 @@ public function setShippingTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setTaxAmount($amount)
{
@@ -1327,7 +1379,7 @@ public function setTaxAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setOrderId($id)
{
@@ -1335,7 +1387,7 @@ public function setOrderId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setEmailSent($emailSent)
{
@@ -1343,7 +1395,7 @@ public function setEmailSent($emailSent)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setCreditmemoStatus($creditmemoStatus)
{
@@ -1351,7 +1403,7 @@ public function setCreditmemoStatus($creditmemoStatus)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setState($state)
{
@@ -1359,7 +1411,7 @@ public function setState($state)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingAddressId($id)
{
@@ -1367,7 +1419,7 @@ public function setShippingAddressId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBillingAddressId($id)
{
@@ -1375,7 +1427,7 @@ public function setBillingAddressId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setInvoiceId($id)
{
@@ -1383,7 +1435,7 @@ public function setInvoiceId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setStoreCurrencyCode($code)
{
@@ -1391,7 +1443,7 @@ public function setStoreCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setOrderCurrencyCode($code)
{
@@ -1399,7 +1451,7 @@ public function setOrderCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseCurrencyCode($code)
{
@@ -1407,7 +1459,7 @@ public function setBaseCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setGlobalCurrencyCode($code)
{
@@ -1415,7 +1467,7 @@ public function setGlobalCurrencyCode($code)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setIncrementId($id)
{
@@ -1423,7 +1475,7 @@ public function setIncrementId($id)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setUpdatedAt($timestamp)
{
@@ -1431,7 +1483,7 @@ public function setUpdatedAt($timestamp)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountTaxCompensationAmount($amount)
{
@@ -1439,7 +1491,7 @@ public function setDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseDiscountTaxCompensationAmount($amount)
{
@@ -1447,7 +1499,7 @@ public function setBaseDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingDiscountTaxCompensationAmount($amount)
{
@@ -1455,7 +1507,7 @@ public function setShippingDiscountTaxCompensationAmount($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingDiscountTaxCompensationAmnt($amnt)
{
@@ -1463,7 +1515,7 @@ public function setBaseShippingDiscountTaxCompensationAmnt($amnt)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setShippingInclTax($amount)
{
@@ -1471,7 +1523,7 @@ public function setShippingInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setBaseShippingInclTax($amount)
{
@@ -1479,7 +1531,7 @@ public function setBaseShippingInclTax($amount)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function setDiscountDescription($description)
{
@@ -1487,9 +1539,7 @@ public function setDiscountDescription($description)
}
/**
- * {@inheritdoc}
- *
- * @return \Magento\Sales\Api\Data\CreditmemoExtensionInterface|null
+ * @inheritdoc
*/
public function getExtensionAttributes()
{
@@ -1497,10 +1547,7 @@ public function getExtensionAttributes()
}
/**
- * {@inheritdoc}
- *
- * @param \Magento\Sales\Api\Data\CreditmemoExtensionInterface $extensionAttributes
- * @return $this
+ * @inheritdoc
*/
public function setExtensionAttributes(\Magento\Sales\Api\Data\CreditmemoExtensionInterface $extensionAttributes)
{
diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php
index f00334f496b2a..f644d0c3a5a63 100644
--- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php
+++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php
@@ -37,6 +37,8 @@ public function __construct(
}
/**
+ * Collects credit memo shipping totals.
+ *
* @param \Magento\Sales\Model\Order\Creditmemo $creditmemo
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
@@ -55,12 +57,10 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
$orderShippingInclTax = $order->getShippingInclTax();
$orderBaseShippingInclTax = $order->getBaseShippingInclTax();
$allowedTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded();
- $baseAllowedTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded();
$allowedAmountInclTax = $allowedAmount + $allowedTaxAmount;
- $baseAllowedAmountInclTax = $baseAllowedAmount + $baseAllowedTaxAmount;
-
- // for the credit memo
- $shippingAmount = $baseShippingAmount = $shippingInclTax = $baseShippingInclTax = 0;
+ $baseAllowedAmountInclTax = $orderBaseShippingInclTax
+ - $order->getBaseShippingRefunded()
+ - $order->getBaseShippingTaxRefunded();
// Check if the desired shipping amount to refund was specified (from invoice or another source).
if ($creditmemo->hasBaseShippingAmount()) {
@@ -128,7 +128,6 @@ private function isSuppliedShippingAmountInclTax($order)
/**
* Get the Tax Config.
- * In a future release, will become a constructor parameter.
*
* @return \Magento\Tax\Model\Config
*
diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php
index a842c0470ad85..5ab9469441bef 100644
--- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php
+++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php
@@ -5,9 +5,14 @@
*/
namespace Magento\Sales\Model\Order\Creditmemo\Total;
+/**
+ * Collects credit memo taxes.
+ */
class Tax extends AbstractTotal
{
/**
+ * Collects credit memo taxes.
+ *
* @param \Magento\Sales\Model\Order\Creditmemo $creditmemo
* @return $this
*
@@ -79,18 +84,10 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
$totalDiscountTaxCompensation += $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor;
$baseTotalDiscountTaxCompensation +=
$invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor;
- $shippingDiscountTaxCompensationAmount =
- $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor;
- $baseShippingDiscountTaxCompensationAmount =
- $invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor;
$shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount);
$baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base');
$totalDiscountTaxCompensation = $creditmemo->roundPrice($totalDiscountTaxCompensation);
$baseTotalDiscountTaxCompensation = $creditmemo->roundPrice($baseTotalDiscountTaxCompensation, 'base');
- $shippingDiscountTaxCompensationAmount =
- $creditmemo->roundPrice($shippingDiscountTaxCompensationAmount);
- $baseShippingDiscountTaxCompensationAmount =
- $creditmemo->roundPrice($baseShippingDiscountTaxCompensationAmount, 'base');
if ($taxFactor < 1 && $invoice->getShippingTaxAmount() > 0) {
$isPartialShippingRefunded = true;
}
diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php
index fd5c015d9db4f..6e12f10f0c679 100644
--- a/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php
+++ b/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php
@@ -5,6 +5,9 @@
*/
namespace Magento\Sales\Model\Order\Invoice\Total;
+/**
+ * Collects invoice taxes.
+ */
class Tax extends AbstractTotal
{
/**
@@ -69,11 +72,24 @@ public function collect(\Magento\Sales\Model\Order\Invoice $invoice)
}
}
+ $taxDiscountCompensationAmt = $totalDiscountTaxCompensation;
+ $baseTaxDiscountCompensationAmt = $baseTotalDiscountTaxCompensation;
+ $allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationAmount() -
+ $order->getDiscountTaxCompensationInvoiced();
+ $allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationAmount() -
+ $order->getBaseDiscountTaxCompensationInvoiced();
+
if ($this->_canIncludeShipping($invoice)) {
$totalTax += $order->getShippingTaxAmount();
$baseTotalTax += $order->getBaseShippingTaxAmount();
$totalDiscountTaxCompensation += $order->getShippingDiscountTaxCompensationAmount();
$baseTotalDiscountTaxCompensation += $order->getBaseShippingDiscountTaxCompensationAmnt();
+
+ $allowedDiscountTaxCompensation += $order->getShippingDiscountTaxCompensationAmount() -
+ $order->getShippingDiscountTaxCompensationInvoiced();
+ $allowedBaseDiscountTaxCompensation += $order->getBaseShippingDiscountTaxCompensationAmnt() -
+ $order->getBaseShippingDiscountTaxCompensationInvoiced();
+
$invoice->setShippingTaxAmount($order->getShippingTaxAmount());
$invoice->setBaseShippingTaxAmount($order->getBaseShippingTaxAmount());
$invoice->setShippingDiscountTaxCompensationAmount($order->getShippingDiscountTaxCompensationAmount());
@@ -81,14 +97,6 @@ public function collect(\Magento\Sales\Model\Order\Invoice $invoice)
}
$allowedTax = $order->getTaxAmount() - $order->getTaxInvoiced();
$allowedBaseTax = $order->getBaseTaxAmount() - $order->getBaseTaxInvoiced();
- $allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationAmount() +
- $order->getShippingDiscountTaxCompensationAmount() -
- $order->getDiscountTaxCompensationInvoiced() -
- $order->getShippingDiscountTaxCompensationInvoiced();
- $allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationAmount() +
- $order->getBaseShippingDiscountTaxCompensationAmnt() -
- $order->getBaseDiscountTaxCompensationInvoiced() -
- $order->getBaseShippingDiscountTaxCompensationInvoiced();
if ($invoice->isLast()) {
$totalTax = $allowedTax;
@@ -107,8 +115,8 @@ public function collect(\Magento\Sales\Model\Order\Invoice $invoice)
$invoice->setTaxAmount($totalTax);
$invoice->setBaseTaxAmount($baseTotalTax);
- $invoice->setDiscountTaxCompensationAmount($totalDiscountTaxCompensation);
- $invoice->setBaseDiscountTaxCompensationAmount($baseTotalDiscountTaxCompensation);
+ $invoice->setDiscountTaxCompensationAmount($taxDiscountCompensationAmt);
+ $invoice->setBaseDiscountTaxCompensationAmount($baseTaxDiscountCompensationAmt);
$invoice->setGrandTotal($invoice->getGrandTotal() + $totalTax + $totalDiscountTaxCompensation);
$invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() + $baseTotalTax + $baseTotalDiscountTaxCompensation);
diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php
index da2a06c2db25a..c202c5d0a643f 100644
--- a/app/code/Magento/Sales/Model/Order/Item.php
+++ b/app/code/Magento/Sales/Model/Order/Item.php
@@ -232,7 +232,7 @@ public function getQtyToShip()
*/
public function getSimpleQtyToShip()
{
- $qty = $this->getQtyOrdered() - $this->getQtyShipped() - $this->getQtyRefunded() - $this->getQtyCanceled();
+ $qty = $this->getQtyOrdered() - $this->getQtyShipped() - $this->getQtyCanceled();
return max($qty, 0);
}
diff --git a/app/code/Magento/Sales/Model/Order/ItemRepository.php b/app/code/Magento/Sales/Model/Order/ItemRepository.php
index 544c809e2c082..6d03f31c76380 100644
--- a/app/code/Magento/Sales/Model/Order/ItemRepository.php
+++ b/app/code/Magento/Sales/Model/Order/ItemRepository.php
@@ -5,9 +5,7 @@
*/
namespace Magento\Sales\Model\Order;
-use Magento\Catalog\Api\Data\ProductOptionExtensionFactory;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
-use Magento\Catalog\Model\ProductOptionFactory;
use Magento\Catalog\Model\ProductOptionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\DataObject;
@@ -17,6 +15,7 @@
use Magento\Sales\Api\Data\OrderItemInterface;
use Magento\Sales\Api\Data\OrderItemSearchResultInterfaceFactory;
use Magento\Sales\Api\OrderItemRepositoryInterface;
+use Magento\Sales\Model\Order\ProductOption;
use Magento\Sales\Model\ResourceModel\Metadata;
/**
@@ -40,16 +39,6 @@ class ItemRepository implements OrderItemRepositoryInterface
*/
protected $searchResultFactory;
- /**
- * @var ProductOptionFactory
- */
- protected $productOptionFactory;
-
- /**
- * @var ProductOptionExtensionFactory
- */
- protected $extensionFactory;
-
/**
* @var ProductOptionProcessorInterface[]
*/
@@ -61,40 +50,41 @@ class ItemRepository implements OrderItemRepositoryInterface
protected $registry = [];
/**
- * @var \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface
+ * @var CollectionProcessorInterface
*/
private $collectionProcessor;
/**
- * ItemRepository constructor.
+ * @var ProductOption
+ */
+ private $productOption;
+
+ /**
* @param DataObjectFactory $objectFactory
* @param Metadata $metadata
* @param OrderItemSearchResultInterfaceFactory $searchResultFactory
- * @param ProductOptionFactory $productOptionFactory
- * @param ProductOptionExtensionFactory $extensionFactory
+ * @param CollectionProcessorInterface $collectionProcessor
+ * @param ProductOption $productOption
* @param array $processorPool
- * @param CollectionProcessorInterface|null $collectionProcessor
*/
public function __construct(
DataObjectFactory $objectFactory,
Metadata $metadata,
OrderItemSearchResultInterfaceFactory $searchResultFactory,
- ProductOptionFactory $productOptionFactory,
- ProductOptionExtensionFactory $extensionFactory,
- array $processorPool = [],
- CollectionProcessorInterface $collectionProcessor = null
+ CollectionProcessorInterface $collectionProcessor,
+ ProductOption $productOption,
+ array $processorPool = []
) {
$this->objectFactory = $objectFactory;
$this->metadata = $metadata;
$this->searchResultFactory = $searchResultFactory;
- $this->productOptionFactory = $productOptionFactory;
- $this->extensionFactory = $extensionFactory;
+ $this->collectionProcessor = $collectionProcessor;
+ $this->productOption = $productOption;
$this->processorPool = $processorPool;
- $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor();
}
/**
- * load entity
+ * Loads entity.
*
* @param int $id
* @return OrderItemInterface
@@ -113,7 +103,7 @@ public function get($id)
throw new NoSuchEntityException(__('Requested entity doesn\'t exist'));
}
- $this->addProductOption($orderItem);
+ $this->productOption->add($orderItem);
$this->addParentItem($orderItem);
$this->registry[$id] = $orderItem;
}
@@ -134,7 +124,7 @@ public function getList(SearchCriteriaInterface $searchCriteria)
$this->collectionProcessor->process($searchCriteria, $searchResult);
/** @var OrderItemInterface $orderItem */
foreach ($searchResult->getItems() as $orderItem) {
- $this->addProductOption($orderItem);
+ $this->productOption->add($orderItem);
}
return $searchResult;
@@ -175,7 +165,9 @@ public function save(OrderItemInterface $entity)
{
if ($entity->getProductOption()) {
$request = $this->getBuyRequest($entity);
- $entity->setProductOptions(['info_buyRequest' => $request->toArray()]);
+ $productOptions = $entity->getProductOptions();
+ $productOptions['info_buyRequest'] = $request->toArray();
+ $entity->setProductOptions($productOptions);
}
$this->metadata->getMapper()->save($entity);
@@ -183,37 +175,6 @@ public function save(OrderItemInterface $entity)
return $this->registry[$entity->getEntityId()];
}
- /**
- * Add product option data
- *
- * @param OrderItemInterface $orderItem
- * @return $this
- */
- protected function addProductOption(OrderItemInterface $orderItem)
- {
- /** @var DataObject $request */
- $request = $orderItem->getBuyRequest();
-
- $productType = $orderItem->getProductType();
- if (isset($this->processorPool[$productType])
- && !$orderItem->getParentItemId()) {
- $data = $this->processorPool[$productType]->convertToProductOption($request);
- if ($data) {
- $this->setProductOption($orderItem, $data);
- }
- }
-
- if (isset($this->processorPool['custom_options'])
- && !$orderItem->getParentItemId()) {
- $data = $this->processorPool['custom_options']->convertToProductOption($request);
- if ($data) {
- $this->setProductOption($orderItem, $data);
- }
- }
-
- return $this;
- }
-
/**
* Set parent item.
*
@@ -228,32 +189,6 @@ private function addParentItem(OrderItemInterface $orderItem)
}
}
- /**
- * Set product options data
- *
- * @param OrderItemInterface $orderItem
- * @param array $data
- * @return $this
- */
- protected function setProductOption(OrderItemInterface $orderItem, array $data)
- {
- $productOption = $orderItem->getProductOption();
- if (!$productOption) {
- $productOption = $this->productOptionFactory->create();
- $orderItem->setProductOption($productOption);
- }
-
- $extensionAttributes = $productOption->getExtensionAttributes();
- if (!$extensionAttributes) {
- $extensionAttributes = $this->extensionFactory->create();
- $productOption->setExtensionAttributes($extensionAttributes);
- }
-
- $extensionAttributes->setData(key($data), current($data));
-
- return $this;
- }
-
/**
* Retrieve order item's buy request
*
@@ -285,20 +220,4 @@ protected function getBuyRequest(OrderItemInterface $entity)
return $request;
}
-
- /**
- * Retrieve collection processor
- *
- * @deprecated 100.2.0
- * @return CollectionProcessorInterface
- */
- private function getCollectionProcessor()
- {
- if (!$this->collectionProcessor) {
- $this->collectionProcessor = \Magento\Framework\App\ObjectManager::getInstance()->get(
- \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface::class
- );
- }
- return $this->collectionProcessor;
- }
}
diff --git a/app/code/Magento/Sales/Model/Order/ProductOption.php b/app/code/Magento/Sales/Model/Order/ProductOption.php
new file mode 100644
index 0000000000000..da0bccd3d806b
--- /dev/null
+++ b/app/code/Magento/Sales/Model/Order/ProductOption.php
@@ -0,0 +1,103 @@
+productOptionFactory = $productOptionFactory;
+ $this->extensionFactory = $extensionFactory;
+ $this->processorPool = $processorPool;
+ }
+
+ /**
+ * Adds product option to the order item.
+ *
+ * @param OrderItemInterface $orderItem
+ * @return void
+ */
+ public function add(OrderItemInterface $orderItem)
+ {
+ /** @var DataObject $request */
+ $request = $orderItem->getBuyRequest();
+
+ $productType = $orderItem->getProductType();
+ if (isset($this->processorPool[$productType])
+ && !$orderItem->getParentItemId()) {
+ $data = $this->processorPool[$productType]->convertToProductOption($request);
+ if ($data) {
+ $this->setProductOption($orderItem, $data);
+ }
+ }
+
+ if (isset($this->processorPool['custom_options'])
+ && !$orderItem->getParentItemId()) {
+ $data = $this->processorPool['custom_options']->convertToProductOption($request);
+ if ($data) {
+ $this->setProductOption($orderItem, $data);
+ }
+ }
+ }
+
+ /**
+ * Sets product options data.
+ *
+ * @param OrderItemInterface $orderItem
+ * @param array $data
+ * @return void
+ */
+ private function setProductOption(OrderItemInterface $orderItem, array $data)
+ {
+ $productOption = $orderItem->getProductOption();
+ if (!$productOption) {
+ $productOption = $this->productOptionFactory->create();
+ $orderItem->setProductOption($productOption);
+ }
+
+ $extensionAttributes = $productOption->getExtensionAttributes();
+ if (!$extensionAttributes) {
+ $extensionAttributes = $this->extensionFactory->create();
+ $productOption->setExtensionAttributes($extensionAttributes);
+ }
+
+ $extensionAttributes->setData(key($data), current($data));
+ }
+}
diff --git a/app/code/Magento/Sales/Model/Order/Shipment.php b/app/code/Magento/Sales/Model/Order/Shipment.php
index 92bbdb9626b6e..9346283321eac 100644
--- a/app/code/Magento/Sales/Model/Order/Shipment.php
+++ b/app/code/Magento/Sales/Model/Order/Shipment.php
@@ -343,7 +343,15 @@ public function addItem(\Magento\Sales\Model\Order\Shipment\Item $item)
public function getTracksCollection()
{
if ($this->tracksCollection === null) {
- $this->tracksCollection = $this->_trackCollectionFactory->create()->setShipmentFilter($this->getId());
+ $this->tracksCollection = $this->_trackCollectionFactory->create();
+
+ if ($this->getId()) {
+ $this->tracksCollection->setShipmentFilter($this->getId());
+
+ foreach ($this->tracksCollection as $item) {
+ $item->setShipment($this);
+ }
+ }
}
return $this->tracksCollection;
@@ -383,19 +391,20 @@ public function getTrackById($trackId)
*/
public function addTrack(\Magento\Sales\Model\Order\Shipment\Track $track)
{
- $track->setShipment(
- $this
- )->setParentId(
- $this->getId()
- )->setOrderId(
- $this->getOrderId()
- )->setStoreId(
- $this->getStoreId()
- );
+ $track->setShipment($this)
+ ->setParentId($this->getId())
+ ->setOrderId($this->getOrderId())
+ ->setStoreId($this->getStoreId());
+
if (!$track->getId()) {
$this->getTracksCollection()->addItem($track);
}
+ $tracks = $this->getTracks();
+ // as it new track entity, collection doesn't contain it
+ $tracks[] = $track;
+ $this->setTracks($tracks);
+
/**
* Track saving is implemented in _afterSave()
* This enforces \Magento\Framework\Model\AbstractModel::save() not to skip _afterSave()
@@ -562,18 +571,16 @@ public function setItems($items)
/**
* Returns tracks
*
- * @return \Magento\Sales\Api\Data\ShipmentTrackInterface[]
+ * @return \Magento\Sales\Api\Data\ShipmentTrackInterface[]|null
*/
public function getTracks()
{
+ if (!$this->getId()) {
+ return $this->getData(ShipmentInterface::TRACKS);
+ }
+
if ($this->getData(ShipmentInterface::TRACKS) === null) {
- $collection = $this->_trackCollectionFactory->create()->setShipmentFilter($this->getId());
- if ($this->getId()) {
- foreach ($collection as $item) {
- $item->setShipment($this);
- }
- $this->setData(ShipmentInterface::TRACKS, $collection->getItems());
- }
+ $this->setData(ShipmentInterface::TRACKS, $this->getTracksCollection()->getItems());
}
return $this->getData(ShipmentInterface::TRACKS);
}
diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php
index f6dd8f8527a53..82c612c1a781d 100644
--- a/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php
@@ -35,4 +35,19 @@ public function __construct(
) {
parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel);
}
+
+ /**
+ * @inheritdoc
+ */
+ protected function _initSelect()
+ {
+ parent::_initSelect();
+
+ $tableDescription = $this->getConnection()->describeTable($this->getMainTable());
+ foreach ($tableDescription as $columnInfo) {
+ $this->addFilterToMap($columnInfo['COLUMN_NAME'], 'main_table.' . $columnInfo['COLUMN_NAME']);
+ }
+
+ return $this;
+ }
}
diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Relation.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Relation.php
index 9c8671d02c578..5851b2d936139 100644
--- a/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Relation.php
+++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Relation.php
@@ -62,8 +62,8 @@ public function processRelation(\Magento\Framework\Model\AbstractModel $object)
$this->shipmentItemResource->save($item);
}
}
- if (null !== $object->getTracksCollection()) {
- foreach ($object->getTracksCollection() as $track) {
+ if (null !== $object->getTracks()) {
+ foreach ($object->getTracks() as $track) {
$track->setParentId($object->getId());
$this->shipmentTrackResource->save($track);
}
diff --git a/app/code/Magento/Sales/Model/Service/CreditmemoService.php b/app/code/Magento/Sales/Model/Service/CreditmemoService.php
index 905e9cc4eae1c..1173fa4b7eb5a 100644
--- a/app/code/Magento/Sales/Model/Service/CreditmemoService.php
+++ b/app/code/Magento/Sales/Model/Service/CreditmemoService.php
@@ -189,6 +189,8 @@ public function refund(
}
/**
+ * Checks if credit memo is available for refund.
+ *
* @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo
* @return bool
* @throws \Magento\Framework\Exception\LocalizedException
@@ -211,7 +213,7 @@ protected function validateForRefund(\Magento\Sales\Api\Data\CreditmemoInterface
throw new \Magento\Framework\Exception\LocalizedException(
__(
'The most money available to refund is %1.',
- $creditmemo->getOrder()->formatBasePrice($baseAvailableRefund)
+ $creditmemo->getOrder()->formatPriceTxt($baseAvailableRefund)
)
);
}
@@ -219,8 +221,9 @@ protected function validateForRefund(\Magento\Sales\Api\Data\CreditmemoInterface
}
/**
- * @return \Magento\Sales\Model\Order\RefundAdapterInterface
+ * Initializes RefundAdapterInterface dependency.
*
+ * @return \Magento\Sales\Model\Order\RefundAdapterInterface
* @deprecated 100.1.3
*/
private function getRefundAdapter()
@@ -233,8 +236,9 @@ private function getRefundAdapter()
}
/**
- * @return \Magento\Framework\App\ResourceConnection|mixed
+ * Initializes ResourceConnection dependency.
*
+ * @return \Magento\Framework\App\ResourceConnection|mixed
* @deprecated 100.1.3
*/
private function getResource()
@@ -247,8 +251,9 @@ private function getResource()
}
/**
- * @return \Magento\Sales\Api\OrderRepositoryInterface
+ * Initializes OrderRepositoryInterface dependency.
*
+ * @return \Magento\Sales\Api\OrderRepositoryInterface
* @deprecated 100.1.3
*/
private function getOrderRepository()
@@ -261,8 +266,9 @@ private function getOrderRepository()
}
/**
- * @return \Magento\Sales\Api\InvoiceRepositoryInterface
+ * Initializes InvoiceRepositoryInterface dependency.
*
+ * @return \Magento\Sales\Api\InvoiceRepositoryInterface
* @deprecated 100.1.3
*/
private function getInvoiceRepository()
diff --git a/app/code/Magento/Sales/Setup/UpgradeSchema.php b/app/code/Magento/Sales/Setup/UpgradeSchema.php
index fe2d422914c57..6e625a1eaaa19 100644
--- a/app/code/Magento/Sales/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Sales/Setup/UpgradeSchema.php
@@ -109,6 +109,9 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
if (version_compare($context->getVersion(), '2.0.10', '<')) {
$this->expandRemoteIpField($installer);
}
+ if (version_compare($context->getVersion(), '2.0.11', '<')) {
+ $this->expandLastTransIdField($installer);
+ }
}
/**
@@ -161,4 +164,21 @@ private function expandRemoteIpField(SchemaSetupInterface $installer)
]
);
}
+
+ /**
+ * @param SchemaSetupInterface $installer
+ * @return void
+ */
+ private function expandLastTransIdField(SchemaSetupInterface $installer)
+ {
+ $connection = $installer->getConnection(self::$connectionName);
+ $connection->modifyColumn(
+ $installer->getTable('sales_order_payment', self::$connectionName),
+ 'last_trans_id',
+ [
+ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+ 'length' => 255
+ ]
+ );
+ }
}
diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml
index a4ff621c05e1d..a46bf13a9688e 100644
--- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml
+++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
@@ -77,13 +77,14 @@
+
-
+
@@ -165,6 +166,15 @@
+
+
+
+
+
+
+
+
+
@@ -193,4 +203,10 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml
new file mode 100644
index 0000000000000..65a4b512394d8
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminCreditMemoNewPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminCreditMemoNewPage.xml
index e78cfc28c4469..a9e37bc3a9df2 100644
--- a/app/code/Magento/Sales/Test/Mftf/Page/AdminCreditMemoNewPage.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminCreditMemoNewPage.xml
@@ -10,5 +10,6 @@
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd">
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoiceNewPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoiceNewPage.xml
index 1f8291c0c2d2f..cfd5c5794a2de 100644
--- a/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoiceNewPage.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoiceNewPage.xml
@@ -12,5 +12,6 @@
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderDetailsPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderDetailsPage.xml
index f217caa49a1e9..4280356278a88 100644
--- a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderDetailsPage.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderDetailsPage.xml
@@ -15,5 +15,9 @@
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml
new file mode 100644
index 0000000000000..d835bfe069683
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml
index 446186d5da8a3..5fa5584fa8824 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml
@@ -10,5 +10,6 @@
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml
new file mode 100644
index 0000000000000..dbae8042b6554
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceItemsSection.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderCreditMemosTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderCreditMemosTabSection.xml
new file mode 100644
index 0000000000000..1e801dab4b134
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderCreditMemosTabSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
index 79a897ec52a4c..c4cf5bd05bb6f 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml
index ab74320f26a30..22bff9c286d0f 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml
@@ -7,12 +7,14 @@
-->
+ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml
new file mode 100644
index 0000000000000..264b57733eea7
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml
new file mode 100644
index 0000000000000..f71b603a40b7d
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml
new file mode 100644
index 0000000000000..78d0a45bce460
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml
index 18823b2b0acc2..f9e954548a4d0 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml
@@ -11,7 +11,12 @@
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml
new file mode 100644
index 0000000000000..66a9709473623
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml
new file mode 100644
index 0000000000000..379cb67d3e52f
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml
index eaad9912c6de1..82ac6d9515ce6 100644
--- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml
@@ -61,6 +61,7 @@
+
diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/SaveTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/SaveTest.php
index 71a474c390de3..cc2bf929f8250 100644
--- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/SaveTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/SaveTest.php
@@ -197,9 +197,11 @@ public function testSaveActionWithNegativeCreditmemo()
);
$this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValue(null));
- $creditmemoMock = $this->createPartialMock(\Magento\Sales\Model\Order\Creditmemo::class, ['load', 'getGrandTotal', 'getAllowZeroGrandTotal', '__wakeup']);
- $creditmemoMock->expects($this->once())->method('getGrandTotal')->will($this->returnValue('0'));
- $creditmemoMock->expects($this->once())->method('getAllowZeroGrandTotal')->will($this->returnValue(false));
+ $creditmemoMock = $this->createPartialMock(
+ \Magento\Sales\Model\Order\Creditmemo::class,
+ ['load', 'isValidGrandTotal', '__wakeup']
+ );
+ $creditmemoMock->expects($this->once())->method('isValidGrandTotal')->willReturn(false);
$this->memoLoaderMock->expects(
$this->once()
)->method(
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php
index 0b65c2d972d32..5981e8ea77e12 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php
@@ -12,6 +12,7 @@
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\CollectionFactory;
use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\Collection as ItemCollection;
+use Magento\Framework\App\Config\ScopeConfigInterface;
/**
* Class CreditmemoTest
@@ -30,6 +31,11 @@ class CreditmemoTest extends \PHPUnit\Framework\TestCase
*/
protected $creditmemo;
+ /**
+ * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $scopeConfigMock;
+
/**
* @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
*/
@@ -38,6 +44,7 @@ class CreditmemoTest extends \PHPUnit\Framework\TestCase
protected function setUp()
{
$this->orderFactory = $this->createPartialMock(\Magento\Sales\Model\OrderFactory::class, ['create']);
+ $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
$objectManagerHelper = new ObjectManagerHelper($this);
$this->cmItemCollectionFactoryMock = $this->getMockBuilder(
@@ -50,16 +57,21 @@ protected function setUp()
'context' => $this->createMock(\Magento\Framework\Model\Context::class),
'registry' => $this->createMock(\Magento\Framework\Registry::class),
'localeDate' => $this->createMock(
- \Magento\Framework\Stdlib\DateTime\TimezoneInterface::class),
+ \Magento\Framework\Stdlib\DateTime\TimezoneInterface::class
+ ),
'dateTime' => $this->createMock(\Magento\Framework\Stdlib\DateTime::class),
'creditmemoConfig' => $this->createMock(
- \Magento\Sales\Model\Order\Creditmemo\Config::class),
+ \Magento\Sales\Model\Order\Creditmemo\Config::class
+ ),
'orderFactory' => $this->orderFactory,
'cmItemCollectionFactory' => $this->cmItemCollectionFactoryMock,
'calculatorFactory' => $this->createMock(\Magento\Framework\Math\CalculatorFactory::class),
'storeManager' => $this->createMock(\Magento\Store\Model\StoreManagerInterface::class),
'commentFactory' => $this->createMock(\Magento\Sales\Model\Order\Creditmemo\CommentFactory::class),
- 'commentCollectionFactory' => $this->createMock(\Magento\Sales\Model\ResourceModel\Order\Creditmemo\Comment\CollectionFactory::class),
+ 'commentCollectionFactory' => $this->createMock(
+ \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Comment\CollectionFactory::class
+ ),
+ 'scopeConfig' => $this->scopeConfigMock
];
$this->creditmemo = $objectManagerHelper->getObject(
\Magento\Sales\Model\Order\Creditmemo::class,
@@ -72,7 +84,10 @@ public function testGetOrder()
$orderId = 100000041;
$this->creditmemo->setOrderId($orderId);
$entityName = 'creditmemo';
- $order = $this->createPartialMock(\Magento\Sales\Model\Order::class, ['load', 'setHistoryEntityName', '__wakeUp']);
+ $order = $this->createPartialMock(
+ \Magento\Sales\Model\Order::class,
+ ['load', 'setHistoryEntityName', '__wakeUp']
+ );
$this->creditmemo->setOrderId($orderId);
$order->expects($this->atLeastOnce())
->method('setHistoryEntityName')
@@ -95,17 +110,50 @@ public function testGetEntityType()
$this->assertEquals('creditmemo', $this->creditmemo->getEntityType());
}
- public function testIsValidGrandTotalGrandTotalEmpty()
+ /**
+ * @dataProvider validGrandTotalDataProvider
+ * @param int $grandTotal
+ * @param int $allowZero
+ * @param bool $expectedResult
+ *
+ * @return void
+ */
+ public function testIsValidGrandTotalGrandTotal(int $grandTotal, int $allowZero, bool $expectedResult)
{
- $this->creditmemo->setGrandTotal(0);
- $this->assertFalse($this->creditmemo->isValidGrandTotal());
+ $this->creditmemo->setGrandTotal($grandTotal);
+ $this->scopeConfigMock->expects($this->any())
+ ->method('getValue')
+ ->with('sales/zerograndtotal_creditmemo/allow_zero_grandtotal',
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE)
+ ->willReturn($allowZero);
+
+ $this->assertEquals($expectedResult, $this->creditmemo->isValidGrandTotal());
}
- public function testIsValidGrandTotalGrandTotal()
+ /**
+ * Data provider for the testIsValidGrantTotalGrantTotal()
+ *
+ * @return array
+ */
+ public function validGrandTotalDataProvider(): array
{
- $this->creditmemo->setGrandTotal(0);
- $this->creditmemo->getAllowZeroGrandTotal(true);
- $this->assertFalse($this->creditmemo->isValidGrandTotal());
+ return [
+ [
+ 'grandTotal' => 0,
+ 'allowZero' => 0,
+ 'expectedResult' => false,
+ ],
+ [
+ 'grandTotal' => 0,
+ 'allowZero' => 1,
+ 'expectedResult' => true,
+ ],
+ [
+ 'grandTotal' => 1,
+ 'allowZero' => 0,
+ 'expectedResult' => true,
+ ],
+ ];
}
public function testIsValidGrandTotal()
@@ -136,7 +184,8 @@ public function testGetItemsCollectionWithId()
/** @var ItemCollection|\PHPUnit_Framework_MockObject_MockObject $itemCollectionMock */
$itemCollectionMock = $this->getMockBuilder(
- \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\Collection::class)
+ \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\Collection::class
+ )
->disableOriginalConstructor()
->getMock();
$itemCollectionMock->expects($this->once())
@@ -164,7 +213,8 @@ public function testGetItemsCollectionWithoutId()
/** @var ItemCollection|\PHPUnit_Framework_MockObject_MockObject $itemCollectionMock */
$itemCollectionMock = $this->getMockBuilder(
- \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\Collection::class)
+ \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\Collection::class
+ )
->disableOriginalConstructor()
->getMock();
$itemCollectionMock->expects($this->once())
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php
deleted file mode 100644
index 0c34e5bdffd4a..0000000000000
--- a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php
+++ /dev/null
@@ -1,365 +0,0 @@
-objectFactory = $this->getMockBuilder(\Magento\Framework\DataObject\Factory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
-
- $this->metadata = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Metadata::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->searchResultFactory = $this->getMockBuilder(
- \Magento\Sales\Api\Data\OrderItemSearchResultInterfaceFactory::class
- )
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
-
- $this->productOptionFactory = $this->getMockBuilder(\Magento\Catalog\Model\ProductOptionFactory::class)
- ->setMethods([
- 'create',
- ])
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->collectionProcessor = $this->createMock(
- \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface::class
- );
-
- $this->extensionFactory = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductOptionExtensionFactory::class)
- ->setMethods([
- 'create',
- ])
- ->disableOriginalConstructor()
- ->getMock();
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\InputException
- * @expectedExceptionMessage ID required
- */
- public function testGetWithNoId()
- {
- $model = new ItemRepository(
- $this->objectFactory,
- $this->metadata,
- $this->searchResultFactory,
- $this->productOptionFactory,
- $this->extensionFactory,
- [],
- $this->collectionProcessor
- );
-
- $model->get(null);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\NoSuchEntityException
- * @expectedExceptionMessage Requested entity doesn't exist
- */
- public function testGetEmptyEntity()
- {
- $orderItemId = 1;
-
- $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
- ->disableOriginalConstructor()
- ->getMock();
- $orderItemMock->expects($this->once())
- ->method('load')
- ->with($orderItemId)
- ->willReturn($orderItemMock);
- $orderItemMock->expects($this->once())
- ->method('getItemId')
- ->willReturn(null);
-
- $this->metadata->expects($this->once())
- ->method('getNewInstance')
- ->willReturn($orderItemMock);
-
- $model = new ItemRepository(
- $this->objectFactory,
- $this->metadata,
- $this->searchResultFactory,
- $this->productOptionFactory,
- $this->extensionFactory,
- [],
- $this->collectionProcessor
- );
-
- $model->get($orderItemId);
- }
-
- public function testGet()
- {
- $orderItemId = 1;
- $productType = 'configurable';
-
- $this->productOptionData = ['option1' => 'value1'];
-
- $this->getProductOptionExtensionMock();
- $productOption = $this->getProductOptionMock();
- $orderItemMock = $this->getOrderMock($productType, $productOption);
-
- $orderItemMock->expects($this->once())
- ->method('load')
- ->with($orderItemId)
- ->willReturn($orderItemMock);
- $orderItemMock->expects($this->once())
- ->method('getItemId')
- ->willReturn($orderItemId);
-
- $this->metadata->expects($this->once())
- ->method('getNewInstance')
- ->willReturn($orderItemMock);
-
- $model = $this->getModel($orderItemMock, $productType);
- $this->assertSame($orderItemMock, $model->get($orderItemId));
-
- // Assert already registered
- $this->assertSame($orderItemMock, $model->get($orderItemId));
- }
-
- public function testGetList()
- {
- $productType = 'configurable';
- $this->productOptionData = ['option1' => 'value1'];
- $searchCriteriaMock = $this->getMockBuilder(\Magento\Framework\Api\SearchCriteria::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->getProductOptionExtensionMock();
- $productOption = $this->getProductOptionMock();
- $orderItemMock = $this->getOrderMock($productType, $productOption);
-
- $searchResultMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Item\Collection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $searchResultMock->expects($this->once())
- ->method('getItems')
- ->willReturn([$orderItemMock]);
-
- $this->searchResultFactory->expects($this->once())
- ->method('create')
- ->willReturn($searchResultMock);
-
- $model = $this->getModel($orderItemMock, $productType);
- $this->assertSame($searchResultMock, $model->getList($searchCriteriaMock));
- }
-
- public function testDeleteById()
- {
- $orderItemId = 1;
- $productType = 'configurable';
-
- $requestMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
- ->disableOriginalConstructor()
- ->getMock();
- $orderItemMock->expects($this->once())
- ->method('load')
- ->with($orderItemId)
- ->willReturn($orderItemMock);
- $orderItemMock->expects($this->once())
- ->method('getItemId')
- ->willReturn($orderItemId);
- $orderItemMock->expects($this->once())
- ->method('getProductType')
- ->willReturn($productType);
- $orderItemMock->expects($this->once())
- ->method('getBuyRequest')
- ->willReturn($requestMock);
-
- $orderItemResourceMock = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\Db\AbstractDb::class)
- ->disableOriginalConstructor()
- ->getMock();
- $orderItemResourceMock->expects($this->once())
- ->method('delete')
- ->with($orderItemMock)
- ->willReturnSelf();
-
- $this->metadata->expects($this->once())
- ->method('getNewInstance')
- ->willReturn($orderItemMock);
- $this->metadata->expects($this->exactly(1))
- ->method('getMapper')
- ->willReturn($orderItemResourceMock);
-
- $model = $this->getModel($orderItemMock, $productType);
- $this->assertTrue($model->deleteById($orderItemId));
- }
-
- /**
- * @param \PHPUnit_Framework_MockObject_MockObject $orderItemMock
- * @param string $productType
- * @param array $data
- * @return ItemRepository
- */
- protected function getModel(
- \PHPUnit_Framework_MockObject_MockObject $orderItemMock,
- $productType,
- array $data = []
- ) {
- $requestMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $requestUpdateMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
- ->disableOriginalConstructor()
- ->getMock();
- $requestUpdateMock->expects($this->any())
- ->method('getData')
- ->willReturn($data);
-
- $this->productOptionProcessorMock = $this->getMockBuilder(
- \Magento\Catalog\Model\ProductOptionProcessorInterface::class
- )
- ->getMockForAbstractClass();
- $this->productOptionProcessorMock->expects($this->any())
- ->method('convertToProductOption')
- ->with($requestMock)
- ->willReturn($this->productOptionData);
- $this->productOptionProcessorMock->expects($this->any())
- ->method('convertToBuyRequest')
- ->with($orderItemMock)
- ->willReturn($requestUpdateMock);
-
- $model = new ItemRepository(
- $this->objectFactory,
- $this->metadata,
- $this->searchResultFactory,
- $this->productOptionFactory,
- $this->extensionFactory,
- [
- $productType => $this->productOptionProcessorMock,
- 'custom_options' => $this->productOptionProcessorMock
- ],
- $this->collectionProcessor
- );
- return $model;
- }
-
- /**
- * @param string $productType
- * @param \PHPUnit_Framework_MockObject_MockObject $productOption
- * @return \PHPUnit_Framework_MockObject_MockObject
- */
- protected function getOrderMock($productType, $productOption)
- {
- $requestMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
- ->disableOriginalConstructor()
- ->getMock();
- $orderItemMock->expects($this->once())
- ->method('getProductType')
- ->willReturn($productType);
- $orderItemMock->expects($this->once())
- ->method('getBuyRequest')
- ->willReturn($requestMock);
- $orderItemMock->expects($this->any())
- ->method('getProductOption')
- ->willReturn(null);
- $orderItemMock->expects($this->any())
- ->method('setProductOption')
- ->with($productOption)
- ->willReturnSelf();
-
- return $orderItemMock;
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject
- */
- protected function getProductOptionMock()
- {
- $productOption = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductOptionInterface::class)
- ->getMockForAbstractClass();
- $productOption->expects($this->any())
- ->method('getExtensionAttributes')
- ->willReturn(null);
-
- $this->productOptionFactory->expects($this->any())
- ->method('create')
- ->willReturn($productOption);
-
- return $productOption;
- }
-
- protected function getProductOptionExtensionMock()
- {
- $productOptionExtension = $this->getMockBuilder(
- \Magento\Catalog\Api\Data\ProductOptionExtensionInterface::class
- )
- ->setMethods([
- 'setData',
- ])
- ->getMockForAbstractClass();
- $productOptionExtension->expects($this->any())
- ->method('setData')
- ->with(key($this->productOptionData), current($this->productOptionData))
- ->willReturnSelf();
-
- $this->extensionFactory->expects($this->any())
- ->method('create')
- ->willReturn($productOptionExtension);
- }
-}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php
index aea234959cea0..ce7fcca42ccb4 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php
@@ -238,4 +238,115 @@ public function getProductOptionsDataProvider()
]
];
}
+
+ /**
+ * Test different combinations of item qty setups
+ *
+ * @param array $options
+ * @param array $expectedResult
+ * @return void
+ *
+ * @dataProvider getItemQtyVariants
+ */
+ public function testGetSimpleQtyToMethods(array $options, array $expectedResult)
+ {
+ $this->model->setData($options);
+ $this->assertSame($this->model->getSimpleQtyToShip(), $expectedResult['to_ship']);
+ $this->assertSame($this->model->getQtyToInvoice(), $expectedResult['to_invoice']);
+ }
+
+ /**
+ * Provides different combinations of qty options for an item and the
+ * expected qtys pending shipment and invoice
+ *
+ * @return array
+ */
+ public function getItemQtyVariants(): array
+ {
+ return [
+ 'empty_item' => [
+ 'options' => [
+ 'qty_ordered' => 0, 'qty_invoiced' => 0, 'qty_refunded' => 0, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 0, 'to_invoice' => 0],
+ ],
+ 'ordered_item' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 0, 'qty_refunded' => 0, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 12, 'to_invoice' => 12],
+ ],
+ 'partially_invoiced' => [
+ 'options' => ['qty_ordered' => 12, 'qty_invoiced' => 4, 'qty_refunded' => 0, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 12, 'to_invoice' => 8],
+ ],
+ 'completely_invoiced' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 0, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 12, 'to_invoice' => 0],
+ ],
+ 'partially_invoiced_refunded' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 5, 'qty_refunded' => 5, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 12, 'to_invoice' => 7],
+ ],
+ 'partially_refunded' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 5, 'qty_shipped' => 0,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 12, 'to_invoice' => 0],
+ ],
+ 'partially_shipped' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 0, 'qty_refunded' => 0, 'qty_shipped' => 4,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 8, 'to_invoice' => 12],
+ ],
+ 'partially_refunded_partially_shipped' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 5, 'qty_shipped' => 4,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 8, 'to_invoice' => 0],
+ ],
+ 'complete' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 0, 'qty_shipped' => 12,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 0, 'to_invoice' => 0],
+ ],
+ 'canceled' => [
+ 'options' => [
+ 'qty_ordered' => 12, 'qty_invoiced' => 0, 'qty_refunded' => 0, 'qty_shipped' => 0,
+ 'qty_canceled' => 12,
+ ],
+ 'expectedResult' => ['to_ship' => 0, 'to_invoice' => 0],
+ ],
+ 'completely_shipped_using_decimals' => [
+ 'options' => [
+ 'qty_ordered' => 4.4, 'qty_invoiced' => 0.4, 'qty_refunded' => 0.4, 'qty_shipped' => 4,
+ 'qty_canceled' => 0,
+ ],
+ 'expectedResult' => ['to_ship' => 0.4, 'to_invoice' => 4.0],
+ ],
+ 'completely_invoiced_using_decimals' => [
+ 'options' => [
+ 'qty_ordered' => 4.4, 'qty_invoiced' => 4, 'qty_refunded' => 0, 'qty_shipped' => 4,
+ 'qty_canceled' => 0.4,
+ ],
+ 'expectedResult' => ['to_ship' => 0.0, 'to_invoice' => 0.0],
+ ],
+ ];
+ }
}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
index 7f6363346872c..6784e10babfee 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
@@ -17,6 +17,7 @@
* Test class for \Magento\Sales\Model\Order
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
*/
class OrderTest extends \PHPUnit\Framework\TestCase
{
@@ -51,6 +52,7 @@ class OrderTest extends \PHPUnit\Framework\TestCase
protected $item;
/**
+ * @var HistoryCollectionFactory|\PHPUnit_Framework_MockObject_MockObject
* @var HistoryCollectionFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $historyCollectionFactoryMock;
@@ -114,7 +116,9 @@ protected function setUp()
'getParentItemId',
'getQuoteItemId',
'getLockedDoInvoice',
- 'getProductId'
+ 'getProductId',
+ 'getQtyRefunded',
+ 'getQtyInvoiced',
]);
$this->salesOrderCollectionMock = $this->getMockBuilder(
\Magento\Sales\Model\ResourceModel\Order\Collection::class
@@ -332,6 +336,20 @@ public function testCanCreditMemo()
$this->assertTrue($this->order->canCreditmemo());
}
+ /**
+ * Test canCreditMemo method when grand total and paid total are zero.
+ *
+ * @return void
+ */
+ public function testCanCreditMemoForZeroTotal()
+ {
+ $grandTotal = 0;
+ $totalPaid = 0;
+ $this->order->setGrandTotal($grandTotal);
+ $this->order->setTotalPaid($totalPaid);
+ $this->assertFalse($this->order->canCreditmemo());
+ }
+
public function testCanNotCreditMemoWithTotalNull()
{
$totalPaid = 0;
@@ -619,6 +637,124 @@ public function testCanCancelAllInvoiced()
$this->item->expects($this->any())
->method('getQtyToInvoice')
->willReturn(0);
+ $this->item->expects($this->any())
+ ->method('getQtyRefunded')
+ ->willReturn(0);
+ $this->item->expects($this->any())
+ ->method('getQtyInvoiced')
+ ->willReturn(1);
+
+ $this->assertFalse($this->order->canCancel());
+ }
+
+ /**
+ * @return void
+ */
+ public function testCanCancelAllRefunded()
+ {
+ $collectionMock = $this->createPartialMock(
+ \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
+ ['getItems', 'setOrderFilter']
+ );
+ $this->orderItemCollectionFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($collectionMock);
+ $collectionMock->expects($this->any())
+ ->method('setOrderFilter')
+ ->willReturnSelf();
+
+ $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
+ $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
+
+ $this->item->expects($this->any())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $this->item->expects($this->once())
+ ->method('getQtyRefunded')
+ ->willReturn(10);
+ $this->item->expects($this->once())
+ ->method('getQtyInvoiced')
+ ->willReturn(10);
+
+ $this->assertTrue($this->order->canCancel());
+ }
+
+ /**
+ * Test that order can be canceled if some items were partially invoiced with certain qty
+ * and then refunded for this qty.
+ * Sample:
+ * - ordered qty = 20
+ * - invoiced = 10
+ * - refunded = 10
+ */
+ public function testCanCancelPartiallyInvoicedAndRefunded()
+ {
+ $collectionMock = $this->createPartialMock(
+ \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
+ ['getItems', 'setOrderFilter']
+ );
+ $this->orderItemCollectionFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($collectionMock);
+ $collectionMock->expects($this->any())
+ ->method('setOrderFilter')
+ ->willReturnSelf();
+
+ $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
+ $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
+
+ $this->item->expects($this->any())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $this->item->expects($this->once())
+ ->method('getQtyToInvoice')
+ ->willReturn(10);
+ $this->item->expects($this->any())
+ ->method('getQtyRefunded')
+ ->willReturn(10);
+ $this->item->expects($this->any())
+ ->method('getQtyInvoiced')
+ ->willReturn(10);
+
+ $this->assertTrue($this->order->canCancel());
+ }
+
+ /**
+ * Test that order CAN NOT be canceled if some items were partially invoiced with certain qty
+ * and then refunded for less than that qty.
+ * Sample:
+ * - ordered qty = 10
+ * - invoiced = 10
+ * - refunded = 5
+ */
+ public function testCanCancelPartiallyInvoicedAndNotFullyRefunded()
+ {
+ $collectionMock = $this->createPartialMock(
+ \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
+ ['getItems', 'setOrderFilter']
+ );
+ $this->orderItemCollectionFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($collectionMock);
+ $collectionMock->expects($this->any())
+ ->method('setOrderFilter')
+ ->willReturnSelf();
+
+ $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
+ $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
+
+ $this->item->expects($this->any())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $this->item->expects($this->any())
+ ->method('getQtyToInvoice')
+ ->willReturn(0);
+ $this->item->expects($this->any())
+ ->method('getQtyRefunded')
+ ->willReturn(5);
+ $this->item->expects($this->any())
+ ->method('getQtyInvoiced')
+ ->willReturn(10);
$this->assertFalse($this->order->canCancel());
}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Shipment/RelationTest.php b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Shipment/RelationTest.php
index a7a615fb0f508..9eee4b809ba0e 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Shipment/RelationTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Shipment/RelationTest.php
@@ -3,145 +3,125 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
namespace Magento\Sales\Test\Unit\Model\ResourceModel\Order\Shipment;
+use Magento\Sales\Model\Order\Shipment;
+use Magento\Sales\Model\Order\Shipment\Comment as CommentEntity;
+use Magento\Sales\Model\Order\Shipment\Item as ItemEntity;
+use Magento\Sales\Model\Order\Shipment\Track as TrackEntity;
+use Magento\Sales\Model\ResourceModel\Order\Shipment\Comment;
+use Magento\Sales\Model\ResourceModel\Order\Shipment\Item;
+use Magento\Sales\Model\ResourceModel\Order\Shipment\Relation;
+use Magento\Sales\Model\ResourceModel\Order\Shipment\Track;
+use PHPUnit\Framework\MockObject\MockObject;
+
/**
* Class RelationTest
*/
class RelationTest extends \PHPUnit\Framework\TestCase
{
/**
- * @var \Magento\Sales\Model\ResourceModel\Order\Shipment\Relation
+ * @var Relation
*/
- protected $relationProcessor;
+ private $relationProcessor;
/**
- * @var \Magento\Sales\Model\ResourceModel\Order\Shipment\Item|\PHPUnit_Framework_MockObject_MockObject
+ * @var Item|MockObject
*/
- protected $itemResourceMock;
+ private $itemResource;
/**
- * @var \Magento\Sales\Model\ResourceModel\Order\Shipment\Track|\PHPUnit_Framework_MockObject_MockObject
+ * @var Track|MockObject
*/
- protected $trackResourceMock;
+ private $trackResource;
/**
- * @var \Magento\Sales\Model\ResourceModel\Order\Shipment\Comment|\PHPUnit_Framework_MockObject_MockObject
+ * @var Comment|MockObject
*/
- protected $commentResourceMock;
+ private $commentResource;
/**
- * @var \Magento\Sales\Model\Order\Shipment\Comment|\PHPUnit_Framework_MockObject_MockObject
+ * @var CommentEntity|MockObject
*/
- protected $commentMock;
+ private $comment;
/**
- * @var \Magento\Sales\Model\Order\Shipment\Track|\PHPUnit_Framework_MockObject_MockObject
+ * @var TrackEntity|MockObject
*/
- protected $trackMock;
+ private $track;
/**
- * @var \Magento\Sales\Model\Order\Shipment|\PHPUnit_Framework_MockObject_MockObject
+ * @var Shipment|MockObject
*/
- protected $shipmentMock;
+ private $shipment;
/**
- * @var \Magento\Sales\Model\Order\Shipment\Item|\PHPUnit_Framework_MockObject_MockObject
+ * @var ItemEntity|MockObject
*/
- protected $itemMock;
+ private $item;
+ /**
+ * @inheritdoc
+ */
protected function setUp()
{
- $this->itemResourceMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Shipment\Item::class)
+ $this->itemResource = $this->getMockBuilder(Item::class)
->disableOriginalConstructor()
- ->setMethods(
- [
- 'save'
- ]
- )
->getMock();
- $this->commentResourceMock = $this->getMockBuilder(
- \Magento\Sales\Model\ResourceModel\Order\Shipment\Comment::class
- )
+ $this->commentResource = $this->getMockBuilder(Comment::class)
->disableOriginalConstructor()
- ->setMethods(
- [
- 'save'
- ]
- )
->getMock();
- $this->trackResourceMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Shipment\Track::class)
+ $this->trackResource = $this->getMockBuilder(Track::class)
->disableOriginalConstructor()
- ->setMethods(
- [
- 'save'
- ]
- )
->getMock();
- $this->shipmentMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Shipment::class)
+ $this->shipment = $this->getMockBuilder(Shipment::class)
->disableOriginalConstructor()
- ->setMethods(
- [
- 'getId',
- 'getItems',
- 'getTracks',
- 'getComments',
- 'getTracksCollection',
- ]
- )
->getMock();
- $this->itemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ $this->item = $this->getMockBuilder(ItemEntity::class)
->disableOriginalConstructor()
- ->setMethods(
- [
- 'setParentId'
- ]
- )
->getMock();
- $this->trackMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Shipment\Track::class)
+ $this->track = $this->getMockBuilder(TrackEntity::class)
->disableOriginalConstructor()
->getMock();
- $this->commentMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Shipment::class)
+ $this->comment = $this->getMockBuilder(Shipment::class)
->disableOriginalConstructor()
->getMock();
- $this->relationProcessor = new \Magento\Sales\Model\ResourceModel\Order\Shipment\Relation(
- $this->itemResourceMock,
- $this->trackResourceMock,
- $this->commentResourceMock
+ $this->relationProcessor = new Relation(
+ $this->itemResource,
+ $this->trackResource,
+ $this->commentResource
);
}
+ /**
+ * Checks saving shipment relations.
+ *
+ * @throws \Exception
+ */
public function testProcessRelations()
{
- $this->shipmentMock->expects($this->exactly(3))
- ->method('getId')
+ $this->shipment->method('getId')
->willReturn('shipment-id-value');
- $this->shipmentMock->expects($this->exactly(2))
- ->method('getItems')
- ->willReturn([$this->itemMock]);
- $this->shipmentMock->expects($this->exactly(2))
- ->method('getComments')
- ->willReturn([$this->commentMock]);
- $this->shipmentMock->expects($this->exactly(2))
- ->method('getTracksCollection')
- ->willReturn([$this->trackMock]);
- $this->itemMock->expects($this->once())
- ->method('setParentId')
+ $this->shipment->method('getItems')
+ ->willReturn([$this->item]);
+ $this->shipment->method('getComments')
+ ->willReturn([$this->comment]);
+ $this->shipment->method('getTracks')
+ ->willReturn([$this->track]);
+ $this->item->method('setParentId')
->with('shipment-id-value')
->willReturnSelf();
- $this->itemResourceMock->expects($this->once())
- ->method('save')
- ->with($this->itemMock)
+ $this->itemResource->method('save')
+ ->with($this->item)
->willReturnSelf();
- $this->commentResourceMock->expects($this->once())
- ->method('save')
- ->with($this->commentMock)
+ $this->commentResource->method('save')
+ ->with($this->comment)
->willReturnSelf();
- $this->trackResourceMock->expects($this->once())
- ->method('save')
- ->with($this->trackMock)
+ $this->trackResource->method('save')
+ ->with($this->track)
->willReturnSelf();
- $this->relationProcessor->processRelation($this->shipmentMock);
+ $this->relationProcessor->processRelation($this->shipment);
}
}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php
index 2e668f0b0d6f1..68681c6c5a66b 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php
@@ -3,10 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Sales\Test\Unit\Model\Service;
use Magento\Sales\Model\Order;
+use Magento\Sales\Api\Data\CreditmemoInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
/**
* Class CreditmemoServiceTest
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -14,34 +19,34 @@
class CreditmemoServiceTest extends \PHPUnit\Framework\TestCase
{
/**
- * @var \Magento\Sales\Api\CreditmemoRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Sales\Api\CreditmemoRepositoryInterface|MockObject
*/
protected $creditmemoRepositoryMock;
/**
- * @var \Magento\Sales\Api\CreditmemoCommentRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Sales\Api\CreditmemoCommentRepositoryInterface|MockObject
*/
protected $creditmemoCommentRepositoryMock;
/**
- * @var \Magento\Framework\Api\SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\Api\SearchCriteriaBuilder|MockObject
*/
protected $searchCriteriaBuilderMock;
/**
- * @var \Magento\Framework\Api\FilterBuilder|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\Api\FilterBuilder|MockObject
*/
protected $filterBuilderMock;
/**
- * @var \Magento\Sales\Model\Order\CreditmemoNotifier|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Sales\Model\Order\CreditmemoNotifier|MockObject
*/
protected $creditmemoNotifierMock;
/**
- * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\Pricing\PriceCurrencyInterface|MockObject
*/
- private $priceCurrencyMock;
+ private $priceCurrency;
/**
* @var \Magento\Sales\Model\Service\CreditmemoService
@@ -79,7 +84,7 @@ protected function setUp()
['setField', 'setValue', 'setConditionType', 'create']
);
$this->creditmemoNotifierMock = $this->createMock(\Magento\Sales\Model\Order\CreditmemoNotifier::class);
- $this->priceCurrencyMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
+ $this->priceCurrency = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
->getMockForAbstractClass();
$this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
@@ -91,7 +96,7 @@ protected function setUp()
'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
'filterBuilder' => $this->filterBuilderMock,
'creditmemoNotifier' => $this->creditmemoNotifierMock,
- 'priceCurrency' => $this->priceCurrencyMock,
+ 'priceCurrency' => $this->priceCurrency,
]
);
}
@@ -187,7 +192,7 @@ public function testRefund()
$orderMock->expects($this->once())->method('getBaseTotalPaid')->willReturn(10);
$creditMemoMock->expects($this->once())->method('getBaseGrandTotal')->willReturn(10);
- $this->priceCurrencyMock->expects($this->any())
+ $this->priceCurrency->expects($this->any())
->method('round')
->willReturnArgument(0);
@@ -259,7 +264,7 @@ public function testRefundPendingCreditMemo()
$orderMock->expects($this->once())->method('getBaseTotalPaid')->willReturn(10);
$creditMemoMock->expects($this->once())->method('getBaseGrandTotal')->willReturn(10);
- $this->priceCurrencyMock->expects($this->any())
+ $this->priceCurrency->expects($this->any())
->method('round')
->willReturnArgument(0);
@@ -324,27 +329,32 @@ public function testRefundExpectsMoneyAvailableToReturn()
$baseGrandTotal = 10;
$baseTotalRefunded = 9;
$baseTotalPaid = 10;
- $creditMemoMock = $this->getMockBuilder(\Magento\Sales\Api\Data\CreditmemoInterface::class)
- ->setMethods(['getId', 'getOrder', 'formatBasePrice'])
+ /** @var CreditmemoInterface|MockObject $creditMemo */
+ $creditMemo = $this->getMockBuilder(CreditmemoInterface::class)
+ ->setMethods(['getId', 'getOrder'])
->getMockForAbstractClass();
- $creditMemoMock->expects($this->once())->method('getId')->willReturn(null);
- $orderMock = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock();
- $creditMemoMock->expects($this->atLeastOnce())->method('getOrder')->willReturn($orderMock);
- $creditMemoMock->expects($this->once())->method('getBaseGrandTotal')->willReturn($baseGrandTotal);
- $orderMock->expects($this->atLeastOnce())->method('getBaseTotalRefunded')->willReturn($baseTotalRefunded);
- $this->priceCurrencyMock->expects($this->exactly(2))->method('round')->withConsecutive(
- [$baseTotalRefunded + $baseGrandTotal],
- [$baseTotalPaid]
- )->willReturnOnConsecutiveCalls(
- $baseTotalRefunded + $baseGrandTotal,
- $baseTotalPaid
- );
- $orderMock->expects($this->atLeastOnce())->method('getBaseTotalPaid')->willReturn($baseTotalPaid);
+ $creditMemo->method('getId')
+ ->willReturn(null);
+ /** @var Order|MockObject $order */
+ $order = $this->getMockBuilder(Order::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $creditMemo->method('getOrder')
+ ->willReturn($order);
+ $creditMemo->method('getBaseGrandTotal')
+ ->willReturn($baseGrandTotal);
+ $order->method('getBaseTotalRefunded')
+ ->willReturn($baseTotalRefunded);
+ $this->priceCurrency->method('round')
+ ->withConsecutive([$baseTotalRefunded + $baseGrandTotal], [$baseTotalPaid])
+ ->willReturnOnConsecutiveCalls($baseTotalRefunded + $baseGrandTotal, $baseTotalPaid);
+ $order->method('getBaseTotalPaid')
+ ->willReturn($baseTotalPaid);
$baseAvailableRefund = $baseTotalPaid - $baseTotalRefunded;
- $orderMock->expects($this->once())->method('formatBasePrice')->with(
- $baseAvailableRefund
- )->willReturn($baseAvailableRefund);
- $this->creditmemoService->refund($creditMemoMock, true);
+ $order->method('formatPriceTxt')
+ ->with($baseAvailableRefund)
+ ->willReturn($baseAvailableRefund);
+ $this->creditmemoService->refund($creditMemo, true);
}
/**
diff --git a/app/code/Magento/Sales/Test/Unit/Observer/AssignOrderToCustomerObserverTest.php b/app/code/Magento/Sales/Test/Unit/Observer/AssignOrderToCustomerObserverTest.php
new file mode 100644
index 0000000000000..c6e02151b9bc1
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/Observer/AssignOrderToCustomerObserverTest.php
@@ -0,0 +1,91 @@
+orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->sut = new AssignOrderToCustomerObserver($this->orderRepositoryMock);
+ }
+
+ /**
+ * Test assigning order to customer after issuing guest order
+ *
+ * @dataProvider getCustomerIds
+ * @param null|int $customerId
+ * @return void
+ */
+ public function testAssignOrderToCustomerAfterGuestOrder($customerId)
+ {
+ $orderId = 1;
+ /** @var Observer|PHPUnit_Framework_MockObject_MockObject $observerMock */
+ $observerMock = $this->createMock(Observer::class);
+ /** @var Event|PHPUnit_Framework_MockObject_MockObject $eventMock */
+ $eventMock = $this->getMockBuilder(Event::class)->disableOriginalConstructor()
+ ->setMethods(['getData'])
+ ->getMock();
+ /** @var CustomerInterface|PHPUnit_Framework_MockObject_MockObject $customerMock */
+ $customerMock = $this->createMock(CustomerInterface::class);
+ /** @var OrderInterface|PHPUnit_Framework_MockObject_MockObject $orderMock */
+ $orderMock = $this->getMockBuilder(OrderInterface::class)
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $observerMock->expects($this->once())->method('getEvent')->willReturn($eventMock);
+ $eventMock->expects($this->any())->method('getData')
+ ->willReturnMap([
+ ['delegate_data', null, ['__sales_assign_order_id' => $orderId]],
+ ['customer_data_object', null, $customerMock]
+ ]);
+ $orderMock->expects($this->once())->method('getCustomerId')->willReturn($customerId);
+ $this->orderRepositoryMock->expects($this->once())->method('get')->with($orderId)
+ ->willReturn($orderMock);
+ if (!$customerId) {
+ $this->orderRepositoryMock->expects($this->once())->method('save')->with($orderMock);
+ $this->sut->execute($observerMock);
+ return ;
+ }
+
+ $this->orderRepositoryMock->expects($this->never())->method('save')->with($orderMock);
+ $this->sut->execute($observerMock);
+ }
+
+ /**
+ * Customer id assigned to order
+ *
+ * @return array
+ */
+ public function getCustomerIds()
+ {
+ return [[null, 1]];
+ }
+}
diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json
index a0e40d283da68..ed5f939d81869 100644
--- a/app/code/Magento/Sales/composer.json
+++ b/app/code/Magento/Sales/composer.json
@@ -33,7 +33,7 @@
"magento/module-sales-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "101.0.5",
+ "version": "101.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Sales/etc/adminhtml/system.xml b/app/code/Magento/Sales/etc/adminhtml/system.xml
index 157420b3d0c73..1b2f8b88d7dc3 100644
--- a/app/code/Magento/Sales/etc/adminhtml/system.xml
+++ b/app/code/Magento/Sales/etc/adminhtml/system.xml
@@ -48,6 +48,13 @@
Magento\Config\Model\Config\Source\Yesno
+
+
+
+
+ Magento\Config\Model\Config\Source\Yesno
+
+
diff --git a/app/code/Magento/Sales/etc/config.xml b/app/code/Magento/Sales/etc/config.xml
index d4d10bfa6dcce..5be06fa3836a7 100644
--- a/app/code/Magento/Sales/etc/config.xml
+++ b/app/code/Magento/Sales/etc/config.xml
@@ -18,6 +18,9 @@
1
+
+ 1
+
1
diff --git a/app/code/Magento/Sales/etc/module.xml b/app/code/Magento/Sales/etc/module.xml
index 3a82dd64a7949..0fd2124785ba7 100644
--- a/app/code/Magento/Sales/etc/module.xml
+++ b/app/code/Magento/Sales/etc/module.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml
index fdbaae2347398..170fea937348d 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml
@@ -47,17 +47,15 @@
-
-
- = /* @escapeNotVerified */ __('Payment & Shipping Information') ?>
+
+
+ = $block->getChildHtml('shipping_method') ?>
-
-
- = $block->getChildHtml('billing_method') ?>
-
-
- = $block->getChildHtml('shipping_method') ?>
-
+
+
+
+
+ = $block->getChildHtml('billing_method') ?>
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml
index 9e0394f6430bd..65d3a612e5133 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml
@@ -100,12 +100,8 @@ require(['prototype'], function(){
diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
index 259ca2165e647..05449c478152f 100644
--- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
+++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
@@ -4,14 +4,17 @@
*/
define([
- "jquery",
+ 'jquery',
'Magento_Ui/js/modal/confirm',
'Magento_Ui/js/modal/alert',
- "mage/translate",
- "prototype",
- "Magento_Catalog/catalog/product/composite/configure",
+ 'mage/template',
+ 'text!Magento_Sales/templates/order/create/shipping/reload.html',
+ 'text!Magento_Sales/templates/order/create/payment/reload.html',
+ 'mage/translate',
+ 'prototype',
+ 'Magento_Catalog/catalog/product/composite/configure',
'Magento_Ui/js/lib/view/utils/async'
-], function(jQuery, confirm, alert){
+], function(jQuery, confirm, alert, template, shippingTemplate, paymentTemplate){
window.AdminOrder = new Class.create();
@@ -29,7 +32,7 @@ define([
this.gridProducts = $H({});
this.gridProductsGift = $H({});
this.billingAddressContainer = '';
- this.shippingAddressContainer= '';
+ this.shippingAddressContainer = '';
this.isShippingMethodReseted = data.shipping_method_reseted ? data.shipping_method_reseted : false;
this.overlayData = $H({});
this.giftMessageDataChanged = false;
@@ -40,6 +43,19 @@ define([
this.excludedPaymentMethods = [];
this.summarizePrice = true;
this.timerId = null;
+ this.shippingTemplate = template(shippingTemplate, {
+ data: {
+ title: jQuery.mage.__('Shipping Method'),
+ linkText: jQuery.mage.__('Get shipping methods and rates')
+ }
+ });
+ this.paymentTemplate = template(paymentTemplate, {
+ data: {
+ title: jQuery.mage.__('Payment Method'),
+ linkText: jQuery.mage.__('Get available payment methods')
+ }
+ });
+
jQuery.async('#order-items', (function(){
this.dataArea = new OrderFormArea('data', $(this.getAreaId('data')), this);
this.itemsArea = Object.extend(new OrderFormArea('items', $(this.getAreaId('items')), this), {
@@ -168,10 +184,11 @@ define([
var data = this.serializeData(container);
data[el.name] = id;
- if(this.isShippingField(container) && !this.isShippingMethodReseted){
+
+ this.resetPaymentMethod();
+ if (this.isShippingField(container) && !this.isShippingMethodReseted) {
this.resetShippingMethod(data);
- }
- else{
+ } else{
this.saveData(data);
}
},
@@ -239,13 +256,14 @@ define([
}
data['order[' + type + '_address][customer_address_id]'] = null;
- data['shipping_as_billing'] = jQuery('[name="shipping_same_as_billing"]').is(':checked') ? 1 : 0;
+ data['shipping_as_billing'] = +this.isShippingAsBilling();
if (name === 'customer_address_id') {
data['order[' + type + '_address][customer_address_id]'] =
$('order-' + type + '_address_customer_address_id').value;
}
+ this.resetPaymentMethod();
if (data['reset_shipping']) {
this.resetShippingMethod(data);
} else {
@@ -348,30 +366,69 @@ define([
this.loadArea(areasToLoad, true, data);
},
- resetShippingMethod : function(data){
- var areasToLoad = ['billing_method', 'shipping_address', 'totals', 'giftmessage', 'items'];
- if(!this.isOnlyVirtualProduct) {
- areasToLoad.push('shipping_method');
- areasToLoad.push('shipping_address');
+ /**
+ * Checks if shipping address is corresponds to billing address.
+ *
+ * @return {Boolean}
+ */
+ isShippingAsBilling: function () {
+ return jQuery('[name="shipping_same_as_billing"]').is(':checked');
+ },
+
+ resetShippingMethod: function() {
+ if (!this.isOnlyVirtualProduct) {
+ $(this.getAreaId('shipping_method')).update(this.shippingTemplate);
}
+ },
- data['reset_shipping'] = 1;
- this.isShippingMethodReseted = true;
- this.loadArea(areasToLoad, true, data);
+ resetPaymentMethod: function() {
+ $(this.getAreaId('billing_method')).update(this.paymentTemplate);
},
- loadShippingRates : function(){
+ /**
+ * Loads shipping options according to address data.
+ *
+ * @return {Boolean}
+ */
+ loadShippingRates: function () {
+ var addressContainer = this.isShippingAsBilling() ?
+ 'billingAddressContainer' :
+ 'shippingAddressContainer',
+ data = this.serializeData(this[addressContainer]).toObject();
+
+ data['collect_shipping_rates'] = 1;
this.isShippingMethodReseted = false;
- this.loadArea(['shipping_method', 'totals'], true, {collect_shipping_rates: 1});
+ this.loadArea(['shipping_method', 'totals'], true, data);
+
+ return false;
},
- setShippingMethod : function(method){
+ setShippingMethod: function(method) {
var data = {};
+
data['order[shipping_method]'] = method;
- this.loadArea(['shipping_method', 'totals', 'billing_method'], true, data);
+ this.loadArea([
+ 'shipping_method',
+ 'totals',
+ 'billing_method'
+ ], true, data);
},
- switchPaymentMethod : function(method){
+ /**
+ * Updates available payment
+ * methods list according to order data.
+ *
+ * @return boolean
+ */
+ loadPaymentMethods: function() {
+ var data = this.serializeData(this.billingAddressContainer).toObject();
+
+ this.loadArea(['billing_method','totals'], true, data);
+
+ return false;
+ },
+
+ switchPaymentMethod: function(method){
jQuery('#edit_form')
.off('submitOrder')
.on('submitOrder', function(){
@@ -1149,9 +1206,15 @@ define([
|| this.excludedPaymentMethods.indexOf(this.paymentMethod) == -1);
},
- serializeData : function(container){
- var fields = $(container).select('input', 'select', 'textarea');
- var data = Form.serializeElements(fields, true);
+ /**
+ * Serializes container form elements data.
+ *
+ * @param {String} container
+ * @return {Object}
+ */
+ serializeData: function (container) {
+ var fields = $(container).select('input', 'select', 'textarea'),
+ data = Form.serializeElements(fields, true);
return $H(data);
},
diff --git a/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/payment/reload.html b/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/payment/reload.html
new file mode 100644
index 0000000000000..c503f3c678ab6
--- /dev/null
+++ b/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/payment/reload.html
@@ -0,0 +1,18 @@
+
+
+
+ <%- data.title %>
+
+
diff --git a/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/shipping/reload.html b/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/shipping/reload.html
new file mode 100644
index 0000000000000..6b191ee81a45a
--- /dev/null
+++ b/app/code/Magento/Sales/view/adminhtml/web/templates/order/create/shipping/reload.html
@@ -0,0 +1,19 @@
+
+
+
+ <%- data.title %>
+
+
diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html
index 3a4aab19e9e7c..a6a10fb49e3f5 100644
--- a/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html
+++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html
@@ -11,7 +11,7 @@
"var this.getUrl($store, 'customer/account/')":"Customer Account URL",
"var order.getCustomerName()":"Customer Name",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -24,7 +24,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
{{trans 'You can check the status of your order by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html
index bc7c079d7f21b..b7411d80d2ba6 100644
--- a/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html
+++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html
@@ -10,7 +10,7 @@
"var creditmemo.increment_id":"Credit Memo Id",
"var billing.getName()":"Guest Customer Name",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -23,7 +23,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_update.html b/app/code/Magento/Sales/view/frontend/email/invoice_update.html
index cafdd65ff5208..4043e59f9d7d6 100644
--- a/app/code/Magento/Sales/view/frontend/email/invoice_update.html
+++ b/app/code/Magento/Sales/view/frontend/email/invoice_update.html
@@ -11,7 +11,7 @@
"var comment":"Invoice Comment",
"var invoice.increment_id":"Invoice Id",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -24,7 +24,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
{{trans 'You can check the status of your order by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html b/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html
index fafb533301efb..40cdec7fb4cab 100644
--- a/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html
+++ b/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html
@@ -10,7 +10,7 @@
"var comment":"Invoice Comment",
"var invoice.increment_id":"Invoice Id",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -23,7 +23,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/order_update.html b/app/code/Magento/Sales/view/frontend/email/order_update.html
index a709a9ed8a7f1..a8f0068b70e87 100644
--- a/app/code/Magento/Sales/view/frontend/email/order_update.html
+++ b/app/code/Magento/Sales/view/frontend/email/order_update.html
@@ -10,7 +10,7 @@
"var order.getCustomerName()":"Customer Name",
"var comment":"Order Comment",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -23,7 +23,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
{{trans 'You can check the status of your order by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/order_update_guest.html b/app/code/Magento/Sales/view/frontend/email/order_update_guest.html
index 5a39b01810c18..749fa3b60ad59 100644
--- a/app/code/Magento/Sales/view/frontend/email/order_update_guest.html
+++ b/app/code/Magento/Sales/view/frontend/email/order_update_guest.html
@@ -9,7 +9,7 @@
"var billing.getName()":"Guest Customer Name",
"var comment":"Order Comment",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status"
+"var order.getFrontendStatusLabel()":"Order Status"
} @-->
{{template config_path="design/email/header_template"}}
@@ -22,7 +22,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_update.html b/app/code/Magento/Sales/view/frontend/email/shipment_update.html
index 6d9efc37004bc..9d1c93287549a 100644
--- a/app/code/Magento/Sales/view/frontend/email/shipment_update.html
+++ b/app/code/Magento/Sales/view/frontend/email/shipment_update.html
@@ -10,7 +10,7 @@
"var order.getCustomerName()":"Customer Name",
"var comment":"Order Comment",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status",
+"var order.getFrontendStatusLabel()":"Order Status",
"var shipment.increment_id":"Shipment Id"
} @-->
{{template config_path="design/email/header_template"}}
@@ -24,7 +24,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
{{trans 'You can check the status of your order by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}}
diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html b/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html
index 4896a00b7bc5a..0d2dccd3377d2 100644
--- a/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html
+++ b/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html
@@ -9,7 +9,7 @@
"var billing.getName()":"Guest Customer Name",
"var comment":"Order Comment",
"var order.increment_id":"Order Id",
-"var order.getStatusLabel()":"Order Status",
+"var order.getFrontendStatusLabel()":"Order Status",
"var shipment.increment_id":"Shipment Id"
} @-->
{{template config_path="design/email/header_template"}}
@@ -23,7 +23,7 @@
"Your order #%increment_id has been updated with a status of %order_status."
increment_id=$order.increment_id
- order_status=$order.getStatusLabel()
+ order_status=$order.getFrontendStatusLabel()
|raw}}
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
index e43d32760febb..dc179b6ee4ac1 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
@@ -29,9 +29,10 @@
|