diff --git a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php
index d3c84e69c9540..e296c8d3b8978 100644
--- a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php
+++ b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php
@@ -58,22 +58,38 @@ public function build(Filter $filter): string
$conditionValue = $this->mapConditionValue($conditionType, $filter->getValue());
// NOTE: store scope was ignored intentionally to perform search across all stores
- $attributeSelect = $this->resourceConnection->getConnection()
- ->select()
- ->from(
- [$tableAlias => $attribute->getBackendTable()],
- $tableAlias . '.' . $attribute->getEntityIdField()
- )->where(
- $this->resourceConnection->getConnection()->prepareSqlCondition(
- $tableAlias . '.' . $attribute->getIdFieldName(),
- ['eq' => $attribute->getAttributeId()]
- )
- )->where(
- $this->resourceConnection->getConnection()->prepareSqlCondition(
- $tableAlias . '.value',
- [$conditionType => $conditionValue]
- )
- );
+ if ($conditionType == 'is_null') {
+ $entityResourceModel = $attribute->getEntity();
+ $attributeSelect = $this->resourceConnection->getConnection()
+ ->select()
+ ->from(
+ [Collection::MAIN_TABLE_ALIAS => $entityResourceModel->getEntityTable()],
+ Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getEntityIdField()
+ )->joinLeft(
+ [$tableAlias => $attribute->getBackendTable()],
+ $tableAlias . '.' . $attribute->getEntityIdField() . '=' . Collection::MAIN_TABLE_ALIAS .
+ '.' . $entityResourceModel->getEntityIdField() . ' AND ' . $tableAlias . '.' .
+ $attribute->getIdFieldName() . '=' . $attribute->getAttributeId(),
+ ''
+ )->where($tableAlias . '.value is null');
+ } else {
+ $attributeSelect = $this->resourceConnection->getConnection()
+ ->select()
+ ->from(
+ [$tableAlias => $attribute->getBackendTable()],
+ $tableAlias . '.' . $attribute->getEntityIdField()
+ )->where(
+ $this->resourceConnection->getConnection()->prepareSqlCondition(
+ $tableAlias . '.' . $attribute->getIdFieldName(),
+ ['eq' => $attribute->getAttributeId()]
+ )
+ )->where(
+ $this->resourceConnection->getConnection()->prepareSqlCondition(
+ $tableAlias . '.value',
+ [$conditionType => $conditionValue]
+ )
+ );
+ }
return $this->resourceConnection
->getConnection()
@@ -86,6 +102,8 @@ public function build(Filter $filter): string
}
/**
+ * Get attribute entity by its code
+ *
* @param string $field
* @return Attribute
* @throws \Magento\Framework\Exception\LocalizedException
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php b/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php
index 2bb10d3b31a24..893000544a728 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php
@@ -113,27 +113,28 @@ private function customizeAttributeCode($meta)
*/
private function customizeFrontendLabels($meta)
{
+ $labelConfigs = [];
+
foreach ($this->storeRepository->getList() as $store) {
$storeId = $store->getId();
if (!$storeId) {
continue;
}
-
- $meta['manage-titles']['children'] = [
- 'frontend_label[' . $storeId . ']' => $this->arrayManager->set(
- 'arguments/data/config',
- [],
- [
- 'formElement' => Input::NAME,
- 'componentType' => Field::NAME,
- 'label' => $store->getName(),
- 'dataType' => Text::NAME,
- 'dataScope' => 'frontend_label[' . $storeId . ']'
- ]
- ),
- ];
+ $labelConfigs['frontend_label[' . $storeId . ']'] = $this->arrayManager->set(
+ 'arguments/data/config',
+ [],
+ [
+ 'formElement' => Input::NAME,
+ 'componentType' => Field::NAME,
+ 'label' => $store->getName(),
+ 'dataType' => Text::NAME,
+ 'dataScope' => 'frontend_label[' . $storeId . ']'
+ ]
+ );
}
+ $meta['manage-titles']['children'] = $labelConfigs;
+
return $meta;
}
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
index 707ebbb2964cc..23f612582f42e 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
@@ -236,6 +236,8 @@ public function afterSave()
) {
$this->_indexerEavProcessor->markIndexerAsInvalid();
}
+
+ $this->_source = null;
return parent::afterSave();
}
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml
index 0d82ba3817df9..0082b376bc4a6 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml
@@ -30,6 +30,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckProductsOrderActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckProductsOrderActionGroup.xml
new file mode 100644
index 0000000000000..f7cd2e7076288
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckProductsOrderActionGroup.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
index 03a004e500aef..bf0762b4b0319 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
@@ -115,6 +115,27 @@
true
ProductAttributeFrontendLabel
+
+ attribute
+ boolean
+ global
+ false
+ false
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ ProductAttributeFrontendLabel
+
attribute
text
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
index 6d0d953e44676..d136661e917cb 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
@@ -149,6 +149,15 @@
EavStockItem
CustomAttributeProductAttribute
+
+ 50
+
+
+ 60
+
+
+ 70
+
api-simple-product-two
simple
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml
index 0a1804aa284dc..697648cedb7ba 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml
@@ -20,6 +20,7 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAttributeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAttributeSection.xml
new file mode 100644
index 0000000000000..e159a4ce5c0b6
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAttributeSection.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml
index 337a3dd53f593..3f67e4b087cc4 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml
@@ -189,4 +189,9 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
index 178e58ef2d649..f35eb63ee0e0a 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
@@ -16,6 +16,7 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
index 6a4ac0d7683c7..4114b199715cb 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
@@ -31,6 +31,8 @@
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml
new file mode 100644
index 0000000000000..282331924bca3
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php b/app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php
index 6d343fe149d21..fabe504fbe31c 100644
--- a/app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php
+++ b/app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php
@@ -71,6 +71,8 @@ public function mapConditionsToSearchCriteria(CombinedCondition $conditions): Se
}
/**
+ * Convert condition to filter group
+ *
* @param ConditionInterface $condition
* @return null|\Magento\Framework\Api\CombinedFilterGroup|\Magento\Framework\Api\Filter
* @throws InputException
@@ -89,6 +91,8 @@ private function mapConditionToFilterGroup(ConditionInterface $condition)
}
/**
+ * Convert combined condition to filter group
+ *
* @param Combine $combinedCondition
* @return null|\Magento\Framework\Api\CombinedFilterGroup
* @throws InputException
@@ -121,6 +125,8 @@ private function mapCombinedConditionToFilterGroup(CombinedCondition $combinedCo
}
/**
+ * Convert simple condition to filter group
+ *
* @param ConditionInterface $productCondition
* @return FilterGroup|Filter
* @throws InputException
@@ -139,6 +145,8 @@ private function mapSimpleConditionToFilterGroup(ConditionInterface $productCond
}
/**
+ * Convert simple condition with array value to filter group
+ *
* @param ConditionInterface $productCondition
* @return FilterGroup
* @throws InputException
@@ -161,6 +169,8 @@ private function processSimpleConditionWithArrayValue(ConditionInterface $produc
}
/**
+ * Get glue for multiple values by operator
+ *
* @param string $operator
* @return string
*/
@@ -211,6 +221,8 @@ private function reverseSqlOperatorInFilter(Filter $filter)
}
/**
+ * Convert filters array into combined filter group
+ *
* @param array $filters
* @param string $combinationMode
* @return FilterGroup
@@ -227,6 +239,8 @@ private function createCombinedFilterGroup(array $filters, string $combinationMo
}
/**
+ * Creating of filter object by filtering params
+ *
* @param string $field
* @param string $value
* @param string $conditionType
@@ -264,6 +278,7 @@ private function mapRuleOperatorToSQLCondition(string $ruleOperator): string
'!{}' => 'nlike', // does not contains
'()' => 'in', // is one of
'!()' => 'nin', // is not one of
+ '<=>' => 'is_null'
];
if (!array_key_exists($ruleOperator, $operatorsMap)) {
diff --git a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
index ab650c94a0f08..0db178b2a0a6d 100644
--- a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
+++ b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
@@ -4,12 +4,11 @@
* See COPYING.txt for license details.
*/
-/**
- * Catalog Rule Product Condition data model
- */
namespace Magento\CatalogRule\Model\Rule\Condition;
/**
+ * Catalog Rule Product Condition data model
+ *
* @method string getAttribute() Returns attribute code
*/
class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
@@ -29,6 +28,9 @@ public function validate(\Magento\Framework\Model\AbstractModel $model)
$oldAttrValue = $model->getData($attrCode);
if ($oldAttrValue === null) {
+ if ($this->getOperator() === '<=>') {
+ return true;
+ }
return false;
}
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml
index fe4042e8a2e9f..b0c4f2d8a609f 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml
@@ -36,6 +36,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -77,4 +112,8 @@
+
+
+
+
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml
index 71bdfe0613bb7..5b75708d1ae0a 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml
@@ -77,4 +77,21 @@
by_percent
96
+
+
+ CatalogPriceRule
+ Catalog Price Rule Description
+ 1
+
+ - 0
+ - 1
+ - 2
+ - 3
+
+
+ - 1
+
+ by_percent
+ 10
+
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml
index 7cfb5bf40be55..635260888e7fb 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml
@@ -41,6 +41,8 @@
+
+
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml
new file mode 100644
index 0000000000000..053a8c33e640c
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ website
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php
index 711d5a2da9ff5..9e47830debfc4 100644
--- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php
+++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php
@@ -197,6 +197,7 @@ public function getCacheKeyInfo()
$this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_GROUP),
(int) $this->getRequest()->getParam($this->getData('page_var_name'), 1),
$this->getProductsPerPage(),
+ $this->getProductsCount(),
$conditions,
$this->json->serialize($this->getRequest()->getParams()),
$this->getTemplate(),
diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php
index dc6e100ab1ad8..a789753795724 100644
--- a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php
+++ b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php
@@ -167,6 +167,7 @@ public function testGetCacheKeyInfo()
'context_group',
1,
5,
+ 10,
'some_serialized_conditions',
json_encode('request_params'),
'test_template',
diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/ClearWidgetsFromCMSContentActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/ClearWidgetsFromCMSContentActionGroup.xml
new file mode 100644
index 0000000000000..2fa1b86a61572
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/ClearWidgetsFromCMSContentActionGroup.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Cms/Test/Mftf/Page/CmsPageEditPage.xml b/app/code/Magento/Cms/Test/Mftf/Page/CmsPageEditPage.xml
new file mode 100644
index 0000000000000..885310d9399ae
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Mftf/Page/CmsPageEditPage.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml
index 8559334238d2f..ff6167ffc10e0 100644
--- a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml
+++ b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection.xml
@@ -31,6 +31,8 @@
+
+
@@ -99,6 +101,7 @@
+
@@ -111,6 +114,7 @@
+
diff --git a/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigWYSIWYGActionGroup.xml b/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigWYSIWYGActionGroup.xml
index 82411faddfed7..eefaf5f3b539c 100644
--- a/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigWYSIWYGActionGroup.xml
+++ b/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigWYSIWYGActionGroup.xml
@@ -38,4 +38,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php
index 2502b79921e99..e07879e93a6b4 100644
--- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php
@@ -15,6 +15,8 @@
use Magento\Framework\Pricing\PriceCurrencyInterface;
/**
+ * Confugurable product view type
+ *
* @api
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @api
@@ -276,6 +278,8 @@ protected function getOptionImages()
}
/**
+ * Collect price options
+ *
* @return array
*/
protected function getOptionPrices()
@@ -314,6 +318,11 @@ protected function getOptionPrices()
),
],
'tierPrices' => $tierPrices,
+ 'msrpPrice' => [
+ 'amount' => $this->localeFormat->getNumber(
+ $product->getMsrp()
+ ),
+ ],
];
}
return $prices;
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
index f98075f2294cc..46f10608bc95e 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
@@ -24,6 +24,7 @@
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
* @api
* @since 100.0.2
*/
@@ -1385,7 +1386,7 @@ function ($item) {
*/
private function getUsedProductsCacheKey($keyParts)
{
- return md5(implode('_', $keyParts));
+ return sha1(implode('_', $keyParts));
}
/**
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php
index 25d8412c91056..c5c2368720b98 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Product/View/Type/ConfigurableTest.php
@@ -379,6 +379,9 @@ private function getExpectedArray($productId, $amount, $priceQty, $percentage):
'percentage' => $percentage,
],
],
+ 'msrpPrice' => [
+ 'amount' => null ,
+ ]
],
],
'priceFormat' => [],
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 1df84d27a5c30..e732960421541 100644
--- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
+++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
@@ -609,6 +609,13 @@ define([
} else {
$(this.options.slyOldPriceSelector).hide();
}
+
+ $(document).trigger('updateMsrpPriceBlock',
+ [
+ optionId,
+ this.options.spConfig.optionPrices
+ ]
+ );
},
/**
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
index 0991b3f9f4b23..56188ab997b76 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
@@ -80,6 +80,8 @@ public function getOptionText($value)
}
/**
+ * Get option id.
+ *
* @param string $value
* @return null|string
*/
diff --git a/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php b/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
index cd2fe7477ca60..7f6dfa2a5e9ab 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
@@ -5,13 +5,19 @@
*/
namespace Magento\Eav\Model\ResourceModel;
+use Magento\Eav\Model\Config;
use Magento\Framework\DataObject;
+use Magento\Framework\DB\Select;
+use Magento\Framework\DB\Sql\UnionExpression;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\EntityManager\Operation\AttributeInterface;
use Magento\Framework\Model\Entity\ScopeInterface;
use Magento\Framework\Model\Entity\ScopeResolver;
use Psr\Log\LoggerInterface;
+/**
+ * EAV read handler
+ */
class ReadHandler implements AttributeInterface
{
/**
@@ -30,23 +36,21 @@ class ReadHandler implements AttributeInterface
private $logger;
/**
- * @var \Magento\Eav\Model\Config
+ * @var Config
*/
private $config;
/**
- * ReadHandler constructor.
- *
* @param MetadataPool $metadataPool
* @param ScopeResolver $scopeResolver
* @param LoggerInterface $logger
- * @param \Magento\Eav\Model\Config $config
+ * @param Config $config
*/
public function __construct(
MetadataPool $metadataPool,
ScopeResolver $scopeResolver,
LoggerInterface $logger,
- \Magento\Eav\Model\Config $config
+ Config $config
) {
$this->metadataPool = $metadataPool;
$this->scopeResolver = $scopeResolver;
@@ -86,6 +90,8 @@ private function getEntityAttributes(string $entityType, DataObject $entity): ar
}
/**
+ * Get context variables
+ *
* @param ScopeInterface $scope
* @return array
*/
@@ -99,6 +105,8 @@ protected function getContextVariables(ScopeInterface $scope)
}
/**
+ * Execute read handler
+ *
* @param string $entityType
* @param array $entityData
* @param array $arguments
@@ -129,33 +137,40 @@ public function execute($entityType, $entityData, $arguments = [])
}
}
if (count($attributeTables)) {
- $attributeTables = array_keys($attributeTables);
- foreach ($attributeTables as $attributeTable) {
+ $identifiers = null;
+ foreach ($attributeTables as $attributeTable => $attributeIds) {
$select = $connection->select()
->from(
['t' => $attributeTable],
['value' => 't.value', 'attribute_id' => 't.attribute_id']
)
- ->where($metadata->getLinkField() . ' = ?', $entityData[$metadata->getLinkField()]);
+ ->where($metadata->getLinkField() . ' = ?', $entityData[$metadata->getLinkField()])
+ ->where('attribute_id IN (?)', $attributeIds);
+ $attributeIdentifiers = [];
foreach ($context as $scope) {
//TODO: if (in table exists context field)
$select->where(
- $metadata->getEntityConnection()->quoteIdentifier($scope->getIdentifier()) . ' IN (?)',
+ $connection->quoteIdentifier($scope->getIdentifier()) . ' IN (?)',
$this->getContextVariables($scope)
- )->order('t.' . $scope->getIdentifier() . ' DESC');
+ );
+ $attributeIdentifiers[] = $scope->getIdentifier();
}
+ $attributeIdentifiers = array_unique($attributeIdentifiers);
+ $identifiers = array_intersect($identifiers ?? $attributeIdentifiers, $attributeIdentifiers);
$selects[] = $select;
}
- $unionSelect = new \Magento\Framework\DB\Sql\UnionExpression(
- $selects,
- \Magento\Framework\DB\Select::SQL_UNION_ALL
- );
- foreach ($connection->fetchAll($unionSelect) as $attributeValue) {
+ $this->applyIdentifierForSelects($selects, $identifiers);
+ $unionSelect = new UnionExpression($selects, Select::SQL_UNION_ALL, '( %s )');
+ $orderedUnionSelect = $connection->select();
+ $orderedUnionSelect->from(['u' => $unionSelect]);
+ $this->applyIdentifierForUnion($orderedUnionSelect, $identifiers);
+ $attributes = $connection->fetchAll($orderedUnionSelect);
+ foreach ($attributes as $attributeValue) {
if (isset($attributesMap[$attributeValue['attribute_id']])) {
$entityData[$attributesMap[$attributeValue['attribute_id']]] = $attributeValue['value'];
} else {
$this->logger->warning(
- "Attempt to load value of nonexistent EAV attribute '{$attributeValue['attribute_id']}'
+ "Attempt to load value of nonexistent EAV attribute '{$attributeValue['attribute_id']}'
for entity type '$entityType'."
);
}
@@ -163,4 +178,32 @@ public function execute($entityType, $entityData, $arguments = [])
}
return $entityData;
}
+
+ /**
+ * Apply identifiers column on select array
+ *
+ * @param Select[] $selects
+ * @param array $identifiers
+ */
+ private function applyIdentifierForSelects(array $selects, array $identifiers)
+ {
+ foreach ($selects as $select) {
+ foreach ($identifiers as $identifier) {
+ $select->columns($identifier, 't');
+ }
+ }
+ }
+
+ /**
+ * Apply identifiers order on union select
+ *
+ * @param Select $unionSelect
+ * @param array $identifiers
+ */
+ private function applyIdentifierForUnion(Select $unionSelect, array $identifiers)
+ {
+ foreach ($identifiers as $identifier) {
+ $unionSelect->order($identifier);
+ }
+ }
}
diff --git a/app/code/Magento/Msrp/Helper/Data.php b/app/code/Magento/Msrp/Helper/Data.php
index b4ec34ebee19c..393383bb2e772 100644
--- a/app/code/Magento/Msrp/Helper/Data.php
+++ b/app/code/Magento/Msrp/Helper/Data.php
@@ -11,6 +11,7 @@
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
/**
* Msrp data helper
@@ -70,8 +71,7 @@ public function __construct(
}
/**
- * Check if can apply Minimum Advertise price to product
- * in specific visibility
+ * Check if can apply Minimum Advertise price to product in specific visibility
*
* @param int|Product $product
* @param int|null $visibility Check displaying price in concrete place (by default generally)
@@ -135,6 +135,8 @@ public function isShowPriceOnGesture($product)
}
/**
+ * Check if we should show MAP proce before order confirmation
+ *
* @param int|Product $product
* @return bool
*/
@@ -144,6 +146,8 @@ public function isShowBeforeOrderConfirm($product)
}
/**
+ * Check if any MAP price is larger than as low as value.
+ *
* @param int|Product $product
* @return bool|float
*/
@@ -155,10 +159,19 @@ public function isMinimalPriceLessMsrp($product)
$msrp = $product->getMsrp();
$price = $product->getPriceInfo()->getPrice(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE);
if ($msrp === null) {
- if ($product->getTypeId() !== \Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE) {
- return false;
- } else {
+ if ($product->getTypeId() === \Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE) {
$msrp = $product->getTypeInstance()->getChildrenMsrp($product);
+ } elseif ($product->getTypeId() === Configurable::TYPE_CODE) {
+ $prices = [];
+ foreach ($product->getTypeInstance()->getUsedProducts($product) as $item) {
+ if ($item->getMsrp() !== null) {
+ $prices[] = $item->getMsrp();
+ }
+ }
+
+ $msrp = $prices ? max($prices) : 0;
+ } else {
+ return false;
}
}
if ($msrp) {
diff --git a/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml
new file mode 100644
index 0000000000000..3922bb4868914
--- /dev/null
+++ b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ EnableMAP
+
+
+ 1
+
+
+
+ DisableMAP
+
+
+ 0
+
+
diff --git a/app/code/Magento/Msrp/Test/Mftf/Metadata/msrp_settings-meta.xml b/app/code/Magento/Msrp/Test/Mftf/Metadata/msrp_settings-meta.xml
new file mode 100644
index 0000000000000..be91a548ad909
--- /dev/null
+++ b/app/code/Magento/Msrp/Test/Mftf/Metadata/msrp_settings-meta.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml
new file mode 100644
index 0000000000000..a874de3b223a2
--- /dev/null
+++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json
index 6e7bf61063a2a..e3099aa2f14d6 100644
--- a/app/code/Magento/Msrp/composer.json
+++ b/app/code/Magento/Msrp/composer.json
@@ -11,6 +11,7 @@
"magento/module-downloadable": "*",
"magento/module-eav": "*",
"magento/module-grouped-product": "*",
+ "magento/module-configurable-product": "*",
"magento/module-store": "*",
"magento/module-tax": "*"
},
diff --git a/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml b/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml
index dd5abd433073d..a951c14cf4c70 100644
--- a/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml
+++ b/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml
@@ -20,8 +20,23 @@ $priceType = $block->getPrice();
/** @var $product \Magento\Catalog\Model\Product */
$product = $block->getSaleableItem();
$productId = $product->getId();
+
+$amount = 0;
+if ($product->getMsrp()) {
+ $amount = $product->getMsrp();
+} elseif ($product->getTypeId() === \Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE) {
+ $amount = $product->getTypeInstance()->getChildrenMsrp($product);
+} elseif ($product->getTypeId() === \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
+ foreach ($product->getTypeInstance()->getUsedProducts($product) as $item) {
+ if ($item->getMsrp() !== null) {
+ $prices[] = $item->getMsrp();
+ }
+ }
+ $amount = $prices ? max($prices) : 0;
+}
+
$msrpPrice = $block->renderAmount(
- $priceType->getCustomAmount($product->getMsrp() ?: $product->getTypeInstance()->getChildrenMsrp($product)),
+ $priceType->getCustomAmount($amount),
[
'price_id' => $block->getPriceId() ? $block->getPriceId() : 'old-price-' . $productId,
'include_container' => false,
@@ -29,54 +44,56 @@ $msrpPrice = $block->renderAmount(
]
);
$priceElementIdPrefix = $block->getPriceElementIdPrefix() ? $block->getPriceElementIdPrefix() : 'product-price-';
-
-$addToCartUrl = '';
-if ($product->isSaleable()) {
- /** @var Magento\Catalog\Block\Product\AbstractProduct $addToCartUrlGenerator */
- $addToCartUrlGenerator = $block->getLayout()->getBlockSingleton('Magento\Catalog\Block\Product\AbstractProduct');
- $addToCartUrl = $addToCartUrlGenerator->getAddToCartUrl(
- $product,
- ['_query' => [
- \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED =>
- $this->helper('Magento\Framework\Url\Helper\Data')->getEncodedUrl(
- $addToCartUrlGenerator->getAddToCartUrl($product)
- ),
- ]]
- );
-}
?>
-getMsrp()): ?>
+
+
= /* @escapeNotVerified */ $msrpPrice ?>
+ = /* @escapeNotVerified */ $msrpPrice ?>
isShowPriceOnGesture()): ?>
getIdSuffix();
- $popupId = 'msrp-popup-' . $productId . $block->getRandomString(20);
- $data = ['addToCart' => [
- 'origin'=> 'msrp',
- 'popupId' => '#' . $popupId,
- 'productName' => $block->escapeJs($block->escapeHtml($product->getName())),
- 'productId' => $productId,
- 'productIdInput' => 'input[type="hidden"][name="product"]',
- 'realPrice' => $block->getRealPriceHtml(),
- 'isSaleable' => $product->isSaleable(),
- 'msrpPrice' => $msrpPrice,
- 'priceElementId' => $priceElementId,
- 'closeButtonId' => '#map-popup-close',
- 'addToCartUrl' => $addToCartUrl,
- 'paymentButtons' => '[data-label=or]'
- ]];
- if ($block->getRequest()->getFullActionName() === 'catalog_product_view') {
- $data['addToCart']['addToCartButton'] = '#product_addtocart_form [type=submit]';
- } else {
- $data['addToCart']['addToCartButton'] = sprintf(
- 'form:has(input[type="hidden"][name="product"][value="%s"]) button[type="submit"]',
- (int) $productId) . ',' .
- sprintf('.block.widget .price-box[data-product-id=%s]+.product-item-actions button.tocart',
- (int) $productId
- );
- }
+
+ $addToCartUrl = '';
+ if ($product->isSaleable()) {
+ /** @var Magento\Catalog\Block\Product\AbstractProduct $addToCartUrlGenerator */
+ $addToCartUrlGenerator = $block->getLayout()->getBlockSingleton('Magento\Catalog\Block\Product\AbstractProduct');
+ $addToCartUrl = $addToCartUrlGenerator->getAddToCartUrl(
+ $product,
+ ['_query' => [
+ \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED =>
+ $this->helper('Magento\Framework\Url\Helper\Data')->getEncodedUrl(
+ $addToCartUrlGenerator->getAddToCartUrl($product)
+ ),
+ ]]
+ );
+ }
+
+ $priceElementId = $priceElementIdPrefix . $productId . $block->getIdSuffix();
+ $popupId = 'msrp-popup-' . $productId . $block->getRandomString(20);
+ $data = ['addToCart' => [
+ 'origin'=> 'msrp',
+ 'popupId' => '#' . $popupId,
+ 'productName' => $block->escapeJs($block->escapeHtml($product->getName())),
+ 'productId' => $productId,
+ 'productIdInput' => 'input[type="hidden"][name="product"]',
+ 'realPrice' => $block->getRealPriceHtml(),
+ 'isSaleable' => $product->isSaleable(),
+ 'msrpPrice' => $msrpPrice,
+ 'priceElementId' => $priceElementId,
+ 'closeButtonId' => '#map-popup-close',
+ 'addToCartUrl' => $addToCartUrl,
+ 'paymentButtons' => '[data-label=or]'
+ ]];
+ if ($block->getRequest()->getFullActionName() === 'catalog_product_view') {
+ $data['addToCart']['addToCartButton'] = '#product_addtocart_form [type=submit]';
+ } else {
+ $data['addToCart']['addToCartButton'] = sprintf(
+ 'form:has(input[type="hidden"][name="product"][value="%s"]) button[type="submit"]',
+ (int) $productId . ',' .
+ sprintf('.block.widget .price-box[data-product-id=%s]+.product-item-actions button.tocart',
+ (int) $productId));
+ }
?>
isSaleable()) {
"productName": "= $block->escapeJs($block->escapeHtml($product->getName())) ?>",
"closeButtonId": "#map-popup-close"}}'>= /* @escapeNotVerified */ __("What's this?") ?>
-
+
\ No newline at end of file
diff --git a/app/code/Magento/Msrp/view/base/web/js/msrp.js b/app/code/Magento/Msrp/view/base/web/js/msrp.js
index 72dd1d8bbecbe..a0bd3ec132de6 100644
--- a/app/code/Magento/Msrp/view/base/web/js/msrp.js
+++ b/app/code/Magento/Msrp/view/base/web/js/msrp.js
@@ -4,11 +4,12 @@
*/
define([
'jquery',
+ 'Magento_Catalog/js/price-utils',
'underscore',
'jquery/ui',
'mage/dropdown',
'mage/template'
-], function ($) {
+], function ($, priceUtils, _) {
'use strict';
$.widget('mage.addToCart', {
@@ -24,7 +25,14 @@ define([
// Selectors
cartForm: '.form.map.checkout',
msrpLabelId: '#map-popup-msrp',
+ msrpPriceElement: '#map-popup-msrp .price-wrapper',
priceLabelId: '#map-popup-price',
+ priceElement: '#map-popup-price .price',
+ mapInfoLinks: '.map-show-info',
+ displayPriceElement: '.old-price.map-old-price .price-wrapper',
+ fallbackPriceElement: '.normal-price.map-fallback-price .price-wrapper',
+ displayPriceContainer: '.old-price.map-old-price',
+ fallbackPriceContainer: '.normal-price.map-fallback-price',
popUpAttr: '[data-role=msrp-popup-template]',
popupCartButtonId: '#map-popup-button',
paypalCheckoutButons: '[data-action=checkout-form-submit]',
@@ -59,9 +67,11 @@ define([
shadowHinter: 'popup popup-pointer'
},
popupOpened: false,
+ wasOpened: false,
/**
* Creates widget instance
+ *
* @private
*/
_create: function () {
@@ -73,11 +83,13 @@ define([
this.initTierPopup();
}
$(this.options.cartButtonId).on('click', this._addToCartSubmit.bind(this));
+ $(document).on('updateMsrpPriceBlock', this.onUpdateMsrpPrice.bind(this));
$(this.options.cartForm).on('submit', this._onSubmitForm.bind(this));
},
/**
* Init msrp popup
+ *
* @private
*/
initMsrpPopup: function () {
@@ -90,7 +102,7 @@ define([
$msrpPopup.find('button')
.on('click',
- this.handleMsrpAddToCart.bind(this))
+ this.handleMsrpAddToCart.bind(this))
.filter(this.options.popupCartButtonId)
.text($(this.options.addToCartButton).text());
@@ -105,6 +117,7 @@ define([
/**
* Init info popup
+ *
* @private
*/
initInfoPopup: function () {
@@ -213,8 +226,12 @@ define([
var options = this.tierOptions || this.options;
this.popUpOptions.position.of = $(event.target);
- this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);
- this.$popup.find(this.options.priceLabelId).html(options.realPrice);
+
+ if (!this.wasOpened) {
+ this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);
+ this.$popup.find(this.options.priceLabelId).html(options.realPrice);
+ this.wasOpened = true;
+ }
this.$popup.dropdownDialog(this.popUpOptions).dropdownDialog('open');
this._toggle(this.$popup);
@@ -224,6 +241,7 @@ define([
},
/**
+ * Toggle MAP popup visibility
*
* @param {HTMLElement} $elem
* @private
@@ -240,6 +258,7 @@ define([
},
/**
+ * Close MAP information popup
*
* @param {HTMLElement} $elem
*/
@@ -274,6 +293,90 @@ define([
$(this.options.cartForm).submit();
},
+ /**
+ * Call on event updatePrice. Proxy to updateMsrpPrice method.
+ *
+ * @param {Event} event
+ * @param {mixed} priceIndex
+ * @param {Object} prices
+ */
+ onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices) {
+
+ var defaultMsrp,
+ defaultPrice,
+ msrpPrice,
+ finalPrice;
+
+ defaultMsrp = _.chain(prices).map(function (price) {
+ return price.msrpPrice.amount;
+ }).reject(function (p) {
+ return p === null;
+ }).max().value();
+
+ defaultPrice = _.chain(prices).map(function (p) {
+ return p.finalPrice.amount;
+ }).min().value();
+
+ if (typeof priceIndex !== 'undefined') {
+ msrpPrice = prices[priceIndex].msrpPrice.amount;
+ finalPrice = prices[priceIndex].finalPrice.amount;
+
+ if (msrpPrice === null || msrpPrice <= finalPrice) {
+ this.updateNonMsrpPrice(priceUtils.formatPrice(finalPrice));
+ } else {
+ this.updateMsrpPrice(
+ priceUtils.formatPrice(finalPrice),
+ priceUtils.formatPrice(msrpPrice),
+ false);
+ }
+ } else {
+ this.updateMsrpPrice(
+ priceUtils.formatPrice(defaultPrice),
+ priceUtils.formatPrice(defaultMsrp),
+ true);
+ }
+ },
+
+ /**
+ * Update prices for configurable product with MSRP enabled
+ *
+ * @param {String} finalPrice
+ * @param {String} msrpPrice
+ * @param {Boolean} useDefaultPrice
+ */
+ updateMsrpPrice: function (finalPrice, msrpPrice, useDefaultPrice) {
+ var options = this.tierOptions || this.options;
+
+ $(this.options.fallbackPriceContainer).hide();
+ $(this.options.displayPriceContainer).show();
+ $(this.options.mapInfoLinks).show();
+
+ if (useDefaultPrice || !this.wasOpened) {
+ this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);
+ this.$popup.find(this.options.priceLabelId).html(options.realPrice);
+ $(this.options.displayPriceElement).html(msrpPrice);
+ this.wasOpened = true;
+ }
+
+ if (!useDefaultPrice) {
+ this.$popup.find(this.options.msrpPriceElement).html(msrpPrice);
+ this.$popup.find(this.options.priceElement).html(finalPrice);
+ $(this.options.displayPriceElement).html(msrpPrice);
+ }
+ },
+
+ /**
+ * Display non MAP price for irrelevant products
+ *
+ * @param {String} price
+ */
+ updateNonMsrpPrice: function (price) {
+ $(this.options.fallbackPriceElement).html(price);
+ $(this.options.displayPriceContainer).hide();
+ $(this.options.mapInfoLinks).hide();
+ $(this.options.fallbackPriceContainer).show();
+ },
+
/**
* Handler for submit form
*
@@ -284,6 +387,7 @@ define([
$(this.options.cartButtonId).prop('disabled', true);
}
}
+
});
return $.mage.addToCart;
diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
index d2be99757df47..6729fe722de56 100644
--- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
+++ b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
@@ -106,8 +106,8 @@ public function getDefaultOperatorInputByType()
'string' => ['==', '!=', '>=', '>', '<=', '<', '{}', '!{}', '()', '!()'],
'numeric' => ['==', '!=', '>=', '>', '<=', '<', '()', '!()'],
'date' => ['==', '>=', '<='],
- 'select' => ['==', '!='],
- 'boolean' => ['==', '!='],
+ 'select' => ['==', '!=', '<=>'],
+ 'boolean' => ['==', '!=', '<=>'],
'multiselect' => ['{}', '!{}', '()', '!()'],
'grid' => ['()', '!()'],
];
@@ -137,6 +137,7 @@ public function getDefaultOperatorOptions()
'!{}' => __('does not contain'),
'()' => __('is one of'),
'!()' => __('is not one of'),
+ '<=>' => __('is undefined'),
];
}
return $this->_defaultOperatorOptions;
diff --git a/app/code/Magento/Rule/Model/Condition/Sql/Builder.php b/app/code/Magento/Rule/Model/Condition/Sql/Builder.php
index 6267e30a7a6d5..33e1bf97c3474 100644
--- a/app/code/Magento/Rule/Model/Condition/Sql/Builder.php
+++ b/app/code/Magento/Rule/Model/Condition/Sql/Builder.php
@@ -250,8 +250,30 @@ public function attachConditionToCollection(
$this->_joinTablesToCollection($collection, $combine);
$whereExpression = (string)$this->_getMappedSqlCombination($combine);
if (!empty($whereExpression)) {
- // Select ::where method adds braces even on empty expression
- $collection->getSelect()->where($whereExpression);
+ if (!empty($combine->getConditions())) {
+ $conditions = '';
+ $attributeField = '';
+ foreach ($combine->getConditions() as $condition) {
+ if ($condition->getData('attribute') === \Magento\Catalog\Api\Data\ProductInterface::SKU) {
+ $conditions = $condition->getData('value');
+ $attributeField = $condition->getMappedSqlField();
+ }
+ }
+
+ $collection->getSelect()->where($whereExpression);
+
+ if (!empty($conditions) && !empty($attributeField)) {
+ $conditions = explode(',', $conditions);
+ foreach ($conditions as &$condition) {
+ $condition = "'" . trim($condition) . "'";
+ }
+ $conditions = implode(', ', $conditions);
+ $collection->getSelect()->order("FIELD($attributeField, $conditions)");
+ }
+ } else {
+ // Select ::where method adds braces even on empty expression
+ $collection->getSelect()->where($whereExpression);
+ }
}
}
}
diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js
index 8e36562ebd7fe..202337c39da35 100644
--- a/app/code/Magento/Rule/view/adminhtml/web/rules.js
+++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js
@@ -101,6 +101,9 @@ define([
if (!elem.multiple) {
Event.observe(elem, 'change', this.hideParamInputField.bind(this, container));
+
+ this.changeVisibilityForValueRuleParam(elem);
+
}
Event.observe(elem, 'blur', this.hideParamInputField.bind(this, container));
}
@@ -262,6 +265,8 @@ define([
label.innerHTML = str != '' ? str : '...';
}
+ this.changeVisibilityForValueRuleParam(elem);
+
elem = Element.down(container, 'input.input-text');
if (elem) {
@@ -293,6 +298,23 @@ define([
this.shownElement = null;
},
+ changeVisibilityForValueRuleParam: function(elem) {
+ let parsedElementId = elem.id.split('__');
+ if (parsedElementId[2] != 'operator') {
+ return false;
+ }
+
+ let valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value');
+
+ if(elem.value == '<=>') {
+ valueElement.closest('.rule-param').hide();
+ } else {
+ valueElement.closest('.rule-param').show();
+ }
+
+ return true;
+ },
+
addRuleNewChild: function (elem) {
var parent_id = elem.id.replace(/^.*__(.*)__.*$/, '$1');
var children_ul_id = elem.id.replace(/__/g, ':').replace(/[^:]*$/, 'children').replace(/:/g, '__');
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderProcessDataPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderProcessDataPage.xml
new file mode 100644
index 0000000000000..2041bf8f3c9ae
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderProcessDataPage.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml
index 11673f1f0fe26..beb566b20806c 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml
@@ -15,5 +15,6 @@
+
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderItemsOrderedSection.xml
index 53aeeb62c6b70..5c2ff296ebeee 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderItemsOrderedSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderItemsOrderedSection.xml
@@ -23,8 +23,10 @@
+
+
@@ -35,4 +37,4 @@
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Store/Test/Mftf/Section/StorefrontHeaderSection.xml b/app/code/Magento/Store/Test/Mftf/Section/StorefrontHeaderSection.xml
index bee9a79abeb77..8004b750a4d1f 100644
--- a/app/code/Magento/Store/Test/Mftf/Section/StorefrontHeaderSection.xml
+++ b/app/code/Magento/Store/Test/Mftf/Section/StorefrontHeaderSection.xml
@@ -9,7 +9,7 @@
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
-
+
diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js
index 7b69edf6b9314..bd611d0cc1863 100644
--- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js
+++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js
@@ -493,7 +493,7 @@ define([
return '';
}
- $.each(config.options, function () {
+ $.each(config.options, function (index) {
var id,
type,
value,
@@ -523,6 +523,7 @@ define([
label = this.label ? this.label : '';
attr =
' id="' + controlId + '-item-' + id + '"' +
+ ' index="' + index + '"' +
' aria-checked="false"' +
' aria-describedby="' + controlId + '"' +
' tabindex="0"' +
@@ -745,6 +746,12 @@ define([
$widget._UpdatePrice();
}
+ $(document).trigger('updateMsrpPriceBlock',
+ [
+ parseInt($this.attr('index'), 10) + 1,
+ $widget.options.jsonConfig.optionPrices
+ ]);
+
$widget._loadMedia();
$input.trigger('change');
},
diff --git a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js
index 19536e7ff8c18..999e3262dbbdd 100644
--- a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js
+++ b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js
@@ -18,7 +18,7 @@ define([
return Element.extend({
defaults: {
template: 'ui/grid/search/search',
- placeholder: $t('Search by keyword'),
+ placeholder: 'Search by keyword',
label: $t('Keyword'),
value: '',
previews: [],
diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html
index 3ef64fd4b5371..36a3232c3e61a 100644
--- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html
+++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html
@@ -6,7 +6,7 @@
-->