setValue(isset($values[0]) ? $values[0] : null)->getElementHtml();
$to = $element->setValue(isset($values[1]) ? $values[1] : null)->getElementHtml();
- return __(
- '
from '
- ) . $from . __(
- '
to '
- ) . $to;
+ return '
' . __('from') . ' '
+ . $from .
+ '
' . __('to') . ' '
+ . $to;
}
}
diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formgroup.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formgroup.php
index ee92fd7c19b80..6f6ad4f909815 100644
--- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formgroup.php
+++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formgroup.php
@@ -81,12 +81,10 @@ protected function _prepareForm()
*/
protected function _getSetId()
{
- return intval(
- $this->getRequest()->getParam('id')
- ) > 0 ? intval(
- $this->getRequest()->getParam('id')
- ) : $this->_typeFactory->create()->load(
- $this->_coreRegistry->registry('entityType')
- )->getDefaultAttributeSetId();
+ return (int)$this->getRequest()->getParam('id') > 0
+ ? (int)$this->getRequest()->getParam('id')
+ : $this->_typeFactory->create()->load(
+ $this->_coreRegistry->registry('entityType')
+ )->getDefaultAttributeSetId();
}
}
diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Tree/Attribute.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Tree/Attribute.php
index f5e3f94418687..cb0a739b56e4e 100644
--- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Tree/Attribute.php
+++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Tree/Attribute.php
@@ -14,5 +14,5 @@ class Attribute extends \Magento\Backend\Block\Template
/**
* @var string
*/
- protected $_template = 'catalog/product/attribute/set/main/tree/attribute.phtml';
+ protected $_template = 'Magento_Catalog::catalog/product/attribute/set/main/tree/attribute.phtml';
}
diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Action/Attribute/Tab/Inventory.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Action/Attribute/Tab/Inventory.php
index 750bf6f8a0216..4aebd521fe60d 100644
--- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Action/Attribute/Tab/Inventory.php
+++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Action/Attribute/Tab/Inventory.php
@@ -74,7 +74,7 @@ public function getFieldSuffix()
public function getStoreId()
{
$storeId = $this->getRequest()->getParam('store');
- return intval($storeId);
+ return (int)$storeId;
}
/**
diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery.php
index a86ad5ee18529..9c533705fcd52 100644
--- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery.php
+++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery.php
@@ -113,7 +113,7 @@ public function getElementHtml()
*/
public function getImages()
{
- $images = $this->registry->registry('current_product')->getData('media_gallery') ?: null;
+ $images = $this->getDataObject()->getData('media_gallery') ?: null;
if ($images === null) {
$images = ((array)$this->dataPersistor->get('catalog_product'))['product']['media_gallery'] ?? null;
}
diff --git a/app/code/Magento/Catalog/Block/Product/ImageBuilder.php b/app/code/Magento/Catalog/Block/Product/ImageBuilder.php
index ad62031976ee1..f1149f15c41d3 100644
--- a/app/code/Magento/Catalog/Block/Product/ImageBuilder.php
+++ b/app/code/Magento/Catalog/Block/Product/ImageBuilder.php
@@ -121,14 +121,6 @@ protected function getRatio(\Magento\Catalog\Helper\Image $helper)
*/
public function create()
{
- /** @var \Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface $simpleOption */
- $simpleOption = $this->product->getCustomOption('simple_product');
-
- if ($simpleOption !== null) {
- $optionProduct = $simpleOption->getProduct();
- $this->setProduct($optionProduct);
- }
-
/** @var \Magento\Catalog\Helper\Image $helper */
$helper = $this->helperFactory->create()
->init($this->product, $this->imageId);
diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php
index 40afd44305262..726f083c07cd4 100644
--- a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php
+++ b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php
@@ -171,8 +171,8 @@ public function getRowCount()
*/
public function setColumnCount($columns)
{
- if (intval($columns) > 0) {
- $this->_columnCount = intval($columns);
+ if ((int)$columns > 0) {
+ $this->_columnCount = (int)$columns;
}
return $this;
}
@@ -214,8 +214,8 @@ public function getIterableItem()
*/
public function setItemLimit($type, $limit)
{
- if (intval($limit) > 0) {
- $this->_itemLimits[$type] = intval($limit);
+ if ((int)$limit > 0) {
+ $this->_itemLimits[$type] = (int)$limit;
}
return $this;
}
diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php
index 661132457b97e..17828b9d375d3 100644
--- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php
+++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php
@@ -175,7 +175,7 @@ public function getImageAttribute($imageId, $attributeName, $default = null)
{
$attributes =
$this->getConfigView()->getMediaAttributes('Magento_Catalog', Image::MEDIA_TYPE_CONFIG_NODE, $imageId);
- return isset($attributes[$attributeName]) ? $attributes[$attributeName] : $default;
+ return $attributes[$attributeName] ?? $default;
}
/**
diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php
index d582005f653ef..181211a0fc4a2 100644
--- a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php
+++ b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php
@@ -105,9 +105,11 @@ public function getOption()
}
/**
+ * Retrieve formatted price
+ *
* @return string
*/
- public function getFormatedPrice()
+ public function getFormattedPrice()
{
if ($option = $this->getOption()) {
return $this->_formatPrice(
@@ -120,6 +122,17 @@ public function getFormatedPrice()
return '';
}
+ /**
+ * @return string
+ *
+ * @deprecated
+ * @see getFormattedPrice()
+ */
+ public function getFormatedPrice()
+ {
+ return $this->getFormattedPrice();
+ }
+
/**
* Return formated price
*
diff --git a/app/code/Magento/Catalog/Block/Product/View/Price.php b/app/code/Magento/Catalog/Block/Product/View/Price.php
index c38625247b533..37598dfb1a8da 100644
--- a/app/code/Magento/Catalog/Block/Product/View/Price.php
+++ b/app/code/Magento/Catalog/Block/Product/View/Price.php
@@ -9,6 +9,8 @@
*/
namespace Magento\Catalog\Block\Product\View;
+use Magento\Catalog\Model\Product;
+
class Price extends \Magento\Framework\View\Element\Template
{
/**
@@ -37,7 +39,8 @@ public function __construct(
*/
public function getPrice()
{
+ /** @var Product $product */
$product = $this->_coreRegistry->registry('product');
- return $product->getFormatedPrice();
+ return $product->getFormattedPrice();
}
}
diff --git a/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php b/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php
index 704271b58f483..e880e0aba35cc 100644
--- a/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php
+++ b/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php
@@ -139,7 +139,7 @@ public function getCacheKeyInfo()
[
$this->getDisplayType(),
$this->getProductsPerPage(),
- intval($this->getRequest()->getParam($this->getData('page_var_name'), 1)),
+ (int)$this->getRequest()->getParam($this->getData('page_var_name'), 1),
$this->serializer->serialize($this->getRequest()->getParams())
]
);
diff --git a/app/code/Magento/Catalog/Console/Command/PriceIndexerDimensionsModeSetCommand.php b/app/code/Magento/Catalog/Console/Command/PriceIndexerDimensionsModeSetCommand.php
deleted file mode 100644
index 0660d4d6ceb36..0000000000000
--- a/app/code/Magento/Catalog/Console/Command/PriceIndexerDimensionsModeSetCommand.php
+++ /dev/null
@@ -1,196 +0,0 @@
-configReader = $configReader;
- $this->configWriter = $configWriter;
- $this->cacheTypeList = $cacheTypeList;
- $this->modeSwitcher = $modeSwitcher;
- parent::__construct($objectManagerFactory);
- }
-
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this->setName('indexer:set-dimensions-mode:catalog_product_price')
- ->setDescription('Set Indexer Dimensions Mode')
- ->setDefinition($this->getInputList());
-
- parent::configure();
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $errors = $this->validate($input);
-
- if ($errors) {
- throw new \InvalidArgumentException(implode(PHP_EOL, $errors));
- }
-
- $returnValue = \Magento\Framework\Console\Cli::RETURN_SUCCESS;
-
- $indexer = $this->getObjectManager()->get(\Magento\Indexer\Model\Indexer::class);
- $indexer->load(\Magento\Catalog\Model\Indexer\Product\Price\Processor::INDEXER_ID);
-
- try {
- $currentMode = $input->getArgument(self::INPUT_KEY_MODE);
- $previousMode = $this->configReader->getValue(ModeSwitcher::XML_PATH_PRICE_DIMENSIONS_MODE) ?:
- DimensionModeConfiguration::DIMENSION_NONE;
-
- if ($previousMode !== $currentMode) {
- //Create new tables and move data
- $this->modeSwitcher->createTables($currentMode);
- $this->modeSwitcher->moveData($currentMode, $previousMode);
-
- //Change config options
- $this->configWriter->saveConfig(ModeSwitcher::XML_PATH_PRICE_DIMENSIONS_MODE, $currentMode);
- $this->cacheTypeList->cleanType('config');
- $indexer->invalidate();
-
- //Delete old tables
- $this->modeSwitcher->dropTables($previousMode);
-
- $output->writeln(
- 'Dimensions mode for indexer ' . $indexer->getTitle() . ' was changed from \''
- . $previousMode . '\' to \'' . $currentMode . '\''
- );
- } else {
- $output->writeln('Dimensions mode for indexer ' . $indexer->getTitle() . ' has not been changed');
- }
- } catch (LocalizedException $e) {
- $output->writeln($e->getMessage() . PHP_EOL);
- // we must have an exit code higher than zero to indicate something was wrong
- $returnValue = \Magento\Framework\Console\Cli::RETURN_FAILURE;
- } catch (\Exception $e) {
- $output->writeln($indexer->getTitle() . " indexer process unknown error:" . PHP_EOL);
- $output->writeln($e->getMessage() . PHP_EOL);
- // we must have an exit code higher than zero to indicate something was wrong
- $returnValue = \Magento\Framework\Console\Cli::RETURN_FAILURE;
- }
-
- return $returnValue;
- }
-
- /**
- * Get list of arguments for the command
- *
- * @return InputOption[]
- */
- public function getInputList(): array
- {
- $modeOptions[] = new InputArgument(
- self::INPUT_KEY_MODE,
- InputArgument::REQUIRED,
- 'Indexer dimensions mode ['. DimensionModeConfiguration::DIMENSION_NONE
- . '|' . DimensionModeConfiguration::DIMENSION_WEBSITE
- . '|' . DimensionModeConfiguration::DIMENSION_CUSTOMER_GROUP
- . '|' . DimensionModeConfiguration::DIMENSION_WEBSITE_AND_CUSTOMER_GROUP .']'
- );
- return $modeOptions;
- }
-
- /**
- * Check if all admin options are provided
- *
- * @param InputInterface $input
- * @return string[]
- */
- public function validate(InputInterface $input): array
- {
- $errors = [];
-
- $acceptedModeValues = ' Accepted values for ' . self::INPUT_KEY_MODE . ' are \''
- . DimensionModeConfiguration::DIMENSION_NONE . '\', \''
- . DimensionModeConfiguration::DIMENSION_WEBSITE . '\', \''
- . DimensionModeConfiguration::DIMENSION_CUSTOMER_GROUP . '\', \''
- . DimensionModeConfiguration::DIMENSION_WEBSITE_AND_CUSTOMER_GROUP . '\'';
-
- $inputMode = $input->getArgument(self::INPUT_KEY_MODE);
- if (!$inputMode) {
- $errors[] = 'Missing argument \'' . self::INPUT_KEY_MODE .'\'.' . $acceptedModeValues;
- } elseif (!in_array(
- $inputMode,
- [
- DimensionModeConfiguration::DIMENSION_NONE,
- DimensionModeConfiguration::DIMENSION_WEBSITE,
- DimensionModeConfiguration::DIMENSION_CUSTOMER_GROUP,
- DimensionModeConfiguration::DIMENSION_WEBSITE_AND_CUSTOMER_GROUP
- ]
- )) {
- $errors[] = $acceptedModeValues;
- }
- return $errors;
- }
-}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php
index 8f570e35989cb..0a54475b15f9c 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Delete.php
@@ -44,12 +44,12 @@ public function execute()
$this->_eventManager->dispatch('catalog_controller_category_delete', ['category' => $category]);
$this->_auth->getAuthStorage()->setDeletedPath($category->getPath());
$this->categoryRepository->delete($category);
- $this->messageManager->addSuccess(__('You deleted the category.'));
+ $this->messageManager->addSuccessMessage(__('You deleted the category.'));
} catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
return $resultRedirect->setPath('catalog/*/edit', ['_current' => true]);
} catch (\Exception $e) {
- $this->messageManager->addError(__('Something went wrong while trying to delete the category.'));
+ $this->messageManager->addErrorMessage(__('Something went wrong while trying to delete the category.'));
return $resultRedirect->setPath('catalog/*/edit', ['_current' => true]);
}
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
index 4cc0f2d89d179..e24b142411b83 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
@@ -54,14 +54,6 @@ public function execute()
try {
$result = $this->imageUploader->saveFileToTmpDir($imageId);
-
- $result['cookie'] = [
- 'name' => $this->_getSession()->getName(),
- 'value' => $this->_getSession()->getSessionId(),
- 'lifetime' => $this->_getSession()->getCookieLifetime(),
- 'path' => $this->_getSession()->getCookiePath(),
- 'domain' => $this->_getSession()->getCookieDomain(),
- ];
} catch (\Exception $e) {
$result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
index fb08070be5494..af20f75d95226 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
@@ -279,7 +279,7 @@ public function imagePreprocessing($data)
continue;
}
- $data[$attributeCode] = false;
+ $data[$attributeCode] = '';
}
return $data;
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute.php
index 6958b6671d054..8a94899cf5041 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute.php
@@ -56,7 +56,7 @@ protected function _validateProducts()
}
if ($error) {
- $this->messageManager->addError($error);
+ $this->messageManager->addErrorMessage($error);
}
return !$error;
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Save.php
index 82496446aef9f..0fbf9054ef1bd 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Save.php
@@ -192,7 +192,7 @@ public function execute()
$this->_eventManager->dispatch('catalog_product_to_website_change', ['products' => $productIds]);
}
- $this->messageManager->addSuccess(
+ $this->messageManager->addSuccessMessage(
__('A total of %1 record(s) were updated.', count($this->attributeHelper->getProductIds()))
);
@@ -205,9 +205,9 @@ public function execute()
$this->_productPriceIndexerProcessor->reindexList($this->attributeHelper->getProductIds());
}
} catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
- $this->messageManager->addException(
+ $this->messageManager->addExceptionMessage(
$e,
__('Something went wrong while updating the product(s) attributes.')
);
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
index bb18436be6102..a873f08d082d7 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
@@ -68,7 +68,7 @@ public function execute()
$response->setError(true);
$response->setMessage($e->getMessage());
} catch (\Exception $e) {
- $this->messageManager->addException(
+ $this->messageManager->addExceptionMessage(
$e,
__('Something went wrong while updating the product(s) attributes.')
);
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Delete.php
index cc5a658a9296d..bef6aee0e2afd 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Delete.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Delete.php
@@ -21,23 +21,23 @@ public function execute()
// entity type check
$model->load($id);
if ($model->getEntityTypeId() != $this->_entityTypeId) {
- $this->messageManager->addError(__('We can\'t delete the attribute.'));
+ $this->messageManager->addErrorMessage(__('We can\'t delete the attribute.'));
return $resultRedirect->setPath('catalog/*/');
}
try {
$model->delete();
- $this->messageManager->addSuccess(__('You deleted the product attribute.'));
+ $this->messageManager->addSuccessMessage(__('You deleted the product attribute.'));
return $resultRedirect->setPath('catalog/*/');
} catch (\Exception $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
return $resultRedirect->setPath(
'catalog/*/edit',
['attribute_id' => $this->getRequest()->getParam('attribute_id')]
);
}
}
- $this->messageManager->addError(__('We can\'t find an attribute to delete.'));
+ $this->messageManager->addErrorMessage(__('We can\'t find an attribute to delete.'));
return $resultRedirect->setPath('catalog/*/');
}
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Edit.php
index 5a9f244a2bbe1..52c79e2a66c74 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Edit.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Edit.php
@@ -25,14 +25,14 @@ public function execute()
$model->load($id);
if (!$model->getId()) {
- $this->messageManager->addError(__('This attribute no longer exists.'));
+ $this->messageManager->addErrorMessage(__('This attribute no longer exists.'));
$resultRedirect = $this->resultRedirectFactory->create();
return $resultRedirect->setPath('catalog/*/');
}
// entity type check
if ($model->getEntityTypeId() != $this->_entityTypeId) {
- $this->messageManager->addError(__('This attribute cannot be edited.'));
+ $this->messageManager->addErrorMessage(__('This attribute cannot be edited.'));
$resultRedirect = $this->resultRedirectFactory->create();
return $resultRedirect->setPath('catalog/*/');
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php
index b9f9b739f4fa3..cfcd9560f72b8 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php
@@ -327,7 +327,8 @@ private function preprocessOptionsData(&$data)
$serializedOptions = json_decode($data['serialized_options'], JSON_OBJECT_AS_ARRAY);
foreach ($serializedOptions as $serializedOption) {
$option = [];
- parse_str($serializedOption, $option);
+ $serializedOptionWithParsedAmpersand = str_replace('&', '%26', $serializedOption);
+ parse_str($serializedOptionWithParsedAmpersand, $option);
$data = array_replace_recursive($data, $option);
}
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php
index b1edda0ffa34c..7fe012a87d929 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php
@@ -91,7 +91,7 @@ public function execute()
$attributeSet->setEntityTypeId($this->_entityTypeId)->load($setName, 'attribute_set_name');
if ($attributeSet->getId()) {
$setName = $this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($setName);
- $this->messageManager->addError(__('An attribute set named \'%1\' already exists.', $setName));
+ $this->messageManager->addErrorMessage(__('An attribute set named \'%1\' already exists.', $setName));
$layout = $this->layoutFactory->create();
$layout->initMessages();
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
index 7e8b03a66f603..63e52eead064c 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
@@ -43,11 +43,11 @@ public function execute()
$product = $this->productBuilder->build($this->getRequest());
try {
$newProduct = $this->productCopier->copy($product);
- $this->messageManager->addSuccess(__('You duplicated the product.'));
+ $this->messageManager->addSuccessMessage(__('You duplicated the product.'));
$resultRedirect->setPath('catalog/*/edit', ['_current' => true, 'id' => $newProduct->getId()]);
} catch (\Exception $e) {
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
$resultRedirect->setPath('catalog/*/edit', ['_current' => true]);
}
return $resultRedirect;
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Edit.php
index 9f99ad0fe6aca..3a4d3af4b39b1 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Edit.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Edit.php
@@ -52,12 +52,12 @@ public function execute()
if (($productId && !$product->getEntityId())) {
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
- $this->messageManager->addError(__('This product doesn\'t exist.'));
+ $this->messageManager->addErrorMessage(__('This product doesn\'t exist.'));
return $resultRedirect->setPath('catalog/*/');
} elseif ($productId === 0) {
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
- $this->messageManager->addError(__('Invalid product id. Should be numeric value greater than 0'));
+ $this->messageManager->addErrorMessage(__('Invalid product id. Should be numeric value greater than 0'));
return $resultRedirect->setPath('catalog/*/');
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Group/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Group/Save.php
index 4909e22775e55..8a5f375f2b706 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Group/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Group/Save.php
@@ -29,12 +29,12 @@ public function execute()
);
if ($model->itemExists()) {
- $this->messageManager->addError(__('A group with the same name already exists.'));
+ $this->messageManager->addErrorMessage(__('A group with the same name already exists.'));
} else {
try {
$model->save();
} catch (\Exception $e) {
- $this->messageManager->addError(__('Something went wrong while saving this group.'));
+ $this->messageManager->addErrorMessage(__('Something went wrong while saving this group.'));
}
}
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
index 95339870b4d61..7153f9fd0f3f9 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
@@ -159,6 +159,7 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra
}
$productData = $this->normalize($productData);
+ $productData = $this->convertSpecialFromDateStringToObject($productData);
if (!empty($productData['is_downloadable'])) {
$productData['product_has_weight'] = 0;
@@ -452,4 +453,19 @@ private function fillProductOptions(Product $product, array $productOptions)
return $product->setOptions($customOptions);
}
+
+ /**
+ * Convert string date presentation into object
+ *
+ * @param array $productData
+ * @return array
+ */
+ private function convertSpecialFromDateStringToObject($productData)
+ {
+ if (isset($productData['special_from_date']) && $productData['special_from_date'] != '') {
+ $productData['special_from_date'] = new \DateTime($productData['special_from_date']);
+ }
+
+ return $productData;
+ }
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php
index 366356597fdfb..d04284b4b323c 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php
@@ -11,6 +11,7 @@
use Magento\Ui\Component\MassAction\Filter;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\Framework\Exception\NotFoundException;
class MassDelete extends \Magento\Catalog\Controller\Adminhtml\Product
{
@@ -54,9 +55,15 @@ public function __construct(
/**
* @return \Magento\Backend\Model\View\Result\Redirect
+ * @throws NotFoundException
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws \Magento\Framework\Exception\StateException
*/
public function execute()
{
+ if (!$this->getRequest()->isPost()) {
+ throw new NotFoundException(__('Page not found'));
+ }
$collection = $this->filter->getCollection($this->collectionFactory->create());
$productDeleted = 0;
/** @var \Magento\Catalog\Model\Product $product */
@@ -66,7 +73,7 @@ public function execute()
}
if ($productDeleted) {
- $this->messageManager->addSuccess(
+ $this->messageManager->addSuccessMessage(
__('A total of %1 record(s) have been deleted.', $productDeleted)
);
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php
index ec5eb9de3fe35..b6e7e31fb9efd 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassStatus.php
@@ -94,10 +94,12 @@ public function execute()
$this->_validateMassStatus($productIds, $status);
$this->_objectManager->get(\Magento\Catalog\Model\Product\Action::class)
->updateAttributes($productIds, ['status' => $status], $storeId);
- $this->messageManager->addSuccess(__('A total of %1 record(s) have been updated.', count($productIds)));
+ $this->messageManager->addSuccessMessage(
+ __('A total of %1 record(s) have been updated.', count($productIds))
+ );
$this->_productPriceIndexerProcessor->reindexList($productIds);
} catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->_getSession()->addException($e, __('Something went wrong while updating the product(s) status.'));
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
index 15154b02dbf8a..bf0d740fc98fb 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
@@ -102,12 +102,12 @@ public function execute()
$this->productBuilder->build($this->getRequest())
);
$this->productTypeManager->processProduct($product);
-
if (isset($data['product'][$product->getIdFieldName()])) {
throw new \Magento\Framework\Exception\LocalizedException(__('Unable to save product'));
}
$originalSku = $product->getSku();
+ $canSaveCustomOptions = $product->getCanSaveCustomOptions();
$product->save();
$this->handleImageRemoveError($data, $product->getId());
$this->getCategoryLinkManagement()->assignProductToCategories(
@@ -117,9 +117,9 @@ public function execute()
$productId = $product->getEntityId();
$productAttributeSetId = $product->getAttributeSetId();
$productTypeId = $product->getTypeId();
-
- $this->copyToStores($data, $productId);
-
+ $extendedData = $data;
+ $extendedData['can_save_custom_options'] = $canSaveCustomOptions;
+ $this->copyToStores($extendedData, $productId);
$this->messageManager->addSuccessMessage(__('You saved the product.'));
$this->getDataPersistor()->clear('catalog_product');
if ($product->getSku() != $originalSku) {
@@ -141,19 +141,20 @@ public function execute()
);
if ($redirectBack === 'duplicate') {
+ $product->unsetData('quantity_and_stock_status');
$newProduct = $this->productCopier->copy($product);
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
}
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
$this->messageManager->addExceptionMessage($e);
- $data = $this->persistMediaData($product, $data);
+ $data = isset($product) ? $this->persistMediaData($product, $data) : $data;
$this->getDataPersistor()->set('catalog_product', $data);
$redirectBack = $productId ? true : 'new';
} catch (\Exception $e) {
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
$this->messageManager->addErrorMessage($e->getMessage());
- $data = $this->persistMediaData($product, $data);
+ $data = isset($product) ? $this->persistMediaData($product, $data) : $data;
$this->getDataPersistor()->set('catalog_product', $data);
$redirectBack = $productId ? true : 'new';
}
@@ -216,6 +217,9 @@ private function handleImageRemoveError($postData, $productId)
/**
* Do copying data to stores
*
+ * If the 'copy_from' field is not specified in the input data,
+ * the store fallback mechanism will automatically take the admin store's default value.
+ *
* @param array $data
* @param int $productId
* @return void
@@ -227,15 +231,18 @@ protected function copyToStores($data, $productId)
if (isset($data['product']['website_ids'][$websiteId])
&& (bool)$data['product']['website_ids'][$websiteId]) {
foreach ($group as $store) {
- $copyFrom = (isset($store['copy_from'])) ? $store['copy_from'] : 0;
- $copyTo = (isset($store['copy_to'])) ? $store['copy_to'] : 0;
- if ($copyTo) {
- $this->_objectManager->create(\Magento\Catalog\Model\Product::class)
- ->setStoreId($copyFrom)
- ->load($productId)
- ->setStoreId($copyTo)
- ->setCopyFromView(true)
- ->save();
+ if (isset($store['copy_from'])) {
+ $copyFrom = $store['copy_from'];
+ $copyTo = (isset($store['copy_to'])) ? $store['copy_to'] : 0;
+ if ($copyTo) {
+ $this->_objectManager->create(\Magento\Catalog\Model\Product::class)
+ ->setStoreId($copyFrom)
+ ->load($productId)
+ ->setStoreId($copyTo)
+ ->setCanSaveCustomOptions($data['can_save_custom_options'])
+ ->setCopyFromView(true)
+ ->save();
+ }
}
}
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php
index b49a4dabe223c..f2695311732f0 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php
@@ -36,10 +36,10 @@ public function execute()
$resultRedirect = $this->resultRedirectFactory->create();
try {
$this->attributeSetRepository->deleteById($setId);
- $this->messageManager->addSuccess(__('The attribute set has been removed.'));
+ $this->messageManager->addSuccessMessage(__('The attribute set has been removed.'));
$resultRedirect->setPath('catalog/*/');
} catch (\Exception $e) {
- $this->messageManager->addError(__('We can\'t delete this set right now.'));
+ $this->messageManager->addErrorMessage(__('We can\'t delete this set right now.'));
$resultRedirect->setUrl($this->_redirect->getRedirectUrl($this->getUrl('*')));
}
return $resultRedirect;
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php
index dfddcf7e92b97..c5dd9ce6d8e77 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php
@@ -127,15 +127,15 @@ public function execute()
$model->initFromSkeleton($this->getRequest()->getParam('skeleton_set'));
}
$model->save();
- $this->messageManager->addSuccess(__('You saved the attribute set.'));
+ $this->messageManager->addSuccessMessage(__('You saved the attribute set.'));
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
$hasError = true;
} catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
$hasError = true;
} catch (\Exception $e) {
- $this->messageManager->addException($e, __('Something went wrong while saving the attribute set.'));
+ $this->messageManager->addExceptionMessage($e, __('Something went wrong while saving the attribute set.'));
$hasError = true;
}
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Validate.php
index 63f46fd32e6f7..e131bfe38c546 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Validate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Validate.php
@@ -137,7 +137,7 @@ public function execute()
$response->setError(true);
$response->setMessages([$e->getMessage()]);
} catch (\Exception $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
$layout = $this->layoutFactory->create();
$layout->initMessages();
$response->setError(true);
diff --git a/app/code/Magento/Catalog/Controller/Category/View.php b/app/code/Magento/Catalog/Controller/Category/View.php
index 9d7bf1dfb361e..e31b1a17ecdc3 100644
--- a/app/code/Magento/Catalog/Controller/Category/View.php
+++ b/app/code/Magento/Catalog/Controller/Category/View.php
@@ -111,7 +111,7 @@ public function __construct(
/**
* Initialize requested category object
*
- * @return \Magento\Catalog\Model\Category
+ * @return \Magento\Catalog\Model\Category|bool
*/
protected function _initCategory()
{
diff --git a/app/code/Magento/Catalog/Controller/Product/Compare/Clear.php b/app/code/Magento/Catalog/Controller/Product/Compare/Clear.php
index 30470d13f002d..568fbf1d05677 100644
--- a/app/code/Magento/Catalog/Controller/Product/Compare/Clear.php
+++ b/app/code/Magento/Catalog/Controller/Product/Compare/Clear.php
@@ -30,12 +30,12 @@ public function execute()
try {
$items->clear();
- $this->messageManager->addSuccess(__('You cleared the comparison list.'));
+ $this->messageManager->addSuccessMessage(__('You cleared the comparison list.'));
$this->_objectManager->get(\Magento\Catalog\Helper\Product\Compare::class)->calculate();
} catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
- $this->messageManager->addException($e, __('Something went wrong clearing the comparison list.'));
+ $this->messageManager->addExceptionMessage($e, __('Something went wrong clearing the comparison list.'));
}
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
diff --git a/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php b/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php
index fadb94761a236..2acbe5ce4d582 100644
--- a/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php
+++ b/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php
@@ -44,7 +44,7 @@ public function execute()
$item->delete();
$productName = $this->_objectManager->get(\Magento\Framework\Escaper::class)
->escapeHtml($product->getName());
- $this->messageManager->addSuccess(
+ $this->messageManager->addSuccessMessage(
__('You removed product %1 from the comparison list.', $productName)
);
$this->_eventManager->dispatch(
diff --git a/app/code/Magento/Catalog/Controller/Product/View.php b/app/code/Magento/Catalog/Controller/Product/View.php
index e99886837ed76..4ec35b3382786 100644
--- a/app/code/Magento/Catalog/Controller/Product/View.php
+++ b/app/code/Magento/Catalog/Controller/Product/View.php
@@ -81,13 +81,16 @@ public function execute()
&& $this->_request->getParam(self::PARAM_NAME_URL_ENCODED)
) {
$product = $this->_initProduct();
+
if (!$product) {
return $this->noProductRedirect();
}
+
if ($specifyOptions) {
$notice = $product->getTypeInstance()->getSpecifyOptionMessage();
- $this->messageManager->addNotice($notice);
+ $this->messageManager->addNoticeMessage($notice);
}
+
if ($this->getRequest()->isAjax()) {
$this->getResponse()->representJson(
$this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class)->jsonEncode([
diff --git a/app/code/Magento/Catalog/Cron/FrontendActionsFlush.php b/app/code/Magento/Catalog/Cron/FrontendActionsFlush.php
index 6e7699abb4776..99e9898eab3c0 100644
--- a/app/code/Magento/Catalog/Cron/FrontendActionsFlush.php
+++ b/app/code/Magento/Catalog/Cron/FrontendActionsFlush.php
@@ -57,8 +57,7 @@ private function getLifeTimeByNamespace($namespace)
];
}
- return isset($configuration['lifetime']) ?
- (int) $configuration['lifetime'] : FrontendStorageConfigurationInterface::DEFAULT_LIFETIME;
+ return (int)$configuration['lifetime'] ?? FrontendStorageConfigurationInterface::DEFAULT_LIFETIME;
}
/**
diff --git a/app/code/Magento/Catalog/CustomerData/CompareProducts.php b/app/code/Magento/Catalog/CustomerData/CompareProducts.php
index 0e688042c615a..afbeab8c9070e 100644
--- a/app/code/Magento/Catalog/CustomerData/CompareProducts.php
+++ b/app/code/Magento/Catalog/CustomerData/CompareProducts.php
@@ -19,6 +19,11 @@ class CompareProducts implements SectionSourceInterface
*/
protected $productUrl;
+ /**
+ * @var \Magento\Catalog\Helper\Output
+ */
+ private $outputHelper;
+
/**
* @param \Magento\Catalog\Helper\Product\Compare $helper
* @param \Magento\Catalog\Model\Product\Url $productUrl
@@ -54,6 +59,7 @@ public function getSectionData()
protected function getItems()
{
$items = [];
+ /** @var \Magento\Catalog\Model\Product $item */
foreach ($this->helper->getItemCollection() as $item) {
$items[] = [
'id' => $item->getId(),
diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php
index 380fd0298c2d7..4e8e63c17199d 100644
--- a/app/code/Magento/Catalog/Helper/Image.php
+++ b/app/code/Magento/Catalog/Helper/Image.php
@@ -859,7 +859,7 @@ public function getFrame()
*/
protected function getAttribute($name)
{
- return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
+ return $this->attributes[$name] ?? null;
}
/**
diff --git a/app/code/Magento/Catalog/Helper/Output.php b/app/code/Magento/Catalog/Helper/Output.php
index facd5351f269a..ecd3fe6a32a83 100644
--- a/app/code/Magento/Catalog/Helper/Output.php
+++ b/app/code/Magento/Catalog/Helper/Output.php
@@ -105,7 +105,7 @@ public function addHandler($method, $handler)
public function getHandlers($method)
{
$method = strtolower($method);
- return isset($this->_handlers[$method]) ? $this->_handlers[$method] : [];
+ return $this->_handlers[$method] ?? [];
}
/**
@@ -151,7 +151,7 @@ public function productAttribute($product, $attributeHtml, $attributeName)
$attributeHtml = nl2br($attributeHtml);
}
}
- if ($attribute->getIsHtmlAllowedOnFront() && $attribute->getIsWysiwygEnabled()) {
+ if ($attribute->getIsHtmlAllowedOnFront() || $attribute->getIsWysiwygEnabled()) {
if ($this->_catalogData->isUrlDirectivesParsingAllowed()) {
$attributeHtml = $this->_getTemplateProcessor()->filter($attributeHtml);
}
diff --git a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/NativeAttributeCondition.php b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/NativeAttributeCondition.php
index 976714dcd9aea..3c2837fd2e9a1 100644
--- a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/NativeAttributeCondition.php
+++ b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/NativeAttributeCondition.php
@@ -74,7 +74,7 @@ private function mapConditionType(string $conditionType, string $field): string
];
}
- return isset($conditionsMap[$conditionType]) ? $conditionsMap[$conditionType] : $conditionType;
+ return $conditionsMap[$conditionType] ?? $conditionType;
}
/**
diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php
index 57cfa75380851..00b093b2918f1 100644
--- a/app/code/Magento/Catalog/Model/Category.php
+++ b/app/code/Magento/Catalog/Model/Category.php
@@ -71,6 +71,11 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
const CACHE_TAG = 'cat_c';
+ /**
+ * Category Store Id
+ */
+ const STORE_ID = 'store_id';
+
/**#@+
* Constants
*/
@@ -588,12 +593,12 @@ public function getStoreIds()
*
* If store id is underfined for category return current active store id
*
- * @return integer
+ * @return int
*/
public function getStoreId()
{
- if ($this->hasData('store_id')) {
- return (int)$this->_getData('store_id');
+ if ($this->hasData(self::STORE_ID)) {
+ return (int)$this->_getData(self::STORE_ID);
}
return (int)$this->_storeManager->getStore()->getId();
}
@@ -609,7 +614,7 @@ public function setStoreId($storeId)
if (!is_numeric($storeId)) {
$storeId = $this->_storeManager->getStore($storeId)->getId();
}
- $this->setData('store_id', $storeId);
+ $this->setData(self::STORE_ID, $storeId);
$this->getResource()->setStoreId($storeId);
return $this;
}
@@ -721,7 +726,7 @@ public function getParentId()
return $parentId;
}
$parentIds = $this->getParentIds();
- return intval(array_pop($parentIds));
+ return (int)array_pop($parentIds);
}
/**
diff --git a/app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php
index f22c6903a230c..5af421b5bc34c 100644
--- a/app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php
+++ b/app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php
@@ -60,7 +60,7 @@ public function execute($entity, $arguments = [])
if ($dtoCategoryLinks !== null) {
$hydrator = $this->hydratorPool->getHydrator(CategoryLinkInterface::class);
$dtoCategoryLinks = array_map(function ($categoryLink) use ($hydrator) {
- return $hydrator->extract($categoryLink) ;
+ return $hydrator->extract($categoryLink);
}, $dtoCategoryLinks);
$processLinks = $this->mergeCategoryLinks($dtoCategoryLinks, $modelCategoryLinks);
} else {
diff --git a/app/code/Magento/Catalog/Model/Config.php b/app/code/Magento/Catalog/Model/Config.php
index b3b5204887ea1..01ab0de024577 100644
--- a/app/code/Magento/Catalog/Model/Config.php
+++ b/app/code/Magento/Catalog/Model/Config.php
@@ -382,7 +382,7 @@ public function getProductTypeName($id)
$this->loadProductTypes();
- return isset($this->_productTypesById[$id]) ? $this->_productTypesById[$id] : false;
+ return $this->_productTypesById[$id] ?? false;
}
/**
diff --git a/app/code/Magento/Catalog/Model/ImageExtractor.php b/app/code/Magento/Catalog/Model/ImageExtractor.php
index 7888d8de1c2ff..f13d682f505cd 100644
--- a/app/code/Magento/Catalog/Model/ImageExtractor.php
+++ b/app/code/Magento/Catalog/Model/ImageExtractor.php
@@ -32,12 +32,16 @@ public function process(\DOMElement $mediaNode, $mediaParentTag)
continue;
}
$attributeTagName = $attribute->tagName;
- if ($attributeTagName === 'background') {
- $nodeValue = $this->processImageBackground($attribute->nodeValue);
- } elseif ($attributeTagName === 'width' || $attributeTagName === 'height') {
- $nodeValue = intval($attribute->nodeValue);
+ if ((bool)$attribute->getAttribute('xsi:nil') !== true) {
+ if ($attributeTagName === 'background') {
+ $nodeValue = $this->processImageBackground($attribute->nodeValue);
+ } elseif ($attributeTagName === 'width' || $attributeTagName === 'height') {
+ $nodeValue = (int)$attribute->nodeValue;
+ } else {
+ $nodeValue = $attribute->nodeValue;
+ }
} else {
- $nodeValue = $attribute->nodeValue;
+ $nodeValue = null;
}
$result[$mediaParentTag][$moduleNameImage][Image::MEDIA_TYPE_CONFIG_NODE][$imageId][$attribute->tagName]
= $nodeValue;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/AbstractAction.php
index 8f0e6e9c0cdb5..a94ff06c62ffb 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/AbstractAction.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/AbstractAction.php
@@ -113,7 +113,7 @@ public function getColumns()
public function getMainStoreTable($storeId = \Magento\Store\Model\Store::DEFAULT_STORE_ID)
{
if (is_string($storeId)) {
- $storeId = intval($storeId);
+ $storeId = (int)$storeId;
}
$suffix = sprintf('store_%d', $storeId);
diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php
index faa9c4ee4d529..3c2629bc570f2 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php
@@ -143,7 +143,7 @@ public function getMainTable(int $storeId)
public function createTablesForStore(int $storeId)
{
$mainTableName = $this->getMainTable($storeId);
- //Create index table for store based on on main replica table
+ //Create index table for store based on main replica table
//Using main replica table is necessary for backward capability and TableResolver plugin work
$this->createTable(
$this->getTable(AbstractAction::MAIN_INDEX_TABLE . $this->additionalTableSuffix),
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/AbstractAction.php
index ffd912a7cf367..43b4b5518c16f 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/AbstractAction.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/AbstractAction.php
@@ -3,6 +3,8 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Catalog\Model\Indexer\Product\Eav;
/**
@@ -10,6 +12,11 @@
*/
abstract class AbstractAction
{
+ /**
+ * Config path for enable EAV indexer
+ */
+ const ENABLE_EAV_INDEXER = 'catalog/search/enable_eav_indexer';
+
/**
* EAV Indexers by type
*
@@ -27,17 +34,27 @@ abstract class AbstractAction
*/
protected $_eavDecimalFactory;
+ /**
+ * @var \Magento\Framework\App\Config\ScopeConfigInterface
+ */
+ private $scopeConfig;
+
/**
* AbstractAction constructor.
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory $eavDecimalFactory
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory $eavSourceFactory
+ * @param \Magento\Framework\App\Config\ScopeConfigInterface|null $scopeConfig
*/
public function __construct(
\Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory $eavDecimalFactory,
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory $eavSourceFactory
+ \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory $eavSourceFactory,
+ \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig = null
) {
$this->_eavDecimalFactory = $eavDecimalFactory;
$this->_eavSourceFactory = $eavSourceFactory;
+ $this->scopeConfig = $scopeConfig ?: \Magento\Framework\App\ObjectManager::getInstance()->get(
+ \Magento\Framework\App\Config\ScopeConfigInterface::class
+ );
}
/**
@@ -90,6 +107,9 @@ public function getIndexer($type)
*/
public function reindex($ids = null)
{
+ if (!$this->isEavIndexerEnabled()) {
+ return;
+ }
foreach ($this->getIndexers() as $indexer) {
if ($ids === null) {
$indexer->reindexAll();
@@ -147,4 +167,19 @@ protected function processRelations($indexer, $ids, $onlyParents = false)
$childIds = $onlyParents ? [] : $indexer->getRelationsByParent($parentIds);
return array_unique(array_merge($ids, $childIds, $parentIds));
}
+
+ /**
+ * Get EAV indexer status
+ *
+ * @return bool
+ */
+ private function isEavIndexerEnabled(): bool
+ {
+ $eavIndexerStatus = $this->scopeConfig->getValue(
+ self::ENABLE_EAV_INDEXER,
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+ );
+
+ return (bool)$eavIndexerStatus;
+ }
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Action/Full.php
index bc747e62f641e..802176092d147 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Action/Full.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Eav/Action/Full.php
@@ -3,12 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Catalog\Model\Indexer\Product\Eav\Action;
use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher;
/**
* Class Full reindex action
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Full extends \Magento\Catalog\Model\Indexer\Product\Eav\AbstractAction
{
@@ -32,6 +35,11 @@ class Full extends \Magento\Catalog\Model\Indexer\Product\Eav\AbstractAction
*/
private $activeTableSwitcher;
+ /**
+ * @var \Magento\Framework\App\Config\ScopeConfigInterface
+ */
+ private $scopeConfig;
+
/**
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory $eavDecimalFactory
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory $eavSourceFactory
@@ -39,6 +47,7 @@ class Full extends \Magento\Catalog\Model\Indexer\Product\Eav\AbstractAction
* @param \Magento\Framework\Indexer\BatchProviderInterface|null $batchProvider
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\BatchSizeCalculator $batchSizeCalculator
* @param ActiveTableSwitcher|null $activeTableSwitcher
+ * @param \Magento\Framework\App\Config\ScopeConfigInterface|null $scopeConfig
*/
public function __construct(
\Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory $eavDecimalFactory,
@@ -46,9 +55,13 @@ public function __construct(
\Magento\Framework\EntityManager\MetadataPool $metadataPool = null,
\Magento\Framework\Indexer\BatchProviderInterface $batchProvider = null,
\Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\BatchSizeCalculator $batchSizeCalculator = null,
- ActiveTableSwitcher $activeTableSwitcher = null
+ ActiveTableSwitcher $activeTableSwitcher = null,
+ \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig = null
) {
- parent::__construct($eavDecimalFactory, $eavSourceFactory);
+ $this->scopeConfig = $scopeConfig ?: \Magento\Framework\App\ObjectManager::getInstance()->get(
+ \Magento\Framework\App\Config\ScopeConfigInterface::class
+ );
+ parent::__construct($eavDecimalFactory, $eavSourceFactory, $scopeConfig);
$this->metadataPool = $metadataPool ?: \Magento\Framework\App\ObjectManager::getInstance()->get(
\Magento\Framework\EntityManager\MetadataPool::class
);
@@ -73,6 +86,9 @@ public function __construct(
*/
public function execute($ids = null)
{
+ if (!$this->isEavIndexerEnabled()) {
+ return;
+ }
try {
foreach ($this->getIndexers() as $indexerName => $indexer) {
$connection = $indexer->getConnection();
@@ -129,4 +145,19 @@ protected function syncData($indexer, $destinationTable, $ids = null)
throw $e;
}
}
+
+ /**
+ * Get EAV indexer status
+ *
+ * @return bool
+ */
+ private function isEavIndexerEnabled(): bool
+ {
+ $eavIndexerStatus = $this->scopeConfig->getValue(
+ self::ENABLE_EAV_INDEXER,
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+ );
+
+ return (bool)$eavIndexerStatus;
+ }
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
index 3a1611299288c..f95807f615390 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
@@ -56,39 +56,36 @@ public function __construct(
* @return \Magento\Catalog\Model\Indexer\Product\Flat
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function write($storeId, $productId, $valueFieldSuffix = '')
{
$flatTable = $this->_productIndexerHelper->getFlatTableName($storeId);
+ $entityTableName = $this->_productIndexerHelper->getTable('catalog_product_entity');
$attributes = $this->_productIndexerHelper->getAttributes();
$eavAttributes = $this->_productIndexerHelper->getTablesStructure($attributes);
$updateData = [];
$describe = $this->_connection->describeTable($flatTable);
+ $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
+ $linkField = $metadata->getLinkField();
foreach ($eavAttributes as $tableName => $tableColumns) {
$columnsChunks = array_chunk($tableColumns, self::ATTRIBUTES_CHUNK_SIZE, true);
foreach ($columnsChunks as $columns) {
$select = $this->_connection->select();
- $selectValue = $this->_connection->select();
- $keyColumns = [
- 'entity_id' => 'e.entity_id',
- 'attribute_id' => 't.attribute_id',
- 'value' => $this->_connection->getIfNullSql('`t2`.`value`', '`t`.`value`'),
- ];
-
- if ($tableName != $this->_productIndexerHelper->getTable('catalog_product_entity')) {
+
+ if ($tableName != $entityTableName) {
$valueColumns = [];
$ids = [];
$select->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
- $keyColumns
- );
-
- $selectValue->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
- $keyColumns
+ ['e' => $entityTableName],
+ [
+ 'entity_id' => 'e.entity_id',
+ 'attribute_id' => 't.attribute_id',
+ 'value' => $this->_connection->getIfNullSql('`t2`.`value`', '`t`.`value`'),
+ ]
);
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
@@ -97,8 +94,7 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
$ids[$attribute->getId()] = $columnName;
}
}
- $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
- $select->joinLeft(
+ $select->joinInner(
['t' => $tableName],
sprintf('e.%s = t.%s ', $linkField, $linkField) . $this->_connection->quoteInto(
' AND t.attribute_id IN (?)',
@@ -116,8 +112,6 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
[]
)->where(
'e.entity_id = ' . $productId
- )->where(
- 't.attribute_id IS NOT NULL'
);
$cursor = $this->_connection->query($select);
while ($row = $cursor->fetch(\Zend_Db::FETCH_ASSOC)) {
@@ -157,7 +151,7 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
$columnNames[] = 'attribute_set_id';
$columnNames[] = 'type_id';
$select->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
+ ['e' => $entityTableName],
$columnNames
)->where(
'e.entity_id = ' . $productId
@@ -175,7 +169,9 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
if (!empty($updateData)) {
$updateData += ['entity_id' => $productId];
- $updateData += ['row_id' => $productId];
+ if ($linkField !== $metadata->getIdentifierField()) {
+ $updateData += [$linkField => $productId];
+ }
$updateFields = [];
foreach ($updateData as $key => $value) {
$updateFields[$key] = $key;
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
index 709f27d031ebe..6d0727259d9db 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
@@ -5,16 +5,20 @@
*/
namespace Magento\Catalog\Model\Indexer\Product\Flat\Action;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Indexer\Product\Flat\FlatTableBuilder;
use Magento\Catalog\Model\Indexer\Product\Flat\TableBuilder;
+use Magento\Framework\EntityManager\MetadataPool;
/**
- * Class Row reindex action
+ * Class Row reindex action.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
{
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Indexer
+ * @var Indexer
*/
protected $flatItemWriter;
@@ -23,6 +27,11 @@ class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
*/
protected $flatItemEraser;
+ /**
+ * @var MetadataPool
+ */
+ private $metadataPool;
+
/**
* @param \Magento\Framework\App\ResourceConnection $resource
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -32,6 +41,7 @@ class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
* @param FlatTableBuilder $flatTableBuilder
* @param Indexer $flatItemWriter
* @param Eraser $flatItemEraser
+ * @param MetadataPool|null $metadataPool
*/
public function __construct(
\Magento\Framework\App\ResourceConnection $resource,
@@ -41,7 +51,8 @@ public function __construct(
TableBuilder $tableBuilder,
FlatTableBuilder $flatTableBuilder,
Indexer $flatItemWriter,
- Eraser $flatItemEraser
+ Eraser $flatItemEraser,
+ MetadataPool $metadataPool = null
) {
parent::__construct(
$resource,
@@ -53,6 +64,8 @@ public function __construct(
);
$this->flatItemWriter = $flatItemWriter;
$this->flatItemEraser = $flatItemEraser;
+ $this->metadataPool = $metadataPool ?:
+ \Magento\Framework\App\ObjectManager::getInstance()->get(MetadataPool::class);
}
/**
@@ -61,7 +74,6 @@ public function __construct(
* @param int|null $id
* @return \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row
* @throws \Magento\Framework\Exception\LocalizedException
- * @throws \Zend_Db_Statement_Exception
*/
public function execute($id = null)
{
@@ -71,50 +83,47 @@ public function execute($id = null)
);
}
$ids = [$id];
- foreach ($this->_storeManager->getStores() as $store) {
+ $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
+
+ $stores = $this->_storeManager->getStores();
+ foreach ($stores as $store) {
$tableExists = $this->_isFlatTableExists($store->getId());
if ($tableExists) {
$this->flatItemEraser->removeDeletedProducts($ids, $store->getId());
}
/* @var $status \Magento\Eav\Model\Entity\Attribute */
- $status = $this->_productIndexerHelper->getAttribute('status');
+ $status = $this->_productIndexerHelper->getAttribute(ProductInterface::STATUS);
$statusTable = $status->getBackend()->getTable();
$statusConditions = [
'store_id IN(0,' . (int)$store->getId() . ')',
'attribute_id = ' . (int)$status->getId(),
- 'entity_id = ' . (int)$id
+ $linkField . ' = ' . (int)$id,
];
$select = $this->_connection->select();
- $select->from(
- $statusTable,
- ['value']
- )->where(
- implode(' AND ', $statusConditions)
- )->order(
- 'store_id DESC'
- );
+ $select->from($statusTable, ['value'])
+ ->where(implode(' AND ', $statusConditions))
+ ->order('store_id DESC')
+ ->limit(1);
$result = $this->_connection->query($select);
- $status = $result->fetch(1);
+ $status = $result->fetchColumn(0);
- if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) {
- if (isset($ids[0])) {
- if (!$tableExists) {
- $this->_flatTableBuilder->build(
- $store->getId(),
- [$ids[0]],
- $this->_valueFieldSuffix,
- $this->_tableDropSuffix,
- false
- );
- }
- $this->flatItemWriter->write($store->getId(), $ids[0], $this->_valueFieldSuffix);
+ if ($status == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) {
+ if (!$tableExists) {
+ $this->_flatTableBuilder->build(
+ $store->getId(),
+ $ids,
+ $this->_valueFieldSuffix,
+ $this->_tableDropSuffix,
+ false
+ );
}
- }
- if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) {
+ $this->flatItemWriter->write($store->getId(), $id, $this->_valueFieldSuffix);
+ } else {
$this->flatItemEraser->deleteProductsFromStore($id, $store->getId());
}
}
+
return $this;
}
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php
index 6eb61bab85514..e9a907f0b5097 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php
@@ -160,7 +160,7 @@ protected function _syncData(array $processIds = [])
{
// for backward compatibility split data from old idx table on dimension tables
foreach ($this->dimensionCollectionFactory->create() as $dimensions) {
- $insertSelect = $this->_connection->select()->from(
+ $insertSelect = $this->getConnection()->select()->from(
['ip_tmp' => $this->_defaultIndexerResource->getIdxTable()]
);
@@ -174,7 +174,7 @@ protected function _syncData(array $processIds = [])
}
$query = $insertSelect->insertFromSelect($this->tableMaintainer->getMainTable($dimensions));
- $this->_connection->query($query);
+ $this->getConnection()->query($query);
}
return $this;
}
@@ -191,7 +191,7 @@ protected function _prepareWebsiteDateTable()
{
$baseCurrency = $this->_config->getValue(\Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE);
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
['cw' => $this->_defaultIndexerResource->getTable('store_website')],
['website_id']
)->join(
@@ -203,7 +203,7 @@ protected function _prepareWebsiteDateTable()
);
$data = [];
- foreach ($this->_connection->fetchAll($select) as $item) {
+ foreach ($this->getConnection()->fetchAll($select) as $item) {
/** @var $website \Magento\Store\Model\Website */
$website = $this->_storeManager->getWebsite($item['website_id']);
@@ -237,7 +237,7 @@ protected function _prepareWebsiteDateTable()
$this->_emptyTable($table);
if ($data) {
foreach ($data as $row) {
- $this->_connection->insertOnDuplicate($table, $row, array_keys($row));
+ $this->getConnection()->insertOnDuplicate($table, $row, array_keys($row));
}
}
@@ -325,19 +325,19 @@ protected function _getIndexer($productTypeId)
*/
protected function _insertFromTable($sourceTable, $destTable, $where = null)
{
- $sourceColumns = array_keys($this->_connection->describeTable($sourceTable));
- $targetColumns = array_keys($this->_connection->describeTable($destTable));
- $select = $this->_connection->select()->from($sourceTable, $sourceColumns);
+ $sourceColumns = array_keys($this->getConnection()->describeTable($sourceTable));
+ $targetColumns = array_keys($this->getConnection()->describeTable($destTable));
+ $select = $this->getConnection()->select()->from($sourceTable, $sourceColumns);
if ($where) {
$select->where($where);
}
- $query = $this->_connection->insertFromSelect(
+ $query = $this->getConnection()->insertFromSelect(
$select,
$destTable,
$targetColumns,
\Magento\Framework\DB\Adapter\AdapterInterface::INSERT_ON_DUPLICATE
);
- $this->_connection->query($query);
+ $this->getConnection()->query($query);
}
/**
@@ -348,7 +348,7 @@ protected function _insertFromTable($sourceTable, $destTable, $where = null)
*/
protected function _emptyTable($table)
{
- $this->_connection->delete($table);
+ $this->getConnection()->delete($table);
}
/**
@@ -381,7 +381,7 @@ protected function _reindexRows($changedIds = [])
$this->tableMaintainer->createMainTmpTable($dimensions);
$temporaryTable = $this->tableMaintainer->getMainTmpTable($dimensions);
$this->_emptyTable($temporaryTable);
- $indexer->executeByDimension($dimensions, \SplFixedArray::fromArray($entityIds, false));
+ $indexer->executeByDimensions($dimensions, \SplFixedArray::fromArray($entityIds, false));
// copy to index
$this->_insertFromTable(
$temporaryTable,
@@ -407,12 +407,12 @@ protected function _reindexRows($changedIds = [])
private function deleteIndexData(array $entityIds)
{
foreach ($this->dimensionCollectionFactory->create() as $dimensions) {
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
['index_price' => $this->tableMaintainer->getMainTable($dimensions)],
null
)->where('index_price.entity_id IN (?)', $entityIds);
$query = $select->deleteFromSelect('index_price');
- $this->_connection->query($query);
+ $this->getConnection()->query($query);
}
}
@@ -430,7 +430,7 @@ private function deleteIndexData(array $entityIds)
protected function _copyRelationIndexData($parentIds, $excludeIds = null)
{
$linkField = $this->getProductIdFieldName();
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
$this->_defaultIndexerResource->getTable('catalog_product_relation'),
['child_id']
)->join(
@@ -445,18 +445,18 @@ protected function _copyRelationIndexData($parentIds, $excludeIds = null)
$select->where('child_id NOT IN(?)', $excludeIds);
}
- $children = $this->_connection->fetchCol($select);
+ $children = $this->getConnection()->fetchCol($select);
if ($children) {
foreach ($this->dimensionCollectionFactory->create() as $dimensions) {
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
$this->getIndexTargetTableByDimension($dimensions)
)->where(
'entity_id IN(?)',
$children
);
$query = $select->insertFromSelect($this->_defaultIndexerResource->getIdxTable(), [], false);
- $this->_connection->query($query);
+ $this->getConnection()->query($query);
}
}
@@ -502,8 +502,8 @@ protected function getIndexTargetTable()
protected function getProductIdFieldName()
{
$table = $this->_defaultIndexerResource->getTable('catalog_product_entity');
- $indexList = $this->_connection->getIndexList($table);
- return $indexList[$this->_connection->getPrimaryKeyName($table)]['COLUMNS_LIST'][0];
+ $indexList = $this->getConnection()->getIndexList($table);
+ return $indexList[$this->getConnection()->getPrimaryKeyName($table)]['COLUMNS_LIST'][0];
}
/**
@@ -514,14 +514,14 @@ protected function getProductIdFieldName()
*/
private function getProductsTypes(array $changedIds = [])
{
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
$this->_defaultIndexerResource->getTable('catalog_product_entity'),
['entity_id', 'type_id']
);
if ($changedIds) {
$select->where('entity_id IN (?)', $changedIds);
}
- $pairs = $this->_connection->fetchPairs($select);
+ $pairs = $this->getConnection()->fetchPairs($select);
$byType = [];
foreach ($pairs as $productId => $productType) {
@@ -540,7 +540,7 @@ private function getProductsTypes(array $changedIds = [])
*/
private function getParentProductsTypes(array $productsIds)
{
- $select = $this->_connection->select()->from(
+ $select = $this->getConnection()->select()->from(
['l' => $this->_defaultIndexerResource->getTable('catalog_product_relation')],
''
)->join(
@@ -551,7 +551,7 @@ private function getParentProductsTypes(array $productsIds)
'l.child_id IN(?)',
$productsIds
);
- $pairs = $this->_connection->fetchPairs($select);
+ $pairs = $this->getConnection()->fetchPairs($select);
$byType = [];
foreach ($pairs as $productId => $productType) {
@@ -560,4 +560,14 @@ private function getParentProductsTypes(array $productsIds)
return $byType;
}
+
+ /**
+ * Get connection
+ *
+ * @return \Magento\Framework\DB\Adapter\AdapterInterface
+ */
+ private function getConnection()
+ {
+ return $this->_defaultIndexerResource->getConnection();
+ }
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php
index 411b89d7981cc..1a75751570658 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php
@@ -56,6 +56,11 @@ class Full extends \Magento\Catalog\Model\Indexer\Product\Price\AbstractAction
*/
private $dimensionTableMaintainer;
+ /**
+ * @var \Magento\Indexer\Model\ProcessManager
+ */
+ private $processManager;
+
/**
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -71,7 +76,7 @@ class Full extends \Magento\Catalog\Model\Indexer\Product\Price\AbstractAction
* @param \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher|null $activeTableSwitcher
* @param \Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory|null $dimensionCollectionFactory
* @param \Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer|null $dimensionTableMaintainer
- *
+ * @param \Magento\Indexer\Model\ProcessManager $processManager
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -88,7 +93,8 @@ public function __construct(
\Magento\Framework\Indexer\BatchProviderInterface $batchProvider = null,
\Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher $activeTableSwitcher = null,
\Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory $dimensionCollectionFactory = null,
- \Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer $dimensionTableMaintainer = null
+ \Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer $dimensionTableMaintainer = null,
+ \Magento\Indexer\Model\ProcessManager $processManager = null
) {
parent::__construct(
$config,
@@ -118,6 +124,9 @@ public function __construct(
$this->dimensionTableMaintainer = $dimensionTableMaintainer ?: ObjectManager::getInstance()->get(
\Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer::class
);
+ $this->processManager = $processManager ?: ObjectManager::getInstance()->get(
+ \Magento\Indexer\Model\ProcessManager::class
+ );
}
/**
@@ -195,9 +204,13 @@ private function truncateReplicaTables()
*/
private function reindexProductTypeWithDimensions(DimensionalIndexerInterface $priceIndexer, string $typeId)
{
+ $userFunctions = [];
foreach ($this->dimensionCollectionFactory->create() as $dimensions) {
- $this->reindexByBatches($priceIndexer, $dimensions, $typeId);
+ $userFunctions[] = function () use ($priceIndexer, $dimensions, $typeId) {
+ return $this->reindexByBatches($priceIndexer, $dimensions, $typeId);
+ };
}
+ $this->processManager->execute($userFunctions);
}
/**
@@ -263,7 +276,7 @@ private function reindexByBatchWithDimensions(
$temporaryTable = $this->dimensionTableMaintainer->getMainTmpTable($dimensions);
$this->_emptyTable($temporaryTable);
- $priceIndexer->executeByDimension($dimensions, \SplFixedArray::fromArray($entityIds, false));
+ $priceIndexer->executeByDimensions($dimensions, \SplFixedArray::fromArray($entityIds, false));
// Sync data from temp table to index table
$this->_insertFromTable(
@@ -413,13 +426,19 @@ private function switchTables()
private function moveDataFromReplicaTableToReplicaTables(array $dimensions)
{
if (!$dimensions) {
- return ;
+ return;
}
- //TODO: need to update logic for run this move only when replica table is not empty
$select = $this->dimensionTableMaintainer->getConnection()->select()->from(
$this->dimensionTableMaintainer->getMainReplicaTable([])
);
+ $check = clone $select;
+ $check->reset('columns')->columns('count(*)');
+
+ if (!$this->dimensionTableMaintainer->getConnection()->query($check)->fetchColumn()) {
+ return;
+ }
+
$replicaTablesByDimension = $this->dimensionTableMaintainer->getMainReplicaTable($dimensions);
foreach ($dimensions as $dimension) {
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/DimensionModeConfiguration.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/DimensionModeConfiguration.php
index e5935dac92a36..7a4d8e313462d 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/DimensionModeConfiguration.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/DimensionModeConfiguration.php
@@ -40,6 +40,7 @@ class DimensionModeConfiguration
CustomerGroupDimensionProvider::DIMENSION_NAME
],
];
+
/**
* @var ScopeConfigInterface
*/
@@ -58,12 +59,23 @@ public function __construct(ScopeConfigInterface $scopeConfig)
$this->scopeConfig = $scopeConfig;
}
+ /**
+ * Return dimension modes configuration.
+ *
+ * @return array
+ */
+ public function getDimensionModes(): array
+ {
+ return $this->modesMapping;
+ }
+
/**
* Get names of dimensions which used for provided mode.
* By default return dimensions for current enabled mode
*
* @param string|null $mode
* @return string[]
+ * @throws \InvalidArgumentException
*/
public function getDimensionConfiguration(string $mode = null): array
{
@@ -81,7 +93,7 @@ public function getDimensionConfiguration(string $mode = null): array
private function getCurrentMode(): string
{
if (null === $this->currentMode) {
- $this->currentMode = $this->scopeConfig->getValue(ModeSwitcher::XML_PATH_PRICE_DIMENSIONS_MODE)
+ $this->currentMode = $this->scopeConfig->getValue(ModeSwitcherConfiguration::XML_PATH_PRICE_DIMENSIONS_MODE)
?: self::DIMENSION_NONE;
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcher.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcher.php
index d160a5859abe4..e71031489fa0e 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcher.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcher.php
@@ -3,21 +3,21 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-
declare(strict_types=1);
+
namespace Magento\Catalog\Model\Indexer\Product\Price;
use Magento\Framework\Search\Request\Dimension;
use Magento\Store\Model\Indexer\WebsiteDimensionProvider;
use Magento\Customer\Model\Indexer\CustomerGroupDimensionProvider;
+use Magento\Indexer\Model\DimensionModes;
+use Magento\Indexer\Model\DimensionMode;
/**
* Class to prepare new tables for new indexer mode
*/
-class ModeSwitcher
+class ModeSwitcher implements \Magento\Indexer\Model\ModeSwitcherInterface
{
- const XML_PATH_PRICE_DIMENSIONS_MODE = 'indexer/catalog_product_price/dimensions_mode';
-
/**
* TableMaintainer
*
@@ -38,15 +38,60 @@ class ModeSwitcher
private $dimensionsArray;
/**
- * @param \Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer $tableMaintainer
- * @param \Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory $dimensionCollectionFactory
+ * @var \Magento\Catalog\Model\Indexer\Product\Price\DimensionModeConfiguration
+ */
+ private $dimensionModeConfiguration;
+
+ /**
+ * @var ModeSwitcherConfiguration
+ */
+ private $modeSwitcherConfiguration;
+
+ /**
+ * @param TableMaintainer $tableMaintainer
+ * @param DimensionCollectionFactory $dimensionCollectionFactory
+ * @param DimensionModeConfiguration $dimensionModeConfiguration
+ * @param ModeSwitcherConfiguration $modeSwitcherConfiguration
*/
public function __construct(
- \Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer $tableMaintainer,
- \Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory $dimensionCollectionFactory
+ TableMaintainer $tableMaintainer,
+ DimensionCollectionFactory $dimensionCollectionFactory,
+ DimensionModeConfiguration $dimensionModeConfiguration,
+ ModeSwitcherConfiguration $modeSwitcherConfiguration
) {
$this->tableMaintainer = $tableMaintainer;
$this->dimensionCollectionFactory = $dimensionCollectionFactory;
+ $this->dimensionModeConfiguration = $dimensionModeConfiguration;
+ $this->modeSwitcherConfiguration = $modeSwitcherConfiguration;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDimensionModes(): DimensionModes
+ {
+ $dimensionsList = [];
+ foreach ($this->dimensionModeConfiguration->getDimensionModes() as $dimension => $modes) {
+ $dimensionsList[] = new DimensionMode($dimension, $modes);
+ }
+
+ return new DimensionModes($dimensionsList);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function switchMode(string $currentMode, string $previousMode)
+ {
+ //Create new tables and move data
+ $this->createTables($currentMode);
+ $this->moveData($currentMode, $previousMode);
+
+ //Change config options
+ $this->modeSwitcherConfiguration->saveMode($currentMode);
+
+ //Delete old tables
+ $this->dropTables($previousMode);
}
/**
@@ -55,6 +100,7 @@ public function __construct(
* @param string $currentMode
*
* @return void
+ * @throws \Zend_Db_Exception
*/
public function createTables(string $currentMode)
{
@@ -119,7 +165,7 @@ public function dropTables(string $previousMode)
*
* @param string $mode
*
- * @return array
+ * @return \Magento\Framework\Indexer\MultiDimensionProvider
*/
private function getDimensionsArray(string $mode): \Magento\Framework\Indexer\MultiDimensionProvider
{
@@ -154,7 +200,12 @@ private function insertFromOldTablesToNew(string $newTable, string $oldTable, ar
}
}
$this->tableMaintainer->getConnection()->query(
- $this->tableMaintainer->getConnection()->insertFromSelect($select, $newTable)
+ $this->tableMaintainer->getConnection()->insertFromSelect(
+ $select,
+ $newTable,
+ [],
+ \Magento\Framework\DB\Adapter\AdapterInterface::INSERT_ON_DUPLICATE
+ )
);
}
}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcherConfiguration.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcherConfiguration.php
new file mode 100644
index 0000000000000..66b7147a8db76
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/ModeSwitcherConfiguration.php
@@ -0,0 +1,70 @@
+configWriter = $configWriter;
+ $this->cacheTypeList = $cacheTypeList;
+ $this->indexer = $indexer;
+ }
+
+ /**
+ * Save switcher mode and invalidate reindex.
+ *
+ * @param string $mode
+ * @return void
+ * @throws \InvalidArgumentException
+ */
+ public function saveMode(string $mode)
+ {
+ //Change config options
+ $this->configWriter->saveConfig(self::XML_PATH_PRICE_DIMENSIONS_MODE, $mode);
+ $this->cacheTypeList->cleanType('config');
+ $this->indexer->load(\Magento\Catalog\Model\Indexer\Product\Price\Processor::INDEXER_ID);
+ $this->indexer->invalidate();
+ }
+}
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/TableMaintainer.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/TableMaintainer.php
index 337de6f6dd77f..999eaaa2a8025 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/TableMaintainer.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/TableMaintainer.php
@@ -183,7 +183,7 @@ public function getMainTable(array $dimensions): string
public function createTablesForDimensions(array $dimensions)
{
$mainTableName = $this->getMainTable($dimensions);
- //Create index table for dimensions based on on main replica table
+ //Create index table for dimensions based on main replica table
//Using main replica table is necessary for backward capability and TableResolver plugin work
$this->createTable(
$this->getTable(self::MAIN_INDEX_TABLE . $this->additionalTableSuffix),
diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/AbstractFilter.php b/app/code/Magento/Catalog/Model/Layer/Filter/AbstractFilter.php
index a4db630f0234b..d21a8666ec0ac 100644
--- a/app/code/Magento/Catalog/Model/Layer/Filter/AbstractFilter.php
+++ b/app/code/Magento/Catalog/Model/Layer/Filter/AbstractFilter.php
@@ -241,7 +241,7 @@ protected function _createItem($label, $value, $count = 0)
}
/**
- * Get all product ids from from collection with applied filters
+ * Get all product ids from collection with applied filters
*
* @return array
*/
diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php
index c454c09fc7b75..e4dacf275fc9b 100644
--- a/app/code/Magento/Catalog/Model/Product.php
+++ b/app/code/Magento/Catalog/Model/Product.php
@@ -525,9 +525,9 @@ protected function getCustomAttributesCodes()
public function getStoreId()
{
if ($this->hasData(self::STORE_ID)) {
- return $this->getData(self::STORE_ID);
+ return (int)$this->getData(self::STORE_ID);
}
- return $this->_storeManager->getStore()->getId();
+ return (int)$this->_storeManager->getStore()->getId();
}
/**
@@ -809,6 +809,9 @@ public function getStoreIds()
if (!$this->hasStoreIds()) {
$storeIds = [];
if ($websiteIds = $this->getWebsiteIds()) {
+ if ($this->_storeManager->isSingleStoreMode()) {
+ $websiteIds = array_keys($websiteIds);
+ }
foreach ($websiteIds as $websiteId) {
$websiteStores = $this->_storeManager->getWebsite($websiteId)->getStoreIds();
$storeIds = array_merge($storeIds, $websiteStores);
@@ -1149,11 +1152,24 @@ public function getTierPrice($qty = null)
/**
* Get formatted by currency product price
*
- * @return array || double
+ * @return array|double
+ */
+ public function getFormattedPrice()
+ {
+ return $this->getPriceModel()->getFormattedPrice($this);
+ }
+
+ /**
+ * Get formatted by currency product price
+ *
+ * @return array|double
+ *
+ * @deprecated
+ * @see getFormattedPrice()
*/
public function getFormatedPrice()
{
- return $this->getPriceModel()->getFormatedPrice($this);
+ return $this->getFormattedPrice();
}
/**
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/GroupPrice/AbstractGroupPrice.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/GroupPrice/AbstractGroupPrice.php
index 84770a4a93ed4..4c7c1c5bcf592 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/GroupPrice/AbstractGroupPrice.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/GroupPrice/AbstractGroupPrice.php
@@ -375,118 +375,10 @@ protected function modifyPriceData($object, $data)
*
* @param \Magento\Catalog\Model\Product $object
* @return $this
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterSave($object)
{
- $websiteId = $this->_storeManager->getStore($object->getStoreId())->getWebsiteId();
- $isGlobal = $this->getAttribute()->isScopeGlobal() || $websiteId == 0;
-
- $priceRows = $object->getData($this->getAttribute()->getName());
- if (null === $priceRows) {
- return $this;
- }
-
- $priceRows = array_filter((array)$priceRows);
-
- $old = [];
- $new = [];
-
- // prepare original data for compare
- $origPrices = $object->getOrigData($this->getAttribute()->getName());
- if (!is_array($origPrices)) {
- $origPrices = [];
- }
- foreach ($origPrices as $data) {
- if ($data['website_id'] > 0 || $data['website_id'] == '0' && $isGlobal) {
- $key = implode(
- '-',
- array_merge(
- [$data['website_id'], $data['cust_group']],
- $this->_getAdditionalUniqueFields($data)
- )
- );
- $old[$key] = $data;
- }
- }
-
- // prepare data for save
- foreach ($priceRows as $data) {
- $hasEmptyData = false;
- foreach ($this->_getAdditionalUniqueFields($data) as $field) {
- if (empty($field)) {
- $hasEmptyData = true;
- break;
- }
- }
-
- if ($hasEmptyData || !isset($data['cust_group']) || !empty($data['delete'])) {
- continue;
- }
- if ($this->getAttribute()->isScopeGlobal() && $data['website_id'] > 0) {
- continue;
- }
- if (!$isGlobal && (int)$data['website_id'] == 0) {
- continue;
- }
-
- $key = implode(
- '-',
- array_merge([$data['website_id'], $data['cust_group']], $this->_getAdditionalUniqueFields($data))
- );
-
- $useForAllGroups = $data['cust_group'] == $this->_groupManagement->getAllCustomersGroup()->getId();
- $customerGroupId = !$useForAllGroups ? $data['cust_group'] : 0;
- $new[$key] = array_merge(
- $this->getAdditionalFields($data),
- [
- 'website_id' => $data['website_id'],
- 'all_groups' => $useForAllGroups ? 1 : 0,
- 'customer_group_id' => $customerGroupId,
- 'value' => isset($data['price']) ? $data['price'] : null,
- ],
- $this->_getAdditionalUniqueFields($data)
- );
- }
-
- $delete = array_diff_key($old, $new);
- $insert = array_diff_key($new, $old);
- $update = array_intersect_key($new, $old);
-
- $isChanged = false;
- $productId = $object->getData($this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField());
-
- if (!empty($delete)) {
- foreach ($delete as $data) {
- $this->_getResource()->deletePriceData($productId, null, $data['price_id']);
- $isChanged = true;
- }
- }
-
- if (!empty($insert)) {
- foreach ($insert as $data) {
- $price = new \Magento\Framework\DataObject($data);
- $price->setData(
- $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(),
- $productId
- );
- $this->_getResource()->savePriceData($price);
-
- $isChanged = true;
- }
- }
-
- if (!empty($update)) {
- $isChanged |= $this->updateValues($update, $old);
- }
-
- if ($isChanged) {
- $valueChangedKey = $this->getAttribute()->getName() . '_changed';
- $object->setData($valueChangedKey, 1);
- }
-
return $this;
}
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/SaveHandler.php
new file mode 100644
index 0000000000000..587865414129a
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/SaveHandler.php
@@ -0,0 +1,168 @@
+storeManager = $storeManager;
+ $this->attributeRepository = $attributeRepository;
+ $this->groupManagement = $groupManagement;
+ $this->metadataPoll = $metadataPool;
+ $this->tierPriceResource = $tierPriceResource;
+ }
+
+ /**
+ * Set tier price data for product entity
+ *
+ * @param \Magento\Catalog\Api\Data\ProductInterface|object $entity
+ * @param array $arguments
+ * @return \Magento\Catalog\Api\Data\ProductInterface|object
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws \Magento\Framework\Exception\InputException
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function execute($entity, $arguments = [])
+ {
+ $attribute = $this->attributeRepository->get('tier_price');
+ $priceRows = $entity->getData($attribute->getName());
+ if (null !== $priceRows) {
+ if (!is_array($priceRows)) {
+ throw new \Magento\Framework\Exception\InputException(
+ __('Tier prices data should be array, but actually other type is received')
+ );
+ }
+ $websiteId = $this->storeManager->getStore($entity->getStoreId())->getWebsiteId();
+ $isGlobal = $attribute->isScopeGlobal() || $websiteId === 0;
+ $identifierField = $this->metadataPoll->getMetadata(ProductInterface::class)->getLinkField();
+ $priceRows = array_filter($priceRows);
+ $productId = $entity->getData($identifierField);
+
+ // prepare and save data
+ foreach ($priceRows as $data) {
+ $isPriceWebsiteGlobal = (int)$data['website_id'] === 0;
+ if ($isGlobal === $isPriceWebsiteGlobal
+ || !empty($data['price_qty'])
+ || isset($data['cust_group'])
+ ) {
+ $tierPrice = $this->prepareTierPrice($data);
+ $price = new \Magento\Framework\DataObject($tierPrice);
+ $price->setData(
+ $identifierField,
+ $productId
+ );
+ $this->tierPriceResource->savePriceData($price);
+ $valueChangedKey = $attribute->getName() . '_changed';
+ $entity->setData($valueChangedKey, 1);
+ }
+ }
+ }
+
+ return $entity;
+ }
+
+ /**
+ * Get additional tier price fields
+ *
+ * @return array
+ */
+ private function getAdditionalFields(array $objectArray): array
+ {
+ $percentageValue = $this->getPercentage($objectArray);
+ return [
+ 'value' => $percentageValue ? null : $objectArray['price'],
+ 'percentage_value' => $percentageValue ?: null,
+ ];
+ }
+
+ /**
+ * Check whether price has percentage value.
+ *
+ * @param array $priceRow
+ * @return integer|null
+ */
+ private function getPercentage(array $priceRow)
+ {
+ return isset($priceRow['percentage_value']) && is_numeric($priceRow['percentage_value'])
+ ? (int)$priceRow['percentage_value']
+ : null;
+ }
+
+ /**
+ * Prepare tier price data by provided price row data
+ *
+ * @param array $data
+ * @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ private function prepareTierPrice(array $data): array
+ {
+ $useForAllGroups = (int)$data['cust_group'] === $this->groupManagement->getAllCustomersGroup()->getId();
+ $customerGroupId = $useForAllGroups ? 0 : $data['cust_group'];
+ $tierPrice = array_merge(
+ $this->getAdditionalFields($data),
+ [
+ 'website_id' => $data['website_id'],
+ 'all_groups' => (int)$useForAllGroups,
+ 'customer_group_id' => $customerGroupId,
+ 'value' => $data['price'] ?? null,
+ 'qty' => (int)$data['price_qty']
+ ]
+ );
+
+ return $tierPrice;
+ }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php
new file mode 100644
index 0000000000000..b23dc6f30f8fa
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php
@@ -0,0 +1,307 @@
+storeManager = $storeManager;
+ $this->attributeRepository = $attributeRepository;
+ $this->groupManagement = $groupManagement;
+ $this->metadataPoll = $metadataPool;
+ $this->tierPriceResource = $tierPriceResource;
+ }
+
+ /**
+ * @param \Magento\Catalog\Api\Data\ProductInterface|object $entity
+ * @param array $arguments
+ * @return \Magento\Catalog\Api\Data\ProductInterface|object
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function execute($entity, $arguments = [])
+ {
+ $attribute = $this->attributeRepository->get('tier_price');
+ $priceRows = $entity->getData($attribute->getName());
+ if (null !== $priceRows) {
+ if (!is_array($priceRows)) {
+ throw new \Magento\Framework\Exception\InputException(
+ __('Tier prices data should be array, but actually other type is received')
+ );
+ }
+ $websiteId = $this->storeManager->getStore($entity->getStoreId())->getWebsiteId();
+ $isGlobal = $attribute->isScopeGlobal() || $websiteId === 0;
+ $identifierField = $this->metadataPoll->getMetadata(ProductInterface::class)->getLinkField();
+ $productId = $entity->getData($identifierField);
+
+ // prepare original data to compare
+ $origPrices = $entity->getOrigData($attribute->getName());
+ $old = $this->prepareOriginalDataToCompare($origPrices, $isGlobal);
+ // prepare data for save
+ $new = $this->prepareNewDataForSave($priceRows, $isGlobal);
+
+ $delete = array_diff_key($old, $new);
+ $insert = array_diff_key($new, $old);
+ $update = array_intersect_key($new, $old);
+
+ $isAttributeChanged = $this->deleteValues($productId, $delete);
+ $isAttributeChanged |= $this->insertValues($productId, $insert);
+ $isAttributeChanged |= $this->updateValues($update, $old);
+
+ if ($isAttributeChanged) {
+ $valueChangedKey = $attribute->getName() . '_changed';
+ $entity->setData($valueChangedKey, 1);
+ }
+ }
+
+ return $entity;
+ }
+
+ /**
+ * Get additional tier price fields
+ *
+ * @param array $objectArray
+ * @return array
+ */
+ private function getAdditionalFields(array $objectArray): array
+ {
+ $percentageValue = $this->getPercentage($objectArray);
+ return [
+ 'value' => $percentageValue ? null : $objectArray['price'],
+ 'percentage_value' => $percentageValue ?: null,
+ ];
+ }
+
+ /**
+ * Check whether price has percentage value.
+ *
+ * @param array $priceRow
+ * @return integer|null
+ */
+ private function getPercentage(array $priceRow)
+ {
+ return isset($priceRow['percentage_value']) && is_numeric($priceRow['percentage_value'])
+ ? (int)$priceRow['percentage_value']
+ : null;
+ }
+
+ /**
+ * Update existing tier prices for processed product
+ *
+ * @param array $valuesToUpdate
+ * @param array $oldValues
+ * @return boolean
+ */
+ private function updateValues(array $valuesToUpdate, array $oldValues): bool
+ {
+ $isChanged = false;
+ foreach ($valuesToUpdate as $key => $value) {
+ if ((!empty($value['value']) && (float)$oldValues[$key]['price'] !== (float)$value['value'])
+ || $this->getPercentage($oldValues[$key]) !== $this->getPercentage($value)
+ ) {
+ $price = new \Magento\Framework\DataObject(
+ [
+ 'value_id' => $oldValues[$key]['price_id'],
+ 'value' => $value['value'],
+ 'percentage_value' => $this->getPercentage($value)
+ ]
+ );
+ $this->tierPriceResource->savePriceData($price);
+ $isChanged = true;
+ }
+ }
+
+ return $isChanged;
+ }
+
+ /**
+ * Insert new tier prices for processed product
+ *
+ * @param int $productId
+ * @param array $valuesToInsert
+ * @return bool
+ */
+ private function insertValues(int $productId, array $valuesToInsert): bool
+ {
+ $isChanged = false;
+ $identifierField = $this->metadataPoll->getMetadata(ProductInterface::class)->getLinkField();
+ foreach ($valuesToInsert as $data) {
+ $price = new \Magento\Framework\DataObject($data);
+ $price->setData(
+ $identifierField,
+ $productId
+ );
+ $this->tierPriceResource->savePriceData($price);
+ $isChanged = true;
+ }
+
+ return $isChanged;
+ }
+
+ /**
+ * Delete tier price values for processed product
+ *
+ * @param int $productId
+ * @param array $valuesToDelete
+ * @return bool
+ */
+ private function deleteValues(int $productId, array $valuesToDelete): bool
+ {
+ $isChanged = false;
+ foreach ($valuesToDelete as $data) {
+ $this->tierPriceResource->deletePriceData($productId, null, $data['price_id']);
+ $isChanged = true;
+ }
+
+ return $isChanged;
+ }
+
+ /**
+ * Get generated price key based on price data
+ *
+ * @param array $priceData
+ * @return string
+ */
+ private function getPriceKey(array $priceData): string
+ {
+ $key = implode(
+ '-',
+ array_merge([$priceData['website_id'], $priceData['cust_group']], [(int)$priceData['price_qty']])
+ );
+
+ return $key;
+ }
+
+ /**
+ * Prepare tier price data by provided price row data
+ *
+ * @param array $data
+ * @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ private function prepareTierPrice(array $data): array
+ {
+ $useForAllGroups = (int)$data['cust_group'] === $this->groupManagement->getAllCustomersGroup()->getId();
+ $customerGroupId = $useForAllGroups ? 0 : $data['cust_group'];
+ $tierPrice = array_merge(
+ $this->getAdditionalFields($data),
+ [
+ 'website_id' => $data['website_id'],
+ 'all_groups' => (int)$useForAllGroups,
+ 'customer_group_id' => $customerGroupId,
+ 'value' => $data['price'] ?? null,
+ 'qty' => (int)$data['price_qty']
+ ]
+ );
+
+ return $tierPrice;
+ }
+
+ /**
+ * Check by id is website global
+ *
+ * @param int $websiteId
+ * @return bool
+ */
+ private function isWebsiteGlobal(int $websiteId): bool
+ {
+ return $websiteId === 0;
+ }
+
+ /**
+ * @param array|null $origPrices
+ * @param bool $isGlobal
+ * @return array
+ */
+ private function prepareOriginalDataToCompare($origPrices, $isGlobal = true): array
+ {
+ $old = [];
+ if (is_array($origPrices)) {
+ foreach ($origPrices as $data) {
+ if ($isGlobal === $this->isWebsiteGlobal((int)$data['website_id'])) {
+ $key = $this->getPriceKey($data);
+ $old[$key] = $data;
+ }
+ }
+ }
+
+ return $old;
+ }
+
+ /**
+ * @param array $priceRows
+ * @param bool $isGlobal
+ * @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ private function prepareNewDataForSave($priceRows, $isGlobal = true): array
+ {
+ $new = [];
+ $priceRows = array_filter($priceRows);
+ foreach ($priceRows as $data) {
+ if (empty($data['delete'])
+ && (!empty($data['price_qty'])
+ || isset($data['cust_group'])
+ || $isGlobal === $this->isWebsiteGlobal((int)$data['website_id']))
+ ) {
+ $key = $this->getPriceKey($data);
+ $new[$key] = $this->prepareTierPrice($data);
+ }
+ }
+
+ return $new;
+ }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Compare/Item.php b/app/code/Magento/Catalog/Model/Product/Compare/Item.php
index 8f18780ef8f71..777ed0fbe393b 100644
--- a/app/code/Magento/Catalog/Model/Product/Compare/Item.php
+++ b/app/code/Magento/Catalog/Model/Product/Compare/Item.php
@@ -158,8 +158,8 @@ public function addProductData($product)
{
if ($product instanceof Product) {
$this->setProductId($product->getId());
- } elseif (intval($product)) {
- $this->setProductId(intval($product));
+ } elseif ((int)$product) {
+ $this->setProductId((int)$product);
}
return $this;
diff --git a/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverComposite.php b/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverComposite.php
new file mode 100644
index 0000000000000..ec500ac2f2030
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverComposite.php
@@ -0,0 +1,68 @@
+itemResolvers = $itemResolvers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFinalProduct(ItemInterface $item): ProductInterface
+ {
+ $finalProduct = $item->getProduct();
+
+ foreach ($this->itemResolvers as $resolver) {
+ $resolvedProduct = $this->getItemResolverInstance($resolver)->getFinalProduct($item);
+ if ($resolvedProduct !== $finalProduct) {
+ $finalProduct = $resolvedProduct;
+ break;
+ }
+ }
+
+ return $finalProduct;
+ }
+
+ /**
+ * Get the instance of the item resolver by class name.
+ *
+ * @param string $className
+ * @return ItemResolverInterface
+ */
+ private function getItemResolverInstance(string $className): ItemResolverInterface
+ {
+ if (!isset($this->itemResolversInstances[$className])) {
+ $this->itemResolversInstances[$className] = ObjectManager::getInstance()->get($className);
+ }
+
+ return $this->itemResolversInstances[$className];
+ }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverInterface.php b/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverInterface.php
new file mode 100644
index 0000000000000..9e6de01bb5112
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Configuration/Item/ItemResolverInterface.php
@@ -0,0 +1,26 @@
+getImageProcessor()->rotate($angle);
return $this;
}
diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php
index 6d29eedc9885d..2b72a6ca4e8ae 100644
--- a/app/code/Magento/Catalog/Model/Product/Option.php
+++ b/app/code/Magento/Catalog/Model/Product/Option.php
@@ -8,6 +8,7 @@
use Magento\Catalog\Api\Data\ProductCustomOptionInterface;
use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface;
+use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterfaceFactory;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection;
@@ -102,6 +103,11 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
*/
private $metadataPool;
+ /**
+ * @var ProductCustomOptionValuesInterfaceFactory
+ */
+ private $customOptionValuesFactory;
+
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
@@ -114,6 +120,7 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
+ * @param ProductCustomOptionValuesInterfaceFactory|null $customOptionValuesFactory
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -127,12 +134,16 @@ public function __construct(
Option\Validator\Pool $validatorPool,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
- array $data = []
+ array $data = [],
+ ProductCustomOptionValuesInterfaceFactory $customOptionValuesFactory = null
) {
$this->productOptionValue = $productOptionValue;
$this->optionTypeFactory = $optionFactory;
$this->validatorPool = $validatorPool;
$this->string = $string;
+ $this->customOptionValuesFactory = $customOptionValuesFactory ?:
+ \Magento\Framework\App\ObjectManager::getInstance()->get(ProductCustomOptionValuesInterfaceFactory::class);
+
parent::__construct(
$context,
$registry,
@@ -312,7 +323,7 @@ public function getGroupByType($type = null)
self::OPTION_TYPE_TIME => self::OPTION_GROUP_DATE,
];
- return isset($optionGroupsToTypes[$type]) ? $optionGroupsToTypes[$type] : '';
+ return $optionGroupsToTypes[$type] ?? '';
}
/**
@@ -391,20 +402,21 @@ public function beforeSave()
*/
public function afterSave()
{
- $this->getValueInstance()->unsetValues();
$values = $this->getValues() ?: $this->getData('values');
if (is_array($values)) {
foreach ($values as $value) {
- if ($value instanceof \Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface) {
+ if ($value instanceof ProductCustomOptionValuesInterface) {
$data = $value->getData();
} else {
$data = $value;
}
- $this->getValueInstance()->addValue($data);
- }
- $this->getValueInstance()->setOption($this)->saveValues();
- } elseif ($this->getGroupByType($this->getType()) == self::OPTION_GROUP_SELECT) {
+ $this->customOptionValuesFactory->create()
+ ->addValue($data)
+ ->setOption($this)
+ ->saveValues();
+ }
+ } elseif ($this->getGroupByType($this->getType()) === self::OPTION_GROUP_SELECT) {
throw new LocalizedException(__('Select type options required values rows.'));
}
@@ -805,7 +817,7 @@ public function setImageSizeY($imageSizeY)
}
/**
- * @param \Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface[] $values
+ * @param ProductCustomOptionValuesInterface[] $values
* @return $this
*/
public function setValues(array $values = null)
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php
index cb6e76aebaadb..f6884a8d17f1f 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php
@@ -101,11 +101,11 @@ public function validateUserValue($values)
$this->setUserValue(
[
'date' => isset($value['date']) ? $value['date'] : '',
- 'year' => isset($value['year']) ? intval($value['year']) : 0,
- 'month' => isset($value['month']) ? intval($value['month']) : 0,
- 'day' => isset($value['day']) ? intval($value['day']) : 0,
- 'hour' => isset($value['hour']) ? intval($value['hour']) : 0,
- 'minute' => isset($value['minute']) ? intval($value['minute']) : 0,
+ 'year' => isset($value['year']) ? (int)$value['year'] : 0,
+ 'month' => isset($value['month']) ? (int)$value['month'] : 0,
+ 'day' => isset($value['day']) ? (int)$value['day'] : 0,
+ 'hour' => isset($value['hour']) ? (int)$value['hour'] : 0,
+ 'minute' => isset($value['minute']) ? (int)$value['minute'] : 0,
'day_part' => isset($value['day_part']) ? $value['day_part'] : '',
'date_internal' => isset($value['date_internal']) ? $value['date_internal'] : '',
]
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php
index 0277581b43975..0bb193107e65d 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php
@@ -276,7 +276,7 @@ public function getFormattedOptionValue($optionValue)
*/
public function getCustomizedView($optionInfo)
{
- return isset($optionInfo['value']) ? $optionInfo['value'] : $optionInfo;
+ return $optionInfo['value'] ?? $optionInfo;
}
/**
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ExistingValidate.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ExistingValidate.php
new file mode 100644
index 0000000000000..8d4aea135eabb
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ExistingValidate.php
@@ -0,0 +1,50 @@
+_messages = [];
+ $this->_errors = [];
+
+ if (!is_string($value)) {
+ $this->_messages[] = __('Full file path is expected.')->render();
+ return false;
+ }
+
+ $result = true;
+ $fileInfo = null;
+ if ($originalName) {
+ $fileInfo = ['name' => $originalName];
+ }
+ foreach ($this->_validators as $element) {
+ $validator = $element['instance'];
+ if ($validator->isValid($value, $fileInfo)) {
+ continue;
+ }
+ $result = false;
+ $messages = $validator->getMessages();
+ $this->_messages = array_merge($this->_messages, $messages);
+ $this->_errors = array_merge($this->_errors, array_keys($messages));
+ if ($element['breakChainOnFailure']) {
+ break;
+ }
+ }
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php
index 32c901afe8e74..c0d10c720f6f6 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php
@@ -13,6 +13,6 @@ class ValidateFactory
*/
public function create()
{
- return new \Zend_Validate();
+ return new ExistingValidate();
}
}
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php
index b54c66d75a058..49e062c5fd465 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php
@@ -10,6 +10,8 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Catalog\Model\Product\Exception as ProductException;
use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Math\Random;
+use Magento\Framework\App\ObjectManager;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -62,12 +64,18 @@ class ValidatorFile extends Validator
*/
protected $isImageValidator;
+ /**
+ * @var Random
+ */
+ private $random;
+
/**
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Framework\Filesystem $filesystem
* @param \Magento\Framework\File\Size $fileSize
* @param \Magento\Framework\HTTP\Adapter\FileTransferFactory $httpFactory
* @param \Magento\Framework\Validator\File\IsImage $isImageValidator
+ * @param Random|null $random
* @throws \Magento\Framework\Exception\FileSystemException
*/
public function __construct(
@@ -75,12 +83,15 @@ public function __construct(
\Magento\Framework\Filesystem $filesystem,
\Magento\Framework\File\Size $fileSize,
\Magento\Framework\HTTP\Adapter\FileTransferFactory $httpFactory,
- \Magento\Framework\Validator\File\IsImage $isImageValidator
+ \Magento\Framework\Validator\File\IsImage $isImageValidator,
+ Random $random = null
) {
$this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->filesystem = $filesystem;
$this->httpFactory = $httpFactory;
$this->isImageValidator = $isImageValidator;
+ $this->random = $random
+ ?? ObjectManager::getInstance()->get(Random::class);
parent::__construct($scopeConfig, $filesystem, $fileSize);
}
@@ -147,8 +158,6 @@ public function validate($processingParams, $option)
$userValue = [];
if ($upload->isUploaded($file) && $upload->isValid($file)) {
- $extension = pathinfo(strtolower($fileInfo['name']), PATHINFO_EXTENSION);
-
$fileName = \Magento\MediaStorage\Model\File\Uploader::getCorrectFileName($fileInfo['name']);
$dispersion = \Magento\MediaStorage\Model\File\Uploader::getDispersionPath($fileName);
@@ -156,7 +165,8 @@ public function validate($processingParams, $option)
$tmpDirectory = $this->filesystem->getDirectoryRead(DirectoryList::SYS_TMP);
$fileHash = md5($tmpDirectory->readFile($tmpDirectory->getRelativePath($fileInfo['tmp_name'])));
- $filePath .= '/' . $fileHash . '.' . $extension;
+ $fileRandomName = $this->random->getRandomString(32);
+ $filePath .= '/' .$fileRandomName;
$fileFullPath = $this->mediaDirectory->getAbsolutePath($this->quotePath . $filePath);
$upload->addFilter(new \Zend_Filter_File_Rename(['target' => $fileFullPath, 'overwrite' => true]));
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
index 30c3de932c3e6..b9946b99c5fdc 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
@@ -6,6 +6,9 @@
namespace Magento\Catalog\Model\Product\Option\Type\File;
+/**
+ * Validator for existing files.
+ */
class ValidatorInfo extends Validator
{
/**
@@ -90,7 +93,7 @@ public function validate($optionValue, $option)
}
$result = false;
- if ($validatorChain->isValid($this->fileFullPath)) {
+ if ($validatorChain->isValid($this->fileFullPath, $optionValue['title'])) {
$result = $this->rootDirectory->isReadable($this->fileRelativePath)
&& isset($optionValue['secret_key'])
&& $this->buildSecretKey($this->fileRelativePath) == $optionValue['secret_key'];
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php
index 79ee37c51671d..5624733831c1a 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php
@@ -81,7 +81,7 @@ public function validateUserValue($values)
*/
public function prepareForCart()
{
- if ($this->getIsValid() && strlen($this->getUserValue()) > 0) {
+ if ($this->getIsValid() && ($this->getUserValue() !== '')) {
return $this->getUserValue();
} else {
return null;
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Validator/DefaultValidator.php b/app/code/Magento/Catalog/Model/Product/Option/Validator/DefaultValidator.php
index d1fe4c570dc75..73bbc9cc88d3d 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Validator/DefaultValidator.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Validator/DefaultValidator.php
@@ -106,7 +106,9 @@ protected function isValidOptionTitle($title, $storeId)
if ($storeId > \Magento\Store\Model\Store::DEFAULT_STORE_ID && $title === null) {
return true;
}
- if ($this->isEmpty($title)) {
+
+ // checking whether title is null and is empty string
+ if ($title === null || $title === '') {
return false;
}
@@ -166,6 +168,6 @@ protected function isInRange($value, array $range)
*/
protected function isNegative($value)
{
- return intval($value) < 0;
+ return (int)$value < 0;
}
}
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Validator/Pool.php b/app/code/Magento/Catalog/Model/Product/Option/Validator/Pool.php
index 1e00654249556..2256f031098f1 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Validator/Pool.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Validator/Pool.php
@@ -29,6 +29,6 @@ public function __construct(array $validators)
*/
public function get($type)
{
- return isset($this->validators[$type]) ? $this->validators[$type] : $this->validators['default'];
+ return $this->validators[$type] ?? $this->validators['default'];
}
}
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php
index de656f465434a..e7c770d065824 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Value.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php
@@ -78,6 +78,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
+ * @param CustomOptionPriceCalculator|null $customOptionPriceCalculator
*/
public function __construct(
\Magento\Framework\Model\Context $context,
@@ -91,6 +92,7 @@ public function __construct(
$this->_valueCollectionFactory = $valueCollectionFactory;
$this->customOptionPriceCalculator = $customOptionPriceCalculator
?? \Magento\Framework\App\ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
+
parent::__construct(
$context,
$registry,
@@ -203,19 +205,15 @@ public function getProduct()
*/
public function saveValues()
{
+ $option = $this->getOption();
+
foreach ($this->getValues() as $value) {
$this->isDeleted(false);
- $this->setData(
- $value
- )->setData(
- 'option_id',
- $this->getOption()->getId()
- )->setData(
- 'store_id',
- $this->getOption()->getStoreId()
- );
-
- if ($this->getData('is_delete') == '1') {
+ $this->setData($value)
+ ->setData('option_id', $option->getId())
+ ->setData('store_id', $option->getStoreId());
+
+ if ((bool) $this->getData('is_delete') === true) {
if ($this->getId()) {
$this->deleteValues($this->getId());
$this->delete();
@@ -224,7 +222,7 @@ public function saveValues()
$this->save();
}
}
- //eof foreach()
+
return $this;
}
diff --git a/app/code/Magento/Catalog/Model/Product/PriceModifier.php b/app/code/Magento/Catalog/Model/Product/PriceModifier.php
index 4d81000501cff..ed9b3597c0dc9 100644
--- a/app/code/Magento/Catalog/Model/Product/PriceModifier.php
+++ b/app/code/Magento/Catalog/Model/Product/PriceModifier.php
@@ -46,11 +46,11 @@ public function removeTierPrice(\Magento\Catalog\Model\Product $product, $custom
foreach ($prices as $key => $tierPrice) {
if ($customerGroupId == 'all' && $tierPrice['price_qty'] == $qty
- && $tierPrice['all_groups'] == 1 && intval($tierPrice['website_id']) === intval($websiteId)
+ && $tierPrice['all_groups'] == 1 && (int)$tierPrice['website_id'] === (int)$websiteId
) {
unset($prices[$key]);
} elseif ($tierPrice['price_qty'] == $qty && $tierPrice['cust_group'] == $customerGroupId
- && intval($tierPrice['website_id']) === intval($websiteId)
+ && (int)$tierPrice['website_id'] === (int)$websiteId
) {
unset($prices[$key]);
}
diff --git a/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php b/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php
index 7cecd2f37bb84..18dc49a852a94 100644
--- a/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php
+++ b/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php
@@ -181,7 +181,7 @@ public function getList($sku, $customerGroupId)
$prices = [];
foreach ($product->getData('tier_price') as $price) {
- if ((is_numeric($customerGroupId) && intval($price['cust_group']) === intval($customerGroupId))
+ if ((is_numeric($customerGroupId) && (int)$price['cust_group'] === (int)$customerGroupId)
|| ($customerGroupId === 'all' && $price['all_groups'])
) {
/** @var \Magento\Catalog\Api\Data\ProductTierPriceInterface $tierPrice */
diff --git a/app/code/Magento/Catalog/Model/Product/Type.php b/app/code/Magento/Catalog/Model/Product/Type.php
index dc3971397acb2..0bc5216d2d238 100644
--- a/app/code/Magento/Catalog/Model/Product/Type.php
+++ b/app/code/Magento/Catalog/Model/Product/Type.php
@@ -232,7 +232,7 @@ public function getOptions()
public function getOptionText($optionId)
{
$options = $this->getOptionArray();
- return isset($options[$optionId]) ? $options[$optionId] : null;
+ return $options[$optionId] ?? null;
}
/**
@@ -285,7 +285,7 @@ public function getTypesByPriority()
$types = $this->getTypes();
foreach ($types as $typeId => $typeInfo) {
- $priority = isset($typeInfo['index_priority']) ? abs(intval($typeInfo['index_priority'])) : 0;
+ $priority = isset($typeInfo['index_priority']) ? abs((int)$typeInfo['index_priority']) : 0;
if (!empty($typeInfo['composite'])) {
$compositePriority[$typeId] = $priority;
} else {
diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
index 9ad0db444eed0..83057ad00c668 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
@@ -291,13 +291,7 @@ public function attributesCompare($attributeOne, $attributeTwo)
$sortOne = $attributeOne->getGroupSortPath() * 1000 + $attributeOne->getSortPath() * 0.0001;
$sortTwo = $attributeTwo->getGroupSortPath() * 1000 + $attributeTwo->getSortPath() * 0.0001;
- if ($sortOne > $sortTwo) {
- return 1;
- } elseif ($sortOne < $sortTwo) {
- return -1;
- }
-
- return 0;
+ return $sortOne <=> $sortTwo;
}
/**
@@ -938,7 +932,7 @@ public function getForceChildItemQtyChanges($product)
*/
public function prepareQuoteItemQty($qty, $product)
{
- return floatval($qty);
+ return (float)$qty;
}
/**
diff --git a/app/code/Magento/Catalog/Model/Product/Type/Price.php b/app/code/Magento/Catalog/Model/Product/Type/Price.php
index 7eaedf77eb859..f6caa299d66d7 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/Price.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/Price.php
@@ -474,14 +474,15 @@ public function getTierPriceCount($product)
*
* @param float $qty
* @param Product $product
+ *
* @return array|float
*/
- public function getFormatedTierPrice($qty, $product)
+ public function getFormattedTierPrice($qty, $product)
{
$price = $product->getTierPrice($qty);
if (is_array($price)) {
foreach (array_keys($price) as $index) {
- $price[$index]['formated_price'] = $this->priceCurrency->convertAndFormat(
+ $price[$index]['formatted_price'] = $this->priceCurrency->convertAndFormat(
$price[$index]['website_price']
);
}
@@ -492,15 +493,45 @@ public function getFormatedTierPrice($qty, $product)
return $price;
}
+ /**
+ * Get formatted by currency tier price
+ *
+ * @param float $qty
+ * @param Product $product
+ *
+ * @return array|float
+ *
+ * @deprecated
+ * @see getFormattedTierPrice()
+ */
+ public function getFormatedTierPrice($qty, $product)
+ {
+ return $this->getFormattedTierPrice($qty, $product);
+ }
+
+ /**
+ * Get formatted by currency product price
+ *
+ * @param Product $product
+ * @return array|float
+ */
+ public function getFormattedPrice($product)
+ {
+ return $this->priceCurrency->format($product->getFinalPrice());
+ }
+
/**
* Get formatted by currency product price
*
* @param Product $product
* @return array || float
+ *
+ * @deprecated
+ * @see getFormattedPrice()
*/
public function getFormatedPrice($product)
{
- return $this->priceCurrency->format($product->getFinalPrice());
+ return $this->getFormattedPrice($product);
}
/**
diff --git a/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php b/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php
index b635d854c9e2b..d397dc515db61 100644
--- a/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php
+++ b/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php
@@ -47,22 +47,20 @@ public function getCollection(\Magento\Catalog\Model\Product $product, $type)
$products = $this->providers[$type]->getLinkedProducts($product);
$converter = $this->converterPool->getConverter($type);
- $output = [];
$sorterItems = [];
foreach ($products as $item) {
- $output[$item->getId()] = $converter->convert($item);
+ $itemId = $item->getId();
+ $sorterItems[$itemId] = $converter->convert($item);
+ $sorterItems[$itemId]['position'] = $sorterItems[$itemId]['position'] ?? 0;
}
- foreach ($output as $item) {
- $itemPosition = $item['position'];
- if (!isset($sorterItems[$itemPosition])) {
- $sorterItems[$itemPosition] = $item;
- } else {
- $newPosition = $itemPosition + 1;
- $sorterItems[$newPosition] = $item;
- }
- }
- ksort($sorterItems);
+ usort($sorterItems, function ($itemA, $itemB) {
+ $posA = intval($itemA['position']);
+ $posB = intval($itemB['position']);
+
+ return $posA <=> $posB;
+ });
+
return $sorterItems;
}
}
diff --git a/app/code/Magento/Catalog/Model/ProductLink/Repository.php b/app/code/Magento/Catalog/Model/ProductLink/Repository.php
index f8dee9216ddcf..9571ab91c3278 100644
--- a/app/code/Magento/Catalog/Model/ProductLink/Repository.php
+++ b/app/code/Magento/Catalog/Model/ProductLink/Repository.php
@@ -10,6 +10,7 @@
use Magento\Catalog\Api\Data\ProductLinkExtensionFactory;
use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks as LinksInitializer;
use Magento\Catalog\Model\Product\LinkTypeProvider;
+use Magento\Framework\Api\SimpleDataObjectConverter;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\EntityManager\MetadataPool;
@@ -170,7 +171,7 @@ public function getList(\Magento\Catalog\Api\Data\ProductInterface $product)
foreach ($item['custom_attributes'] as $option) {
$name = $option['attribute_code'];
$value = $option['value'];
- $setterName = 'set'.ucfirst($name);
+ $setterName = 'set' . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($name);
// Check if setter exists
if (method_exists($productLinkExtension, $setterName)) {
call_user_func([$productLinkExtension, $setterName], $value);
diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php
index ffd2d044e9425..dd941680b8a4d 100644
--- a/app/code/Magento/Catalog/Model/ProductRepository.php
+++ b/app/code/Magento/Catalog/Model/ProductRepository.php
@@ -6,8 +6,11 @@
*/
namespace Magento\Catalog\Model;
+use Magento\Catalog\Api\Data\ProductExtension;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
+use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException;
use Magento\Framework\Api\Data\ImageContentInterfaceFactory;
use Magento\Framework\Api\ImageContentValidatorInterface;
use Magento\Framework\Api\ImageProcessorInterface;
@@ -16,8 +19,10 @@
use Magento\Framework\DB\Adapter\DeadlockException;
use Magento\Framework\DB\Adapter\LockWaitException;
use Magento\Framework\Exception\CouldNotSaveException;
+use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException;
use Magento\Framework\Exception\ValidatorException;
/**
@@ -294,10 +299,10 @@ protected function getCacheKey($data)
* Add product to internal cache and truncate cache if it has more than cacheLimit elements.
*
* @param string $cacheKey
- * @param \Magento\Catalog\Api\Data\ProductInterface $product
+ * @param ProductInterface $product
* @return void
*/
- private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterface $product)
+ private function cacheProduct($cacheKey, ProductInterface $product)
{
$this->instancesById[$product->getId()][$cacheKey] = $product;
$this->saveProductInLocalCache($product, $cacheKey);
@@ -314,7 +319,7 @@ private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterf
*
* @param array $productData
* @param bool $createNew
- * @return \Magento\Catalog\Api\Data\ProductInterface|Product
+ * @return ProductInterface|Product
* @throws NoSuchEntityException
*/
protected function initializeProductData(array $productData, $createNew)
@@ -361,12 +366,12 @@ private function assignProductToWebsites(\Magento\Catalog\Model\Product $product
/**
* Process product links, creating new links, updating and deleting existing links
*
- * @param \Magento\Catalog\Api\Data\ProductInterface $product
+ * @param ProductInterface $product
* @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $newLinks
* @return $this
* @throws NoSuchEntityException
*/
- private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $product, $newLinks)
+ private function processLinks(ProductInterface $product, $newLinks)
{
if ($newLinks === null) {
// If product links were not specified, don't do anything
@@ -421,7 +426,7 @@ private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $produc
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
- public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
+ public function save(ProductInterface $product, $saveOptions = false)
{
$tierPrices = $product->getData('tier_price');
@@ -435,12 +440,18 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
if (!$product->hasData(Product::STATUS)) {
$product->setStatus($existingProduct->getStatus());
}
+
+ /** @var ProductExtension $extensionAttributes */
+ $extensionAttributes = $product->getExtensionAttributes();
+ if (empty($extensionAttributes->__toArray())) {
+ $product->setExtensionAttributes($existingProduct->getExtensionAttributes());
+ }
} catch (NoSuchEntityException $e) {
$existingProduct = null;
}
$productDataArray = $this->extensibleDataObjectConverter
- ->toNestedArray($product, [], \Magento\Catalog\Api\Data\ProductInterface::class);
+ ->toNestedArray($product, [], ProductInterface::class);
$productDataArray = array_replace($productDataArray, $product->getData());
$ignoreLinksFlag = $product->getData('ignore_links_flag');
$productLinks = null;
@@ -471,53 +482,21 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
);
}
- try {
- if ($tierPrices !== null) {
- $product->setData('tier_price', $tierPrices);
- }
- $this->removeProductFromLocalCache($product->getSku());
- unset($this->instancesById[$product->getId()]);
- $this->resourceModel->save($product);
- } catch (ConnectionException $exception) {
- throw new \Magento\Framework\Exception\TemporaryState\CouldNotSaveException(
- __('Database connection error'),
- $exception,
- $exception->getCode()
- );
- } catch (DeadlockException $exception) {
- throw new \Magento\Framework\Exception\TemporaryState\CouldNotSaveException(
- __('Database deadlock found when trying to get lock'),
- $exception,
- $exception->getCode()
- );
- } catch (LockWaitException $exception) {
- throw new \Magento\Framework\Exception\TemporaryState\CouldNotSaveException(
- __('Database lock wait timeout exceeded'),
- $exception,
- $exception->getCode()
- );
- } catch (\Magento\Eav\Model\Entity\Attribute\Exception $exception) {
- throw \Magento\Framework\Exception\InputException::invalidFieldValue(
- $exception->getAttributeCode(),
- $product->getData($exception->getAttributeCode()),
- $exception
- );
- } catch (ValidatorException $e) {
- throw new CouldNotSaveException(__($e->getMessage()));
- } catch (LocalizedException $e) {
- throw $e;
- } catch (\Exception $e) {
- throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'), $e);
+ if ($tierPrices !== null) {
+ $product->setData('tier_price', $tierPrices);
}
+
+ $this->saveProduct($product);
$this->removeProductFromLocalCache($product->getSku());
unset($this->instancesById[$product->getId()]);
+
return $this->get($product->getSku(), false, $product->getStoreId());
}
/**
* {@inheritdoc}
*/
- public function delete(\Magento\Catalog\Api\Data\ProductInterface $product)
+ public function delete(ProductInterface $product)
{
$sku = $product->getSku();
$productId = $product->getId();
@@ -707,4 +686,52 @@ private function prepareSku(string $sku): string
{
return mb_strtolower(trim($sku));
}
+
+ /**
+ * Save product resource model.
+ *
+ * @param ProductInterface|Product $product
+ * @throws TemporaryCouldNotSaveException
+ * @throws InputException
+ * @throws CouldNotSaveException
+ * @throws LocalizedException
+ */
+ private function saveProduct($product)
+ {
+ try {
+ $this->removeProductFromLocalCache($product->getSku());
+ unset($this->instancesById[$product->getId()]);
+ $this->resourceModel->save($product);
+ } catch (ConnectionException $exception) {
+ throw new TemporaryCouldNotSaveException(
+ __('Database connection error'),
+ $exception,
+ $exception->getCode()
+ );
+ } catch (DeadlockException $exception) {
+ throw new TemporaryCouldNotSaveException(
+ __('Database deadlock found when trying to get lock'),
+ $exception,
+ $exception->getCode()
+ );
+ } catch (LockWaitException $exception) {
+ throw new TemporaryCouldNotSaveException(
+ __('Database lock wait timeout exceeded'),
+ $exception,
+ $exception->getCode()
+ );
+ } catch (AttributeException $exception) {
+ throw InputException::invalidFieldValue(
+ $exception->getAttributeCode(),
+ $product->getData($exception->getAttributeCode()),
+ $exception
+ );
+ } catch (ValidatorException $e) {
+ throw new CouldNotSaveException(__($e->getMessage()));
+ } catch (LocalizedException $e) {
+ throw $e;
+ } catch (\Exception $e) {
+ throw new CouldNotSaveException(__('Unable to save product'), $e);
+ }
+ }
}
diff --git a/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php
index 4cc31d98fdfc2..56d1cfda8bce5 100644
--- a/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php
+++ b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php
@@ -100,8 +100,13 @@ public function processMediaGallery(ProductInterface $product, array $mediaGalle
$newEntries = $mediaGalleryEntries;
}
- $this->processor->clearMediaAttribute($product, array_keys($product->getMediaAttributes()));
$images = $product->getMediaGallery('images');
+
+ if ($images) {
+ $images = $this->determineImageRoles($product, $images);
+ }
+
+ $this->processor->clearMediaAttribute($product, array_keys($product->getMediaAttributes()));
if ($images) {
foreach ($images as $image) {
if (!isset($image['removed']) && !empty($image['types'])) {
@@ -112,6 +117,32 @@ public function processMediaGallery(ProductInterface $product, array $mediaGalle
$this->processEntries($product, $newEntries, $entriesById);
}
+ /**
+ * Ascertain image roles, if they are not set against the gallery entries
+ *
+ * @param ProductInterface $product
+ * @param array $images
+ * @return array
+ */
+ private function determineImageRoles(ProductInterface $product, array $images)
+ {
+ $imagesWithRoles = [];
+ foreach ($images as $image) {
+ if (!isset($image['types'])) {
+ $image['types'] = [];
+ if (isset($image['file'])) {
+ foreach (array_keys($product->getMediaAttributes()) as $attribute) {
+ if ($image['file'] == $product->getData($attribute)) {
+ $image['types'][] = $attribute;
+ }
+ }
+ }
+ }
+ $imagesWithRoles[] = $image;
+ }
+ return $imagesWithRoles;
+ }
+
/**
* Convert entries into product media gallery data and set to product.
*
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php
index 1f3b2642953c8..1ecbc6566da0f 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php
@@ -666,7 +666,7 @@ public function getProductCount($category)
$bind = ['category_id' => (int)$category->getId()];
$counts = $this->getConnection()->fetchOne($select, $bind);
- return intval($counts);
+ return (int)$counts;
}
/**
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php
index 01e4b072b0367..9db2c8248ce52 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php
@@ -173,7 +173,7 @@ public function getMainTable()
public function getMainStoreTable($storeId = \Magento\Store\Model\Store::DEFAULT_STORE_ID)
{
if (is_string($storeId)) {
- $storeId = intval($storeId);
+ $storeId = (int) $storeId;
}
if ($storeId) {
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
index d8243c05dc7ba..f9ec6500b1635 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
@@ -462,7 +462,7 @@ protected function _isOriginalIndexable()
$backendType = $this->getOrigData('backend_type');
$frontendInput = $this->getOrigData('frontend_input');
- if ($backendType == 'int' && $frontendInput == 'select') {
+ if ($backendType == 'int' && ($frontendInput == 'select' || $frontendInput == 'boolean')) {
return true;
} elseif ($backendType == 'varchar' && $frontendInput == 'multiselect') {
return true;
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Layer/Filter/Price.php b/app/code/Magento/Catalog/Model/ResourceModel/Layer/Filter/Price.php
index 7f66e5e253706..585da2af529a4 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Layer/Filter/Price.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Layer/Filter/Price.php
@@ -112,7 +112,7 @@ public function getCount($range)
/**
* Check and set correct variable values to prevent SQL-injections
*/
- $range = floatval($range);
+ $range = (float)$range;
if ($range == 0) {
$range = 1;
}
@@ -399,10 +399,19 @@ public function applyPriceRange(\Magento\Catalog\Model\Layer\Filter\FilterInterf
/**
* Initialize connection and define main table name
- * @deprecated
+ *
* @return void
*/
protected function _construct()
+ {
+ $this->_init('catalog_product_index_price', 'entity_id');
+ }
+
+ /**
+ * {@inheritdoc}
+ * @return string
+ */
+ public function getMainTable()
{
$storeKey = $this->httpContext->getValue(StoreManagerInterface::CONTEXT_STORE);
$priceTableName = $this->priceTableResolver->resolve(
@@ -418,7 +427,8 @@ protected function _construct()
)
]
);
- $this->_init($priceTableName, 'entity_id');
+
+ return $this->getTable($priceTableName);
}
/**
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
index 5a77c9664787c..937b21a9c8421 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
@@ -476,8 +476,7 @@ public function getFlatState()
}
/**
- * Retrieve is flat enabled flag
- * Return always false if magento run admin
+ * Retrieve is flat enabled. Return always false if magento run admin.
*
* @return bool
*/
@@ -505,8 +504,7 @@ protected function _construct()
}
/**
- * Standard resource collection initialization
- * Needed for child classes
+ * Standard resource collection initialization. Needed for child classes.
*
* @param string $model
* @param string $entityModel
@@ -545,8 +543,7 @@ protected function _prepareStaticFields()
}
/**
- * Retrieve collection empty item
- * Redeclared for specifying id field name without getting resource model inside model
+ * Get collection empty item. Redeclared for specifying id field name without getting resource model inside model.
*
* @return \Magento\Framework\DataObject
*/
@@ -632,8 +629,7 @@ public function _loadAttributes($printQuery = false, $logQuery = false)
}
/**
- * Add attribute to entities in collection
- * If $attribute=='*' select all attributes
+ * Add attribute to entities in collection. If $attribute=='*' select all attributes.
*
* @param array|string|integer|\Magento\Framework\App\Config\Element $attribute
* @param bool|string $joinType
@@ -669,8 +665,7 @@ public function addAttributeToSelect($attribute, $joinType = false)
}
/**
- * Processing collection items after loading
- * Adding url rewrites, minimal prices, final prices, tax percents
+ * Processing collection items after loading. Adding url rewrites, minimal prices, final prices, tax percents.
*
* @return $this
*/
@@ -681,6 +676,7 @@ protected function _afterLoad()
}
$this->_prepareUrlDataObject();
+ $this->prepareStoreId();
if (count($this)) {
$this->_eventManager->dispatch('catalog_product_collection_load_after', ['collection' => $this]);
@@ -689,6 +685,23 @@ protected function _afterLoad()
return $this;
}
+ /**
+ * Add Store ID to products from collection.
+ *
+ * @return $this
+ */
+ protected function prepareStoreId()
+ {
+ if ($this->getStoreId() !== null) {
+ /** @var $item \Magento\Catalog\Model\Product */
+ foreach ($this->_items as $item) {
+ $item->setStoreId($this->getStoreId());
+ }
+ }
+
+ return $this;
+ }
+
/**
* Prepare Url Data object
*
@@ -755,8 +768,7 @@ public function addIdFilter($productId, $exclude = false)
}
/**
- * Adding product website names to result collection
- * Add for each product websites information
+ * Adding product website names to result collection. Add for each product websites information.
*
* @return $this
*/
@@ -767,7 +779,7 @@ public function addWebsiteNamesToResult()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function load($printQuery = false, $logQuery = false)
{
@@ -818,14 +830,14 @@ protected function doAddWebsiteNamesToResult()
foreach ($this as $product) {
if (isset($productWebsites[$product->getId()])) {
$product->setData('websites', $productWebsites[$product->getId()]);
+ $product->setData('website_ids', $productWebsites[$product->getId()]);
}
}
return $this;
}
/**
- * Add store availability filter. Include availability product
- * for store website
+ * Add store availability filter. Include availability product for store website.
*
* @param null|string|bool|int|Store $store
* @return $this
@@ -931,7 +943,7 @@ private function mapConditionType($conditionType)
'eq' => 'in',
'neq' => 'nin'
];
- return isset($conditionsMap[$conditionType]) ? $conditionsMap[$conditionType] : $conditionType;
+ return $conditionsMap[$conditionType] ?? $conditionType;
}
/**
@@ -1114,7 +1126,7 @@ public function getSelectCountSql()
/**
* Get SQL for get record count
*
- * @param null $select
+ * @param \Magento\Framework\DB\Select $select
* @param bool $resetLeftJoins
* @return \Magento\Framework\DB\Select
*/
@@ -1356,8 +1368,7 @@ public function joinUrlRewrite()
}
/**
- * Add URL rewrites data to product
- * If collection loadded - run processing else set flag
+ * Add URL rewrites data to product. If collection loadded - run processing else set flag.
*
* @param int|string $categoryId
* @return $this
@@ -1580,7 +1591,8 @@ public function addAttributeToFilter($attribute, $condition = null, $joinType =
}
/**
- * {@inheritdoc}
+ * @inheritdoc
+ *
* @since 101.0.0
*/
protected function getEntityPkName(\Magento\Eav\Model\Entity\AbstractEntity $entity)
@@ -2342,7 +2354,10 @@ private function getGalleryReadHandler()
}
/**
+ * Retrieve Media gallery resource.
+ *
* @deprecated 101.0.1
+ *
* @return \Magento\Catalog\Model\ResourceModel\Product\Gallery
*/
private function getMediaGalleryResource()
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
index 5b68730209b40..77836c58d5070 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php
@@ -84,7 +84,7 @@ protected function _getIndexableAttributes($multiSelect)
if ($multiSelect == true) {
$select->where('ea.backend_type = ?', 'varchar')->where('ea.frontend_input = ?', 'multiselect');
} else {
- $select->where('ea.backend_type = ?', 'int')->where('ea.frontend_input = ?', 'select');
+ $select->where('ea.backend_type = ?', 'int')->where('ea.frontend_input IN( ? )', ['select', 'boolean']);
}
return $this->getConnection()->fetchCol($select);
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php
index 269d29bf7e26a..646cd0d4c1a4c 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php
@@ -93,7 +93,7 @@ public function modifyPrice(IndexTableStructure $priceTable, array $entityIds =
{
// no need to run all queries if current products have no custom options
if (!$this->checkIfCustomOptionsExist($priceTable)) {
- return ;
+ return;
}
$connection = $this->getConnection();
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
index 849c12238db5a..7ea85cd3f6f10 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php
@@ -456,7 +456,7 @@ protected function getSelect($entityIds = null, $type = null)
$specialFromExpr = "{$specialFrom} IS NULL OR {$specialFromDate} <= {$currentDate}";
$specialToExpr = "{$specialTo} IS NULL OR {$specialToDate} >= {$currentDate}";
$specialPriceExpr = $connection->getCheckSql(
- "{$specialPrice} IS NOT NULL AND {$specialFromExpr} AND {$specialToExpr}",
+ "{$specialPrice} IS NOT NULL AND ({$specialFromExpr}) AND ({$specialToExpr})",
$specialPrice,
$maxUnsignedBigint
);
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php
index 683853fd1dc1a..5a055e5ed9603 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php
@@ -64,7 +64,7 @@ public function __construct(
/**
* {@inheritdoc}
*/
- public function executeByDimension(array $dimensions, \Traversable $entityIds = null)
+ public function executeByDimensions(array $dimensions, \Traversable $entityIds)
{
$this->tableMaintainer->createMainTmpTable($dimensions);
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
index ef3f83e5ffa7e..e6eb4804f56b2 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
@@ -112,7 +112,7 @@ public function hasProductLinks($parentId)
['count' => new \Zend_Db_Expr('COUNT(*)')]
)->where(
'product_id = :product_id'
- ) ;
+ );
return $connection->fetchOne(
$select,
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php
index 4775b96e3a448..179da06b59990 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php
@@ -307,7 +307,7 @@ protected function _saveValueTitles(\Magento\Framework\Model\AbstractModel $obje
}
/**
- * Get first col from from first row for option table
+ * Get first col from first row for option table
*
* @param string $tableName
* @param int $optionId
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
index 91bb99ca971a7..5ffc9fbd575b6 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
@@ -160,19 +160,22 @@ protected function _saveValuePrices(AbstractModel $object)
&& isset($objectPrice)
&& $object->getStoreId() != Store::DEFAULT_STORE_ID
) {
- $baseCurrency = $this->_config->getValue(
+ $website = $this->_storeManager->getStore($object->getStoreId())->getWebsite();
+
+ $websiteBaseCurrency = $this->_config->getValue(
Currency::XML_PATH_CURRENCY_BASE,
- 'default'
+ ScopeInterface::SCOPE_WEBSITE,
+ $website
);
- $storeIds = $this->_storeManager->getStore($object->getStoreId())->getWebsite()->getStoreIds();
+ $storeIds = $website->getStoreIds();
if (is_array($storeIds)) {
foreach ($storeIds as $storeId) {
if ($priceType == 'fixed') {
$storeCurrency = $this->_storeManager->getStore($storeId)->getBaseCurrencyCode();
/** @var $currencyModel Currency */
$currencyModel = $this->_currencyFactory->create();
- $currencyModel->load($baseCurrency);
+ $currencyModel->load($websiteBaseCurrency);
$rate = $currencyModel->getRate($storeCurrency);
if (!$rate) {
$rate = 1;
@@ -256,7 +259,8 @@ protected function _saveValueTitles(AbstractModel $object)
$object->unsetData('title');
}
- if ($object->getTitle()) {
+ /*** Checking whether title is not null ***/
+ if ($object->getTitle()!= null) {
if ($existInCurrentStore) {
if ($storeId == $object->getStoreId()) {
$where = [
@@ -300,7 +304,7 @@ protected function _saveValueTitles(AbstractModel $object)
}
/**
- * Get first col from from first row for option table
+ * Get first col from first row for option table
*
* @param string $tableName
* @param int $optionId
diff --git a/app/code/Magento/Catalog/Observer/CategoryProductIndexer.php b/app/code/Magento/Catalog/Observer/CategoryProductIndexer.php
new file mode 100644
index 0000000000000..1a131ed71973d
--- /dev/null
+++ b/app/code/Magento/Catalog/Observer/CategoryProductIndexer.php
@@ -0,0 +1,43 @@
+processor = $processor;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(Observer $observer)
+ {
+ $productIds = $observer->getEvent()->getProductIds();
+ if (!empty($productIds) && $this->processor->isIndexerScheduled()) {
+ $this->processor->markIndexerAsInvalid();
+ }
+ }
+}
diff --git a/app/code/Magento/Catalog/Plugin/Model/Attribute/Backend/AttributeValidation.php b/app/code/Magento/Catalog/Plugin/Model/Attribute/Backend/AttributeValidation.php
index 597a1466a125e..5ccec4c3a4c7b 100644
--- a/app/code/Magento/Catalog/Plugin/Model/Attribute/Backend/AttributeValidation.php
+++ b/app/code/Magento/Catalog/Plugin/Model/Attribute/Backend/AttributeValidation.php
@@ -14,6 +14,11 @@ class AttributeValidation
*/
private $storeManager;
+ /**
+ * @var array
+ */
+ private $allowedEntityTypes;
+
/**
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param array $allowedEntityTypes
@@ -30,6 +35,7 @@ public function __construct(
* @param \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend $subject
* @param \Closure $proceed
* @param \Magento\Framework\DataObject $entity
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
* @return bool
*/
public function aroundValidate(
@@ -41,7 +47,7 @@ public function aroundValidate(
return $entity instanceof $allowedEntity;
}, $this->allowedEntityTypes)));
- if ($isAllowedType && $this->storeManager->getStore()->getId() !== Store::DEFAULT_STORE_ID) {
+ if ($isAllowedType && (int) $this->storeManager->getStore()->getId() !== Store::DEFAULT_STORE_ID) {
$attrCode = $subject->getAttribute()->getAttributeCode();
// Null is meaning "no value" which should be overridden by value from default scope
if (array_key_exists($attrCode, $entity->getData()) && $entity->getData($attrCode) === null) {
diff --git a/app/code/Magento/Catalog/Pricing/Price/ConfiguredRegularPrice.php b/app/code/Magento/Catalog/Pricing/Price/ConfiguredRegularPrice.php
index 66dc783e1401e..75b4d13d1c8d8 100644
--- a/app/code/Magento/Catalog/Pricing/Price/ConfiguredRegularPrice.php
+++ b/app/code/Magento/Catalog/Pricing/Price/ConfiguredRegularPrice.php
@@ -61,7 +61,7 @@ public function setItem(ItemInterface $item)
$this->item = $item;
return $this;
}
-
+
/**
* Price value of product with configured options
*
@@ -70,8 +70,7 @@ public function setItem(ItemInterface $item)
public function getValue()
{
$basePrice = parent::getValue();
-
- return ($this->item && $basePrice !== false)
+ return $this->item && $basePrice !== false
? $basePrice + $this->configuredOptions->getItemOptionsValue($basePrice, $this->item)
: $basePrice;
}
diff --git a/app/code/Magento/Catalog/Pricing/Price/RegularPrice.php b/app/code/Magento/Catalog/Pricing/Price/RegularPrice.php
index 609255d852da3..2c4e332e71237 100644
--- a/app/code/Magento/Catalog/Pricing/Price/RegularPrice.php
+++ b/app/code/Magento/Catalog/Pricing/Price/RegularPrice.php
@@ -22,14 +22,14 @@ class RegularPrice extends AbstractPrice implements BasePriceProviderInterface
/**
* Get price value
*
- * @return float|bool
+ * @return float
*/
public function getValue()
{
if ($this->value === null) {
$price = $this->product->getPrice();
$priceInCurrentCurrency = $this->priceCurrency->convertAndRound($price);
- $this->value = $priceInCurrentCurrency ? floatval($priceInCurrentCurrency) : false;
+ $this->value = $priceInCurrentCurrency ? (float)$priceInCurrentCurrency : 0;
}
return $this->value;
}
diff --git a/app/code/Magento/Catalog/Pricing/Price/TierPrice.php b/app/code/Magento/Catalog/Pricing/Price/TierPrice.php
index 893978a3b6b3b..a62f3ed09ee1d 100644
--- a/app/code/Magento/Catalog/Pricing/Price/TierPrice.php
+++ b/app/code/Magento/Catalog/Pricing/Price/TierPrice.php
@@ -82,7 +82,7 @@ public function __construct(
GroupManagementInterface $groupManagement,
CustomerGroupRetrieverInterface $customerGroupRetriever = null
) {
- $quantity = floatval($quantity) ? $quantity : 1;
+ $quantity = (float)$quantity ? $quantity : 1;
parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency);
$this->customerSession = $customerSession;
$this->groupManagement = $groupManagement;
diff --git a/app/code/Magento/Catalog/Setup/InstallData.php b/app/code/Magento/Catalog/Setup/InstallData.php
index 5b1a10b098eb5..045ddd8a80c95 100644
--- a/app/code/Magento/Catalog/Setup/InstallData.php
+++ b/app/code/Magento/Catalog/Setup/InstallData.php
@@ -124,7 +124,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface
// update attributes group and sort
$attributes = [
'custom_design' => ['group' => 'design', 'sort' => 10],
- // 'custom_design_apply' => array('group' => 'design', 'sort' => 20),
'custom_design_from' => ['group' => 'design', 'sort' => 30],
'custom_design_to' => ['group' => 'design', 'sort' => 40],
'page_layout' => ['group' => 'design', 'sort' => 50],
diff --git a/app/code/Magento/Catalog/Setup/UpgradeData.php b/app/code/Magento/Catalog/Setup/UpgradeData.php
index e8d8582b07f96..4e0be7396a166 100644
--- a/app/code/Magento/Catalog/Setup/UpgradeData.php
+++ b/app/code/Magento/Catalog/Setup/UpgradeData.php
@@ -5,7 +5,6 @@
*/
namespace Magento\Catalog\Setup;
-use Magento\Catalog\Model\Indexer\Product\Price\DimensionModeConfiguration;
use Magento\Eav\Setup\EavSetup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
@@ -397,10 +396,6 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface
$this->enableSegmentation($setup);
}
- if (version_compare($context->getVersion(), '2.2.6') < 0) {
- $this->savePriceIndexerDimensionsMode($setup);
- }
-
$setup->endSetup();
}
@@ -485,21 +480,4 @@ private function enableSegmentation(ModuleDataSetupInterface $setup)
$setup->getConnection()->truncateTable($setup->getTable('catalog_category_product_index_replica'));
$setup->getConnection()->truncateTable($setup->getTable('catalog_category_product_index_tmp'));
}
-
- /**
- * @param ModuleDataSetupInterface $setup
- * @return void
- */
- private function savePriceIndexerDimensionsMode(ModuleDataSetupInterface $setup)
- {
- $setup->getConnection()->insert(
- $setup->getTable('core_config_data'),
- [
- 'scope' => 'default',
- 'scope_id' => 0,
- 'path' => \Magento\Catalog\Model\Indexer\Product\Price\ModeSwitcher::XML_PATH_PRICE_DIMENSIONS_MODE,
- 'value' => DimensionModeConfiguration::DIMENSION_NONE
- ]
- );
- }
}
diff --git a/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php b/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php
index 3d300d9c849a9..05e4bb3817beb 100644
--- a/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php
+++ b/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php
@@ -148,6 +148,20 @@ private function processAttributeValues(ModuleDataSetupInterface $setup, array $
*/
private function fetchAttributeValues(ModuleDataSetupInterface $setup, $tableName)
{
+ $multipleStoresInWebsite = array_values(
+ array_reduce(
+ array_filter($this->getGroupedStoreViews($setup), function ($storeViews) {
+ return is_array($storeViews) && count($storeViews) > 1;
+ }),
+ 'array_merge',
+ []
+ )
+ );
+
+ if (count($multipleStoresInWebsite) < 1) {
+ return [];
+ }
+
$connection = $setup->getConnection();
$batchSelectIterator = $this->batchQueryGenerator->generate(
'value_id',
@@ -158,27 +172,18 @@ private function fetchAttributeValues(ModuleDataSetupInterface $setup, $tableNam
'*'
)
->join(
- [
- 'cea' => $setup->getTable('catalog_eav_attribute'),
- ],
+ ['cea' => $setup->getTable('catalog_eav_attribute')],
'cpei.attribute_id = cea.attribute_id',
''
)
->join(
- [
- 'st' => $setup->getTable('store'),
- ],
+ ['st' => $setup->getTable('store')],
'st.store_id = cpei.store_id',
'st.website_id'
)
- ->where(
- 'cea.is_global = ?',
- self::ATTRIBUTE_WEBSITE
- )
- ->where(
- 'cpei.store_id <> ?',
- self::GLOBAL_STORE_VIEW_ID
- )
+ ->where('cea.is_global = ?', self::ATTRIBUTE_WEBSITE)
+ ->where('cpei.store_id IN (?)', $multipleStoresInWebsite),
+ 1000
);
foreach ($batchSelectIterator as $select) {
@@ -201,17 +206,15 @@ private function getGroupedStoreViews(ModuleDataSetupInterface $setup)
->select()
->from(
$setup->getTable('store'),
- '*'
- );
+ ['store_id', 'website_id']
+ )->where('store_id <> ?', self::GLOBAL_STORE_VIEW_ID);
- $storeViews = $connection->fetchAll($query);
+ $storeViews = $connection->fetchPairs($query);
$this->groupedStoreViews = [];
- foreach ($storeViews as $storeView) {
- if ($storeView['store_id'] != 0) {
- $this->groupedStoreViews[$storeView['website_id']][] = $storeView['store_id'];
- }
+ foreach ($storeViews as $storeId => $websiteId) {
+ $this->groupedStoreViews[$websiteId][] = $storeId;
}
return $this->groupedStoreViews;
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml
index e35769bb2019c..7dafeff34a2ea 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml
@@ -13,21 +13,19 @@
-
-
+
+
.
-
-
+
-
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryActionGroup.xml
index 4872c0c5c716c..127b69e5c3dc4 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryActionGroup.xml
@@ -8,6 +8,7 @@
+
@@ -24,6 +25,7 @@
+
@@ -41,6 +43,7 @@
+
@@ -58,4 +61,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryProductAttributeActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryProductAttributeActionGroup.xml
new file mode 100644
index 0000000000000..b1300f63d967c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryProductAttributeActionGroup.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml
new file mode 100644
index 0000000000000..cbc3ac876a486
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeSetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeSetActionGroup.xml
new file mode 100644
index 0000000000000..a7e76253728a3
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeSetActionGroup.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductCheckUnsupportedFileActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductCheckUnsupportedFileActionGroup.xml
new file mode 100644
index 0000000000000..640dd9ae6d264
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductCheckUnsupportedFileActionGroup.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml
index 7b534ea088d4a..408586d603835 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductGridActionGroup.xml
@@ -16,4 +16,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminResetProductGridToDefaultViewActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminResetProductGridToDefaultViewActionGroup.xml
new file mode 100644
index 0000000000000..8d3b9df6c2e15
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminResetProductGridToDefaultViewActionGroup.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeInAdditionalInformationTabActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeInAdditionalInformationTabActionGroup.xml
new file mode 100644
index 0000000000000..85537fea47e50
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeInAdditionalInformationTabActionGroup.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeNotInAdditionalInformationTabActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeNotInAdditionalInformationTabActionGroup.xml
new file mode 100644
index 0000000000000..5806bb48d783c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CheckAttributeNotInAdditionalInformationTabActionGroup.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateAttributeSetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateAttributeSetActionGroup.xml
new file mode 100644
index 0000000000000..e9e7f1c01e028
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateAttributeSetActionGroup.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateNewGroupInAttributeSetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateNewGroupInAttributeSetActionGroup.xml
new file mode 100644
index 0000000000000..9cc2fa03fc70a
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateNewGroupInAttributeSetActionGroup.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml
new file mode 100644
index 0000000000000..c095faa73d9b1
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteAttributeSetActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteAttributeSetActionGroup.xml
new file mode 100644
index 0000000000000..050c7b930a085
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteAttributeSetActionGroup.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductsOnAdminActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductsOnAdminActionGroup.xml
index 113a70cbef701..15c1a8079d4ac 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductsOnAdminActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductsOnAdminActionGroup.xml
@@ -19,10 +19,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchAndMultiSelectActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchAndMultiSelectActionGroup.xml
new file mode 100644
index 0000000000000..a55576621bd57
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchAndMultiSelectActionGroup.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [{{options}}]
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchForProductOnBackendActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchForProductOnBackendActionGroup.xml
index 12f4b5f117dee..ebeee87b1c89e 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchForProductOnBackendActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SearchForProductOnBackendActionGroup.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddToCartCustomOptionsProductPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddToCartCustomOptionsProductPageActionGroup.xml
index 921a44c7f45c3..4938b6a9592f1 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddToCartCustomOptionsProductPageActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAddToCartCustomOptionsProductPageActionGroup.xml
@@ -12,8 +12,8 @@
-
+
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml
index 1852f205c49ef..1f9bd218b1111 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryActionGroup.xml
@@ -16,7 +16,7 @@
-
+
@@ -25,9 +25,14 @@
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryCheckActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryCheckActionGroup.xml
index e3179117b3462..e560e7facc7fd 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryCheckActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryCheckActionGroup.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CatalogPriceData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogPriceData.xml
new file mode 100644
index 0000000000000..8d460fb7cbf1d
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogPriceData.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ ScopeWebsite
+ DefaultProductPrice
+
+
+ 1
+
+
+ 0
+
+
+ ScopeGlobal
+ DefaultProductPrice
+
+
+ 0
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml
index 5f8c83fe59e4f..34fd7961fab72 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml
@@ -23,8 +23,6 @@
- test product attribute
- test_product_attribute
description
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
index 2840723b1b801..d5f29230f0308 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml
@@ -33,7 +33,7 @@
ProductAttributeFrontendLabel
- testattribute
+ testattribute
select
global
false
@@ -53,4 +53,25 @@
true
ProductAttributeFrontendLabel
+
+ attribute
+ multiselect
+ global
+ false
+ false
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ ProductAttributeFrontendLabel
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeOptionData.xml
index e3b5d20372d9e..25512c0f266e9 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeOptionData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeOptionData.xml
@@ -27,4 +27,36 @@
+
+
+ option3
+ false
+ 2
+ Option3Store0
+ Option3Store1
+
+
+
+ option4
+ false
+ 3
+ Option4Store0
+ Option4Store1
+
+
+
+ option5
+ false
+ 4
+ Option5Store0
+ Option5Store1
+
+
+
+ option6
+ false
+ 5
+ Option6Store0
+ Option6Store1
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
index 0f5a66f730007..35e6d198c7f54 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
@@ -34,6 +34,32 @@
EavStockItem
CustomAttributeCategoryIds
+
+ api-simple-product
+ simple
+ 4
+ 4
+ Api Simple Product
+ 123.00
+ api-simple-product
+ 1
+ 100
+ EavStockItem
+ CustomAttributeProductAttribute
+
+
+ api-simple-product-two
+ simple
+ 4
+ 4
+ Api Simple Product Two
+ 234.00
+ api-simple-product-two
+ 1
+ 100
+ EavStockItem
+ CustomAttributeProductAttribute
+
ApiProductDescription
ApiProductShortDescription
@@ -64,6 +90,17 @@
EavStockItem
CustomAttributeCategoryIds
+
+ SimpleProduct
+ simple
+ 4
+ SimpleProduct
+ 123.00
+ 4
+ 1
+ 1000
+ EavStockItem
+
SimpleOne
simple
@@ -75,6 +112,17 @@
EavStockItem
CustomAttributeProductAttribute
+
+ SimpleOne
+ simple
+ 4
+ SimpleProductOption
+ 10.00
+ 4
+ 1
+ EavStockItem
+ CustomAttributeProductAttribute
+
Image1
1.00
@@ -83,6 +131,24 @@
magento-logo.png
magento-logo
+
+ MagentoLogo
+ 1.00
+ Upload File
+ Yes
+ magento-logo.png
+ magento-logo
+ png
+
+
+ magento-again
+ 1.00
+ Upload File
+ Yes
+ magento-again.jpg
+ magento-again
+ jpg
+
testProductWithDescriptionSku
simple
@@ -123,17 +189,6 @@
1
EavStockItem
-
- virtualproduct
- virtual
- 4
- VirtualProduct
- 99.99
- 250
- 0
- 1
- EavStockItem
-
SimpleProduct
simple
@@ -163,4 +218,35 @@
ProductAttributeMediaGalleryEntryMagentoLogo
CustomAttributeCategoryIds
+
+ api-simple-product
+ simple
+ 4
+ 4
+ Api Simple Product
+ 123.00
+ api-simple-product
+ 1
+ 100
+ EavStockItem
+ ApiProductDescription
+ ApiProductShortDescription
+
+
+ api-simple-product
+ simple
+ 4
+ 1
+ Api Simple Product
+ 123.00
+ api-simple-product
+ 1
+ 100
+ EavStockItem
+ CustomAttributeProductAttribute
+
+
+
+ ProductOptionDropDownWithLongValuesTitle
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml
index 1028988146c86..ae8bcf0893ed0 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml
@@ -48,6 +48,15 @@
ProductOptionValueDropdown1
ProductOptionValueDropdown2
+
+
+ OptionDropDownWithLongTitles
+ drop_down
+ 4
+ true
+ ProductOptionValueDropdownLongTitle1
+ ProductOptionValueDropdownLongTitle2
+
OptionRadioButtons
@@ -101,4 +110,4 @@
0.00
percent
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml
index 7ad5428794fb5..82063a771d2a3 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml
@@ -49,4 +49,16 @@
2
fixed
-
\ No newline at end of file
+
+ Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj11111Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj11111
+ 1
+ 10
+ fixed
+
+
+ Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj22222Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj22222
+ 2
+ 20
+ percent
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/StoreLabelData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/StoreLabelData.xml
index 097b388f45ea0..a703e56beda01 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/StoreLabelData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/StoreLabelData.xml
@@ -24,4 +24,36 @@
1
option2
+
+ 0
+ option3
+
+
+ 1
+ option3
+
+
+ 0
+ option4
+
+
+ 1
+ option4
+
+
+ 0
+ option5
+
+
+ 1
+ option5
+
+
+ 0
+ option6
+
+
+ 1
+ option6
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml
new file mode 100644
index 0000000000000..ae1b5afe4008a
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ $676.50
+ $615.00
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_price-meta.xml b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_price-meta.xml
new file mode 100644
index 0000000000000..7c57827356242
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Metadata/catalog_price-meta.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+ string
+
+
+ string
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminCatalogProductPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCatalogProductPage.xml
new file mode 100644
index 0000000000000..e5d3704bafcd1
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCatalogProductPage.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryEditPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryEditPage.xml
new file mode 100644
index 0000000000000..68c432a136ac9
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryEditPage.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryProductAttributeEditPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryProductAttributeEditPage.xml
new file mode 100644
index 0000000000000..035b6739c5aaf
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryProductAttributeEditPage.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeEditPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeEditPage.xml
new file mode 100644
index 0000000000000..3d7e79343155b
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeEditPage.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeSetEditPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeSetEditPage.xml
new file mode 100644
index 0000000000000..1e5ef870ba8fd
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductAttributeSetEditPage.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductCreatePage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductCreatePage.xml
index d69949d1cf05f..8c8ae0ede2eb8 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductCreatePage.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductCreatePage.xml
@@ -16,5 +16,7 @@
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductEditPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductEditPage.xml
index 3270730488aa5..4b240c4dc9421 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductEditPage.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/AdminProductEditPage.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml
index cbc460e7e5a25..b32c3ded033f9 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontProductPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontProductPage.xml
index a8b326491dbe7..9fcbcc199176b 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontProductPage.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontProductPage.xml
@@ -8,7 +8,10 @@
-
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminAddProductsToOptionPanelSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminAddProductsToOptionPanelSection.xml
new file mode 100644
index 0000000000000..75fda66ac5cb1
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminAddProductsToOptionPanelSection.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml
new file mode 100644
index 0000000000000..bf6f3c692b6c3
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeEditSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeEditSection.xml
new file mode 100644
index 0000000000000..798832f707bf0
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeEditSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeGridSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeGridSection.xml
index 96d03815df286..bb944270a10a9 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeGridSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeGridSection.xml
@@ -15,5 +15,6 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetActionSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetActionSection.xml
new file mode 100644
index 0000000000000..bf06119b75e4e
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetActionSection.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetEditSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetEditSection.xml
new file mode 100644
index 0000000000000..3334cd2dc1805
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetEditSection.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetGridSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetGridSection.xml
index 59567cc0f2b82..bc179ff95841e 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetGridSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetGridSection.xml
@@ -10,5 +10,9 @@
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetSection.xml
index edb34cb5792e2..963c4db8d7bfd 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetSection.xml
@@ -9,6 +9,15 @@
-
\ No newline at end of file
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml
index 7f7798f25f4dd..81c6a80e7e3a7 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml
@@ -10,16 +10,24 @@
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd">
-
+
-
-
-
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml
new file mode 100644
index 0000000000000..0f1fe8abeb3b5
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.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 aa63845fed385..0cbb0cb519751 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml
@@ -9,10 +9,19 @@
+
+
+
+
+
+
+
+
+
@@ -22,14 +31,19 @@
+
+
+
+
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml
index 7fc5e69766145..a02da2df51702 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml
@@ -17,5 +17,9 @@
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml
index 3a7e1ae6b0884..569b20a9c1479 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridSection.xml
@@ -17,11 +17,14 @@
-
-
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml
index 3c7bfda3196da..904003412b9c1 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml
@@ -14,6 +14,7 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml
index 080d48f0538d3..f793cd14441f7 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml
@@ -9,7 +9,8 @@
-
+
+
@@ -18,5 +19,7 @@
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
index 4f25877bbe2b8..ccb5ae60db59b 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml
@@ -13,12 +13,16 @@
-
-
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMessagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMessagesSection.xml
index 0621c18ef4ec3..f1456ac8ee387 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMessagesSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontMessagesSection.xml
@@ -11,5 +11,6 @@
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductAdditionalInformationSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductAdditionalInformationSection.xml
new file mode 100644
index 0000000000000..fcec0af892580
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductAdditionalInformationSection.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
index af2d5aa83f779..65fe9b06be66c 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml
@@ -13,6 +13,7 @@
+
@@ -49,5 +50,10 @@
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml
new file mode 100644
index 0000000000000..c738e32b3e0d7
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductMediaSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml
index d198961befb45..c960f8432e64d 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageSection.xml
@@ -10,11 +10,13 @@
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml
new file mode 100644
index 0000000000000..5742f44e1fedf
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $1,000.00
+ grabTextFromSubtotalField1
+
+
+
+
+
+
+ $1,350.00
+ grabTextFromSubtotalField2
+
+
+
+
+
+
+ $1,640.00
+ grabTextFromSubtotalField3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $1,500.00
+ grabTextFromSubtotalField4
+
+
+
+ $1,500.00
+ grabTextFromCheckoutCartSummarySectionSubtotal1
+
+
+
+
+
+ $1,500.00
+ grabTextFromMiniCartSubtotalField
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $1,500.00
+ grabTextFromSubtotalField5
+
+
+
+
+
+
+
+
+
+
+
+
+ $1,500.00
+ grabTextFromSubtotalField6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $4,000.00
+ grabTextFromSubtotalField7
+
+
+
+ $4,000.00
+ grabTextFromCheckoutCartSummarySectionSubtotal2
+
+
+
+
+
+ $4,000.00
+ grabTextFromMiniCartSubtotalField2
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml
new file mode 100644
index 0000000000000..4b75e0db0c9ab
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml
index 2dac0d483a1ba..6f477a5325e64 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml
@@ -35,6 +35,6 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductCustomAttributeSet.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductCustomAttributeSet.xml
new file mode 100644
index 0000000000000..294766794b92c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductCustomAttributeSet.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml
new file mode 100644
index 0000000000000..2a761f192f29f
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml
new file mode 100644
index 0000000000000..19b03b4bdc06d
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml
new file mode 100644
index 0000000000000..bfa22e94ccbed
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml
index ab8f272028f92..2e82f89b6fb87 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml
@@ -54,7 +54,7 @@
-
+
@@ -71,7 +71,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml
new file mode 100644
index 0000000000000..4058112a2d76c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml
@@ -0,0 +1,341 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 123.00
+
+
+
+ 123.00
+
+
+
+ 123.00
+
+
+
+ 123.00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice1
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice2
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice3
+
+
+
+
+
+
+
+
+
+
+
+ {{TestDataTierPrice.goldenPrice2}}
+ $checkProductPrice4
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice5
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice7
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice8
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice9
+
+
+
+
+
+
+
+
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice10
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice11
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice12
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice14
+
+
+ {{TestDataTierPrice.goldenPrice1}}
+ $checkProductPrice15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml
index 7925d2f3174a9..9575d7fea56fc 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml
@@ -7,7 +7,7 @@
-->
+ xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd">
@@ -21,32 +21,30 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -55,7 +53,7 @@
-
+
@@ -87,8 +85,8 @@
-
+
+
-
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest.xml
index 25ad235da8045..325a6028e4464 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest.xml
@@ -31,10 +31,10 @@
-
+
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml
index 0b3837b1f2785..c2b502fd43f34 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml
@@ -37,7 +37,7 @@
-
+
@@ -46,7 +46,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -80,6 +80,6 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml
index 648904d778843..d60130c545f10 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml
@@ -16,7 +16,6 @@
-
@@ -68,19 +67,19 @@
-
+
-
+
-
+
-
+
@@ -98,18 +97,20 @@
+
+
-
-
+
+
-
+
@@ -125,6 +126,7 @@
+
@@ -132,6 +134,7 @@
+
@@ -172,10 +175,11 @@
+
-
+
@@ -183,11 +187,12 @@
-
+
+
@@ -197,12 +202,14 @@
+
-
+
+
@@ -243,52 +250,54 @@
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
+
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml
new file mode 100644
index 0000000000000..714ea833d5b0b
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ productOptionValueText
+ Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj111 ...
+
+
+
+
+ productOptionValueTruncatedText
+ 11Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj11111
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/composer.json b/app/code/Magento/Catalog/Test/Mftf/composer.json
deleted file mode 100644
index 44c0032b3ee12..0000000000000
--- a/app/code/Magento/Catalog/Test/Mftf/composer.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "magento/functional-test-module-catalog",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/functional-test-module-eav": "100.0.0-dev",
- "magento/functional-test-module-cms": "100.0.0-dev",
- "magento/functional-test-module-indexer": "100.0.0-dev",
- "magento/functional-test-module-customer": "100.0.0-dev",
- "magento/functional-test-module-theme": "100.0.0-dev",
- "magento/functional-test-module-checkout": "100.0.0-dev",
- "magento/functional-test-module-backend": "100.0.0-dev",
- "magento/functional-test-module-widget": "100.0.0-dev",
- "magento/functional-test-module-wishlist": "100.0.0-dev",
- "magento/functional-test-module-tax": "100.0.0-dev",
- "magento/functional-test-module-msrp": "100.0.0-dev",
- "magento/functional-test-module-catalog-inventory": "100.0.0-dev",
- "magento/functional-test-module-directory": "100.0.0-dev",
- "magento/functional-test-module-catalog-rule": "100.0.0-dev",
- "magento/functional-test-module-product-alert": "100.0.0-dev",
- "magento/functional-test-module-url-rewrite": "100.0.0-dev",
- "magento/functional-test-module-catalog-url-rewrite": "100.0.0-dev",
- "magento/functional-test-module-page-cache": "100.0.0-dev",
- "magento/functional-test-module-quote": "100.0.0-dev",
- "magento/functional-test-module-config": "100.0.0-dev",
- "magento/functional-test-module-media-storage": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0",
- "magento/functional-test-module-ui": "100.0.0-dev"
- },
- "suggest": {
- "magento/functional-test-module-cookie": "100.0.0-dev",
- "magento/functional-test-module-sales": "100.0.0-dev",
- "magento/functional-test-module-catalog-sample-data": "100.0.0-dev"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php
index 7d0e38625664f..8612858960c8c 100644
--- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php
@@ -303,14 +303,8 @@ public function testCreateWithSimpleProduct($data, $expected)
$imageId = 'test_image_id';
$productMock = $this->createMock(\Magento\Catalog\Model\Product::class);
- $simpleOptionMock = $this->createMock(\Magento\Wishlist\Model\Item\Option::class);
$simpleProductMock = $this->createMock(\Magento\Catalog\Model\Product::class);
- $productMock->expects($this->once())->method('getCustomOption')
- ->with('simple_product')->willReturn($simpleOptionMock);
-
- $simpleOptionMock->expects($this->once())->method('getProduct')->willReturn($simpleProductMock);
-
$helperMock = $this->createMock(\Magento\Catalog\Helper\Image::class);
$helperMock->expects($this->once())
->method('init')
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/DeleteTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/DeleteTest.php
index af1ded6987196..196b4df5b47c0 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/DeleteTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/DeleteTest.php
@@ -71,7 +71,7 @@ protected function setUp()
false,
true,
true,
- ['addSuccess']
+ ['addSuccessMessage']
);
$this->categoryRepository = $this->createMock(\Magento\Catalog\Api\CategoryRepositoryInterface::class);
$context->expects($this->any())
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
index f6a586950afdc..74173dc926d97 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
@@ -5,8 +5,6 @@
*/
namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Category;
-use Magento\Catalog\Controller\Adminhtml\Category\Save as Model;
-
/**
* Class SaveTest
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -104,7 +102,7 @@ protected function setUp()
false,
true,
true,
- ['addSuccess', 'getMessages']
+ ['addSuccessMessage', 'getMessages']
);
$this->save = $this->objectManager->getObject(
@@ -394,7 +392,7 @@ public function testExecute($categoryId, $storeId, $parentId)
$categoryMock->expects($this->once())
->method('save');
$this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
+ ->method('addSuccessMessage')
->with(__('You saved the category.'));
$categoryMock->expects($this->at(1))
->method('getId')
@@ -463,9 +461,25 @@ public function dataProviderExecute()
*/
public function imagePreprocessingDataProvider()
{
+ $dataWithImage = [
+ 'image' => 'path.jpg',
+ 'name' => 'category',
+ 'description' => '',
+ 'parent' => 0
+ ];
+ $expectedSameAsDataWithImage = $dataWithImage;
+
+ $dataWithoutImage = [
+ 'name' => 'category',
+ 'description' => '',
+ 'parent' => 0
+ ];
+ $expectedIfDataWithoutImage = $dataWithoutImage;
+ $expectedIfDataWithoutImage['image'] = '';
+
return [
- [['attribute1' => null, 'attribute2' => 123]],
- [['attribute2' => 123]]
+ 'categoryPostData contains image' => [$dataWithImage, $expectedSameAsDataWithImage],
+ 'categoryPostData doesn\'t contain image' => [$dataWithoutImage, $expectedIfDataWithoutImage],
];
}
@@ -473,8 +487,9 @@ public function imagePreprocessingDataProvider()
* @dataProvider imagePreprocessingDataProvider
*
* @param array $data
+ * @param array $expected
*/
- public function testImagePreprocessingWithoutValue($data)
+ public function testImagePreprocessing($data, $expected)
{
$eavConfig = $this->createPartialMock(\Magento\Eav\Model\Config::class, ['getEntityType']);
@@ -484,49 +499,17 @@ public function testImagePreprocessingWithoutValue($data)
$collection = new \Magento\Framework\DataObject(['attribute_collection' => [
new \Magento\Framework\DataObject([
- 'attribute_code' => 'attribute1',
+ 'attribute_code' => 'image',
'backend' => $imageBackendModel
]),
new \Magento\Framework\DataObject([
- 'attribute_code' => 'attribute2',
+ 'attribute_code' => 'name',
'backend' => new \Magento\Framework\DataObject()
- ])
- ]]);
-
- $eavConfig->expects($this->once())
- ->method('getEntityType')
- ->with(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE)
- ->will($this->returnValue($collection));
-
- $model = $this->objectManager->getObject(\Magento\Catalog\Controller\Adminhtml\Category\Save::class, [
- 'eavConfig' => $eavConfig
- ]);
-
- $result = $model->imagePreprocessing($data);
-
- $this->assertEquals([
- 'attribute1' => false,
- 'attribute2' => 123
- ], $result);
- }
-
- public function testImagePreprocessingWithValue()
- {
- $eavConfig = $this->createPartialMock(\Magento\Eav\Model\Config::class, ['getEntityType']);
-
- $imageBackendModel = $this->objectManager->getObject(
- \Magento\Catalog\Model\Category\Attribute\Backend\Image::class
- );
-
- $collection = new \Magento\Framework\DataObject(['attribute_collection' => [
- new \Magento\Framework\DataObject([
- 'attribute_code' => 'attribute1',
- 'backend' => $imageBackendModel
]),
new \Magento\Framework\DataObject([
- 'attribute_code' => 'attribute2',
+ 'attribute_code' => 'level',
'backend' => new \Magento\Framework\DataObject()
- ])
+ ]),
]]);
$eavConfig->expects($this->once())
@@ -534,18 +517,12 @@ public function testImagePreprocessingWithValue()
->with(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE)
->will($this->returnValue($collection));
- $model = $this->objectManager->getObject(Model::class, [
+ $model = $this->objectManager->getObject(\Magento\Catalog\Controller\Adminhtml\Category\Save::class, [
'eavConfig' => $eavConfig
]);
- $result = $model->imagePreprocessing([
- 'attribute1' => 'somevalue',
- 'attribute2' => null
- ]);
+ $result = $model->imagePreprocessing($data);
- $this->assertEquals([
- 'attribute1' => 'somevalue',
- 'attribute2' => null
- ], $result);
+ $this->assertEquals($expected, $result);
}
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php
index 5a977b7934670..0ddd89afeac22 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php
@@ -94,7 +94,7 @@ private function prepareContext()
$messageManager = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
->setMethods([])
->disableOriginalConstructor()->getMock();
- $messageManager->expects($this->any())->method('addError')->willReturn(true);
+ $messageManager->expects($this->any())->method('addErrorMessage')->willReturn(true);
$this->context = $this->getMockBuilder(\Magento\Backend\App\Action\Context::class)
->setMethods(['getRequest', 'getObjectManager', 'getMessageManager', 'getResultRedirectFactory'])
->disableOriginalConstructor()->getMock();
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/SaveTest.php
index c88a008efb19b..de44af7f58afc 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/SaveTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/SaveTest.php
@@ -250,8 +250,8 @@ public function testExecuteThatProductIdsAreObtainedFromAttributeHelper()
['inventory', [], [7]],
]));
- $this->messageManager->expects($this->never())->method('addError');
- $this->messageManager->expects($this->never())->method('addException');
+ $this->messageManager->expects($this->never())->method('addErrorMessage');
+ $this->messageManager->expects($this->never())->method('addExceptionMessage');
$this->object->execute();
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
index dce3f5886d1a8..aed87f918ebb8 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
@@ -198,10 +198,12 @@ public function testInitialize(
'option2' => ['is_delete' => false, 'name' => 'name1', 'price' => 'price1', 'option_id' => '13'],
'option3' => ['is_delete' => false, 'name' => 'name1', 'price' => 'price1', 'option_id' => '14']
];
+ $specialFromDate = '2018-03-03 19:30:00';
$productData = [
'stock_data' => ['stock_data'],
'options' => $optionsData,
- 'website_ids' => $websiteIds
+ 'website_ids' => $websiteIds,
+ 'special_from_date' => $specialFromDate,
];
if (!empty($tierPrice)) {
$productData = array_merge($productData, ['tier_price' => $tierPrice]);
@@ -306,6 +308,7 @@ public function testInitialize(
}
$this->assertEquals($expectedLinks, $resultLinks);
+ $this->assertEquals($specialFromDate, $productData['special_from_date']);
}
/**
diff --git a/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php
new file mode 100644
index 0000000000000..1a9d7959dda9c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php
@@ -0,0 +1,51 @@
+indexerMock = $this->createMock(Indexer::class);
+ $this->deleteAbandonedStoreFlatTables = new DeleteAbandonedStoreFlatTables($this->indexerMock);
+ }
+
+ /**
+ * Test execute method
+ *
+ * @return void
+ */
+ public function testExecute()
+ {
+ $this->indexerMock->expects($this->once())->method('deleteAbandonedStoreFlatTables');
+ $this->deleteAbandonedStoreFlatTables->execute();
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php
new file mode 100644
index 0000000000000..c59d86aa3d5f1
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php
@@ -0,0 +1,127 @@
+resourceConnectionMock = $this->createMock(ResourceConnection::class);
+ $this->attributeRepositoryMock = $this->createMock(AttributeRepository::class);
+ $this->attributeMock = $this->createMock(Attribute::class);
+ $this->scopeConfigMock = $this->createMock(ScopeConfig::class);
+ $this->dbAdapterMock = $this->createMock(AdapterInterface::class);
+ $this->attributeBackendMock = $this->createMock(BackendInterface::class);
+ $this->deleteOutdatedPriceValues = new DeleteOutdatedPriceValues(
+ $this->resourceConnectionMock,
+ $this->attributeRepositoryMock,
+ $this->scopeConfigMock
+ );
+ }
+
+ /**
+ * Test execute method
+ *
+ * @return void
+ */
+ public function testExecute()
+ {
+ $table = 'catalog_product_entity_decimal';
+ $attributeId = 15;
+ $conditions = ['first', 'second'];
+
+ $this->scopeConfigMock->expects($this->once())->method('getValue')->with(Store::XML_PATH_PRICE_SCOPE)
+ ->willReturn(Store::XML_PATH_PRICE_SCOPE);
+ $this->attributeRepositoryMock->expects($this->once())->method('get')
+ ->with(ProductAttributeInterface::ENTITY_TYPE_CODE, ProductAttributeInterface::CODE_PRICE)
+ ->willReturn($this->attributeMock);
+ $this->attributeMock->expects($this->once())->method('getId')->willReturn($attributeId);
+ $this->attributeMock->expects($this->once())->method('getBackend')->willReturn($this->attributeBackendMock);
+ $this->attributeBackendMock->expects($this->once())->method('getTable')->willReturn($table);
+ $this->resourceConnectionMock->expects($this->once())
+ ->method('getConnection')
+ ->willReturn($this->dbAdapterMock);
+ $this->dbAdapterMock->expects($this->exactly(2))->method('quoteInto')->willReturnMap([
+ ['attribute_id = ?', $attributeId, null, null, $conditions[0]],
+ ['store_id != ?', Store::DEFAULT_STORE_ID, null, null, $conditions[1]],
+ ]);
+ $this->dbAdapterMock->expects($this->once())->method('delete')->with($table, $conditions);
+ $this->deleteOutdatedPriceValues->execute();
+ }
+
+ /**
+ * Test execute method
+ * The price scope config option is not equal to global value
+ *
+ * @return void
+ */
+ public function testExecutePriceConfigIsNotSetToGlobal()
+ {
+ $this->scopeConfigMock->expects($this->once())->method('getValue')->with(Store::XML_PATH_PRICE_SCOPE)
+ ->willReturn(null);
+ $this->attributeRepositoryMock->expects($this->never())->method('get');
+ $this->dbAdapterMock->expects($this->never())->method('delete');
+
+ $this->deleteOutdatedPriceValues->execute();
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php b/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php
new file mode 100644
index 0000000000000..e30ddda0b70b9
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php
@@ -0,0 +1,286 @@
+ 'getId',
+ ProductInterface::NAME => 'getName'
+ ];
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->helperMock = $this->getMockBuilder(Compare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->productUrlMock = $this->getMockBuilder(Url::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->outputHelperMock = $this->getMockBuilder(Output::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->objectManagerHelper = new ObjectManagerHelper($this);
+
+ $this->model = $this->objectManagerHelper->getObject(
+ CompareProducts::class,
+ [
+ 'helper' => $this->helperMock,
+ 'productUrl' => $this->productUrlMock,
+ 'outputHelper' => $this->outputHelperMock
+ ]
+ );
+ }
+
+ /**
+ * Prepare compare items collection.
+ *
+ * @param array $items
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getItemCollectionMock(array $items) : \PHPUnit_Framework_MockObject_MockObject
+ {
+ $itemCollectionMock = $this->getMockBuilder(Collection::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $itemCollectionMock->expects($this->any())
+ ->method('getIterator')
+ ->willReturn(new \ArrayIterator($items));
+
+ return $itemCollectionMock;
+ }
+
+ /**
+ * Prepare product mocks objects and add corresponding method mocks for helpers.
+ *
+ * @param array $dataSet
+ * @return array
+ */
+ private function prepareProductsWithCorrespondingMocks(array $dataSet) : array
+ {
+ $items = [];
+ $urlMap = [];
+ $outputMap = [];
+ $helperMap = [];
+
+ $count = count($dataSet);
+
+ foreach ($dataSet as $data) {
+ $item = $this->getProductMock($data);
+ $items[] = $item;
+
+ $outputMap[] = [$item, $data['name'], 'name', 'productName#' . $data['id']];
+ $helperMap[] = [$item, 'http://remove.url/' . $data['id']];
+ $urlMap[] = [$item, [], 'http://product.url/' . $data['id']];
+ }
+
+ $this->productUrlMock->expects($this->exactly($count))
+ ->method('getUrl')
+ ->will($this->returnValueMap($urlMap));
+
+ $this->outputHelperMock->expects($this->exactly($count))
+ ->method('productAttribute')
+ ->will($this->returnValueMap($outputMap));
+
+ $this->helperMock->expects($this->exactly($count))
+ ->method('getPostDataRemove')
+ ->will($this->returnValueMap($helperMap));
+
+ return $items;
+ }
+
+ /**
+ * Prepare mock of product object.
+ *
+ * @param array $data
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getProductMock(array $data) : \PHPUnit_Framework_MockObject_MockObject
+ {
+ $product = $this->getMockBuilder(Product::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ($data as $index => $value) {
+ $product->expects($this->once())
+ ->method($this->productValueMap[$index])
+ ->willReturn($value);
+ }
+
+ return $product;
+ }
+
+ public function testGetSectionData()
+ {
+ $dataSet = [
+ ['id' => 1, 'name' => 'product#1'],
+ ['id' => 2, 'name' => 'product#2'],
+ ['id' => 3, 'name' => 'product#3']
+ ];
+
+ $count = count($dataSet);
+
+ $this->helperMock->expects($this->once())
+ ->method('getItemCount')
+ ->willReturn($count);
+
+ $items = $this->prepareProductsWithCorrespondingMocks($dataSet);
+
+ $itemCollectionMock = $this->getItemCollectionMock($items);
+
+ $this->helperMock->expects($this->once())
+ ->method('getItemCollection')
+ ->willReturn($itemCollectionMock);
+
+ $this->helperMock->expects($this->once())
+ ->method('getListUrl')
+ ->willReturn('http://list.url');
+
+ $this->assertEquals(
+ [
+ 'count' => $count,
+ 'countCaption' => __('%1 items', $count),
+ 'listUrl' => 'http://list.url',
+ 'items' => [
+ [
+ 'id' => 1,
+ 'product_url' => 'http://product.url/1',
+ 'name' => 'productName#1',
+ 'remove_url' => 'http://remove.url/1'
+ ],
+ [
+ 'id' => 2,
+ 'product_url' => 'http://product.url/2',
+ 'name' => 'productName#2',
+ 'remove_url' => 'http://remove.url/2'
+ ],
+ [
+ 'id' => 3,
+ 'product_url' => 'http://product.url/3',
+ 'name' => 'productName#3',
+ 'remove_url' => 'http://remove.url/3'
+ ]
+ ]
+ ],
+ $this->model->getSectionData()
+ );
+ }
+
+ public function testGetSectionDataNoItems()
+ {
+ $count = 0;
+
+ $this->helperMock->expects($this->once())
+ ->method('getItemCount')
+ ->willReturn($count);
+
+ $this->helperMock->expects($this->never())
+ ->method('getItemCollection');
+
+ $this->helperMock->expects($this->once())
+ ->method('getListUrl')
+ ->willReturn('http://list.url');
+
+ $this->assertEquals(
+ [
+ 'count' => $count,
+ 'countCaption' => __('%1 items', $count),
+ 'listUrl' => 'http://list.url',
+ 'items' => []
+ ],
+ $this->model->getSectionData()
+ );
+ }
+
+ public function testGetSectionDataSingleItem()
+ {
+ $count = 1;
+
+ $this->helperMock->expects($this->once())
+ ->method('getItemCount')
+ ->willReturn($count);
+
+ $items = $this->prepareProductsWithCorrespondingMocks(
+ [
+ [
+ 'id' => 12345,
+ 'name' => 'SingleProduct'
+ ]
+ ]
+ );
+
+ $itemCollectionMock = $this->getItemCollectionMock($items);
+
+ $this->helperMock->expects($this->once())
+ ->method('getItemCollection')
+ ->willReturn($itemCollectionMock);
+
+ $this->helperMock->expects($this->once())
+ ->method('getListUrl')
+ ->willReturn('http://list.url');
+
+ $this->assertEquals(
+ [
+ 'count' => 1,
+ 'countCaption' => __('1 item'),
+ 'listUrl' => 'http://list.url',
+ 'items' => [
+ [
+ 'id' => 12345,
+ 'product_url' => 'http://product.url/12345',
+ 'name' => 'productName#12345',
+ 'remove_url' => 'http://remove.url/12345'
+ ]
+ ]
+ ],
+ $this->model->getSectionData()
+ );
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/SaveHandlerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/SaveHandlerTest.php
new file mode 100644
index 0000000000000..027eb5ad505ed
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/SaveHandlerTest.php
@@ -0,0 +1,176 @@
+objectManager = new ObjectManager($this);
+ $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getStore'])
+ ->getMockForAbstractClass();
+ $this->attributeRepository = $this->getMockBuilder(ProductAttributeRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['get'])
+ ->getMockForAbstractClass();
+ $this->groupManagement = $this->getMockBuilder(GroupManagementInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getAllCustomersGroup'])
+ ->getMockForAbstractClass();
+ $this->metadataPoll = $this->getMockBuilder(MetadataPool::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getMetadata'])
+ ->getMock();
+ $this->tierPriceResource = $this->getMockBuilder(Tierprice::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+
+ $this->saveHandler = $this->objectManager->getObject(
+ \Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\SaveHandler::class,
+ [
+ 'storeManager' => $this->storeManager,
+ 'attributeRepository' => $this->attributeRepository,
+ 'groupManagement' => $this->groupManagement,
+ 'metadataPoll' => $this->metadataPoll,
+ 'tierPriceResource' => $this->tierPriceResource
+ ]
+ );
+ }
+
+ public function testExecute()
+ {
+ $tierPrices = [
+ ['website_id' => 0, 'price_qty' => 2, 'cust_group' => 0, 'price' => 10],
+ ['website_id' => 0, 'price_qty' => 3, 'cust_group' => 3200, 'price' => null, 'percentage_value' => 20]
+ ];
+ $linkField = 'entity_id';
+ $productId = 10;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject $product */
+ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getData','setData', 'getStoreId'])
+ ->getMockForAbstractClass();
+ $product->expects($this->atLeastOnce())->method('getData')->willReturnMap(
+ [
+ ['tier_price', $tierPrices],
+ ['entity_id', $productId]
+ ]
+ );
+ $product->expects($this->atLeastOnce())->method('getStoreId')->willReturn(0);
+ $product->expects($this->atLeastOnce())->method('setData')->with('tier_price_changed', 1);
+ $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getWebsiteId'])
+ ->getMockForAbstractClass();
+ $store->expects($this->atLeastOnce())->method('getWebsiteId')->willReturn(0);
+ $this->storeManager->expects($this->atLeastOnce())->method('getStore')->willReturn($store);
+ /** @var \PHPUnit_Framework_MockObject_MockObject $attribute */
+ $attribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductAttributeInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getName', 'isScopeGlobal'])
+ ->getMockForAbstractClass();
+ $attribute->expects($this->atLeastOnce())->method('getName')->willReturn('tier_price');
+ $attribute->expects($this->atLeastOnce())->method('isScopeGlobal')->willReturn(true);
+ $this->attributeRepository->expects($this->atLeastOnce())->method('get')->with('tier_price')
+ ->willReturn($attribute);
+ $productMetadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getLinkField'])
+ ->getMockForAbstractClass();
+ $productMetadata->expects($this->atLeastOnce())->method('getLinkField')->willReturn($linkField);
+ $this->metadataPoll->expects($this->atLeastOnce())->method('getMetadata')
+ ->with(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->willReturn($productMetadata);
+ $customerGroup = $this->getMockBuilder(\Magento\Customer\Api\Data\GroupInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getId'])
+ ->getMockForAbstractClass();
+ $customerGroup->expects($this->atLeastOnce())->method('getId')->willReturn(3200);
+ $this->groupManagement->expects($this->atLeastOnce())->method('getAllCustomersGroup')
+ ->willReturn($customerGroup);
+ $this->tierPriceResource->expects($this->atLeastOnce())->method('savePriceData')->willReturnSelf();
+
+ $this->assertEquals($product, $this->saveHandler->execute($product));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\InputException
+ * @expectedExceptionMessage Tier prices data should be array, but actually other type is received
+ */
+ public function testExecuteWithException()
+ {
+ /** @var \PHPUnit_Framework_MockObject_MockObject $attribute */
+ $attribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductAttributeInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getName', 'isScopeGlobal'])
+ ->getMockForAbstractClass();
+ $attribute->expects($this->atLeastOnce())->method('getName')->willReturn('tier_price');
+ $this->attributeRepository->expects($this->atLeastOnce())->method('get')->with('tier_price')
+ ->willReturn($attribute);
+ /** @var \PHPUnit_Framework_MockObject_MockObject $product */
+ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getData','setData', 'getStoreId', 'getOrigData'])
+ ->getMockForAbstractClass();
+ $product->expects($this->atLeastOnce())->method('getData')->with('tier_price')->willReturn(1);
+
+ $this->saveHandler->execute($product);
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php
new file mode 100644
index 0000000000000..be2f0c5185fff
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php
@@ -0,0 +1,185 @@
+objectManager = new ObjectManager($this);
+ $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getStore'])
+ ->getMockForAbstractClass();
+ $this->attributeRepository = $this->getMockBuilder(ProductAttributeRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['get'])
+ ->getMockForAbstractClass();
+ $this->groupManagement = $this->getMockBuilder(GroupManagementInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getAllCustomersGroup'])
+ ->getMockForAbstractClass();
+ $this->metadataPoll = $this->getMockBuilder(MetadataPool::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getMetadata'])
+ ->getMock();
+ $this->tierPriceResource = $this->getMockBuilder(Tierprice::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+
+ $this->updateHandler = $this->objectManager->getObject(
+ \Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\UpdateHandler::class,
+ [
+ 'storeManager' => $this->storeManager,
+ 'attributeRepository' => $this->attributeRepository,
+ 'groupManagement' => $this->groupManagement,
+ 'metadataPoll' => $this->metadataPoll,
+ 'tierPriceResource' => $this->tierPriceResource
+ ]
+ );
+ }
+
+ public function testExecute()
+ {
+ $newTierPrices = [
+ ['website_id' => 0, 'price_qty' => 2, 'cust_group' => 0, 'price' => 15],
+ ['website_id' => 0, 'price_qty' => 3, 'cust_group' => 3200, 'price' => null, 'percentage_value' => 20]
+ ];
+ $priceIdToDelete = 2;
+ $originalTierPrices = [
+ ['price_id' => 1, 'website_id' => 0, 'price_qty' => 2, 'cust_group' => 0, 'price' => 10],
+ ['price_id' => $priceIdToDelete, 'website_id' => 0, 'price_qty' => 4, 'cust_group' => 0, 'price' => 20],
+ ];
+ $linkField = 'entity_id';
+ $productId = 10;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject $product */
+ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getData','setData', 'getStoreId', 'getOrigData'])
+ ->getMockForAbstractClass();
+ $product->expects($this->atLeastOnce())->method('getData')->willReturnMap(
+ [
+ ['tier_price', $newTierPrices],
+ ['entity_id', $productId]
+ ]
+ );
+ $product->expects($this->atLeastOnce())->method('getOrigData')->with('tier_price')
+ ->willReturn($originalTierPrices);
+ $product->expects($this->atLeastOnce())->method('getStoreId')->willReturn(0);
+ $product->expects($this->atLeastOnce())->method('setData')->with('tier_price_changed', 1);
+ $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getWebsiteId'])
+ ->getMockForAbstractClass();
+ $store->expects($this->atLeastOnce())->method('getWebsiteId')->willReturn(0);
+ $this->storeManager->expects($this->atLeastOnce())->method('getStore')->willReturn($store);
+ /** @var \PHPUnit_Framework_MockObject_MockObject $attribute */
+ $attribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductAttributeInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getName', 'isScopeGlobal'])
+ ->getMockForAbstractClass();
+ $attribute->expects($this->atLeastOnce())->method('getName')->willReturn('tier_price');
+ $attribute->expects($this->atLeastOnce())->method('isScopeGlobal')->willReturn(true);
+ $this->attributeRepository->expects($this->atLeastOnce())->method('get')->with('tier_price')
+ ->willReturn($attribute);
+ $productMetadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getLinkField'])
+ ->getMockForAbstractClass();
+ $productMetadata->expects($this->atLeastOnce())->method('getLinkField')->willReturn($linkField);
+ $this->metadataPoll->expects($this->atLeastOnce())->method('getMetadata')
+ ->with(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->willReturn($productMetadata);
+ $customerGroup = $this->getMockBuilder(\Magento\Customer\Api\Data\GroupInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getId'])
+ ->getMockForAbstractClass();
+ $customerGroup->expects($this->atLeastOnce())->method('getId')->willReturn(3200);
+ $this->groupManagement->expects($this->atLeastOnce())->method('getAllCustomersGroup')
+ ->willReturn($customerGroup);
+ $this->tierPriceResource->expects($this->exactly(2))->method('savePriceData')->willReturnSelf();
+ $this->tierPriceResource->expects($this->once())->method('deletePriceData')
+ ->with($productId, null, $priceIdToDelete);
+
+ $this->assertEquals($product, $this->updateHandler->execute($product));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\InputException
+ * @expectedExceptionMessage Tier prices data should be array, but actually other type is received
+ */
+ public function testExecuteWithException()
+ {
+ /** @var \PHPUnit_Framework_MockObject_MockObject $attribute */
+ $attribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductAttributeInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getName', 'isScopeGlobal'])
+ ->getMockForAbstractClass();
+ $attribute->expects($this->atLeastOnce())->method('getName')->willReturn('tier_price');
+ $this->attributeRepository->expects($this->atLeastOnce())->method('get')->with('tier_price')
+ ->willReturn($attribute);
+ /** @var \PHPUnit_Framework_MockObject_MockObject $product */
+ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getData','setData', 'getStoreId', 'getOrigData'])
+ ->getMockForAbstractClass();
+ $product->expects($this->atLeastOnce())->method('getData')->with('tier_price')->willReturn(1);
+
+ $this->updateHandler->execute($product);
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php
index 9df0a6bc1eac0..b9e8abe18f4ac 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php
@@ -57,10 +57,14 @@ public function testGetCollection()
$linkedProductOneMock = $this->createMock(Product::class);
$linkedProductTwoMock = $this->createMock(Product::class);
$linkedProductThreeMock = $this->createMock(Product::class);
+ $linkedProductFourMock = $this->createMock(Product::class);
+ $linkedProductFiveMock = $this->createMock(Product::class);
$linkedProductOneMock->expects($this->once())->method('getId')->willReturn(1);
$linkedProductTwoMock->expects($this->once())->method('getId')->willReturn(2);
$linkedProductThreeMock->expects($this->once())->method('getId')->willReturn(3);
+ $linkedProductFourMock->expects($this->once())->method('getId')->willReturn(4);
+ $linkedProductFiveMock->expects($this->once())->method('getId')->willReturn(5);
$this->converterPoolMock->expects($this->once())
->method('getConverter')
@@ -71,9 +75,11 @@ public function testGetCollection()
[$linkedProductOneMock, ['name' => 'Product One', 'position' => 10]],
[$linkedProductTwoMock, ['name' => 'Product Two', 'position' => 2]],
[$linkedProductThreeMock, ['name' => 'Product Three', 'position' => 2]],
+ [$linkedProductFourMock, ['name' => 'Product Four', 'position' => null]],
+ [$linkedProductFiveMock, ['name' => 'Product Five']],
];
- $this->converterMock->expects($this->exactly(3))->method('convert')->willReturnMap($map);
+ $this->converterMock->expects($this->exactly(5))->method('convert')->willReturnMap($map);
$this->providerMock->expects($this->once())
->method('getLinkedProducts')
@@ -82,14 +88,18 @@ public function testGetCollection()
[
$linkedProductOneMock,
$linkedProductTwoMock,
- $linkedProductThreeMock
+ $linkedProductThreeMock,
+ $linkedProductFourMock,
+ $linkedProductFiveMock,
]
);
$expectedResult = [
- 2 => ['name' => 'Product Two', 'position' => 2],
- 3 => ['name' => 'Product Three', 'position' => 2],
- 10 => ['name' => 'Product One', 'position' => 10],
+ 0 => ['name' => 'Product Four', 'position' => 0],
+ 1 => ['name' => 'Product Five', 'position' => 0],
+ 2 => ['name' => 'Product Three', 'position' => 2],
+ 3 => ['name' => 'Product Two', 'position' => 2],
+ 4 => ['name' => 'Product One', 'position' => 10],
];
$actualResult = $this->model->getCollection($this->productMock, 'crosssell');
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/AbstractActionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/AbstractActionTest.php
index a2ca4ef616926..3f86b577d0213 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/AbstractActionTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/AbstractActionTest.php
@@ -22,6 +22,11 @@ class AbstractActionTest extends \PHPUnit\Framework\TestCase
*/
protected $_eavSourceFactoryMock;
+ /**
+ * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $scopeConfig;
+
protected function setUp()
{
$this->_eavDecimalFactoryMock = $this->createPartialMock(
@@ -32,9 +37,16 @@ protected function setUp()
\Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory::class,
['create']
);
+ $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
$this->_model = $this->getMockForAbstractClass(
\Magento\Catalog\Model\Indexer\Product\Eav\AbstractAction::class,
- [$this->_eavDecimalFactoryMock, $this->_eavSourceFactoryMock, []]
+ [
+ $this->_eavDecimalFactoryMock,
+ $this->_eavSourceFactoryMock,
+ $this->scopeConfig
+ ]
);
}
@@ -110,6 +122,10 @@ public function testReindexWithoutArgumentsExecutesReindexAll()
->method('create')
->will($this->returnValue($eavDecimal));
+ $this->scopeConfig->expects($this->once())
+ ->method('getValue')
+ ->willReturn(1);
+
$this->_model->reindex();
}
@@ -174,9 +190,25 @@ public function testReindexWithNotNullArgumentExecutesReindexEntities(
->method('create')
->will($this->returnValue($eavDecimal));
+ $this->scopeConfig->expects($this->once())
+ ->method('getValue')
+ ->willReturn(1);
+
$this->_model->reindex($ids);
}
+ public function testReindexWithDisabledEavIndexer()
+ {
+ $this->scopeConfig->expects($this->once())
+ ->method('getValue')
+ ->willReturn(0);
+
+ $this->_eavSourceFactoryMock->expects($this->never())->method('create');
+ $this->_eavDecimalFactoryMock->expects($this->never())->method('create');
+
+ $this->_model->reindex();
+ }
+
/**
* @return array
*/
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/Action/FullTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/Action/FullTest.php
index c254557904da1..cf9e83ed39650 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/Action/FullTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Eav/Action/FullTest.php
@@ -5,53 +5,84 @@
*/
namespace Magento\Catalog\Test\Unit\Model\Indexer\Product\Eav\Action;
+use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory;
+use Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory;
+use Magento\Framework\EntityManager\MetadataPool;
+use Magento\Framework\Indexer\BatchProviderInterface;
+use Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\BatchSizeCalculator;
+
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class FullTest extends \PHPUnit\Framework\TestCase
{
- public function testExecuteWithAdapterErrorThrowsException()
- {
- $eavDecimalFactory = $this->createPartialMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory::class,
- ['create']
- );
- $eavSourceFactory = $this->createPartialMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory::class,
- ['create']
- );
+ /**
+ * @var \Magento\Catalog\Model\Indexer\Product\Eav\Action\Full|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $model;
- $exceptionMessage = 'exception message';
- $exception = new \Exception($exceptionMessage);
+ /**
+ * @var DecimalFactory|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $eavDecimalFactory;
- $eavDecimalFactory->expects($this->once())
- ->method('create')
- ->will($this->throwException($exception));
+ /**
+ * @var SourceFactory|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $eavSourceFactory;
- $metadataMock = $this->createMock(\Magento\Framework\EntityManager\MetadataPool::class);
- $batchProviderMock = $this->createMock(\Magento\Framework\Indexer\BatchProviderInterface::class);
+ /**
+ * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $metadataPool;
- $batchManagementMock = $this->createMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\BatchSizeCalculator::class
- );
+ /**
+ * @var BatchProviderInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $batchProvider;
- $tableSwitcherMock = $this->getMockBuilder(
- \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher::class
- )->disableOriginalConstructor()->getMock();
-
- $model = new \Magento\Catalog\Model\Indexer\Product\Eav\Action\Full(
- $eavDecimalFactory,
- $eavSourceFactory,
- $metadataMock,
- $batchProviderMock,
- $batchManagementMock,
- $tableSwitcherMock
- );
+ /**
+ * @var BatchSizeCalculator|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $batchSizeCalculator;
- $this->expectException(\Magento\Framework\Exception\LocalizedException::class);
- $this->expectExceptionMessage($exceptionMessage);
+ /**
+ * @var ActiveTableSwitcher|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $activeTableSwitcher;
- $model->execute();
+ /**
+ * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $scopeConfig;
+
+ protected function setUp()
+ {
+ $this->eavDecimalFactory = $this->createPartialMock(DecimalFactory::class, ['create']);
+ $this->eavSourceFactory = $this->createPartialMock(SourceFactory::class, ['create']);
+ $this->metadataPool = $this->createMock(MetadataPool::class);
+ $this->batchProvider = $this->getMockForAbstractClass(BatchProviderInterface::class);
+ $this->batchSizeCalculator = $this->createMock(BatchSizeCalculator::class);
+ $this->activeTableSwitcher = $this->createMock(ActiveTableSwitcher::class);
+ $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $objectManager = new ObjectManager($this);
+ $this->model = $objectManager->getObject(
+ \Magento\Catalog\Model\Indexer\Product\Eav\Action\Full::class,
+ [
+ 'eavDecimalFactory' => $this->eavDecimalFactory,
+ 'eavSourceFactory' => $this->eavSourceFactory,
+ 'metadataPool' => $this->metadataPool,
+ 'batchProvider' => $this->batchProvider,
+ 'batchSizeCalculator' => $this->batchSizeCalculator,
+ 'activeTableSwitcher' => $this->activeTableSwitcher,
+ 'scopeConfig' => $this->scopeConfig
+ ]
+ );
}
/**
@@ -59,14 +90,7 @@ public function testExecuteWithAdapterErrorThrowsException()
*/
public function testExecute()
{
- $eavDecimalFactory = $this->createPartialMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\DecimalFactory::class,
- ['create']
- );
- $eavSourceFactory = $this->createPartialMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\SourceFactory::class,
- ['create']
- );
+ $this->scopeConfig->expects($this->once())->method('getValue')->willReturn(1);
$ids = [1, 2, 3];
$connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
@@ -90,42 +114,29 @@ public function testExecute()
$eavSource->expects($this->atLeastOnce())->method('getConnection')->willReturn($connectionMock);
$eavDecimal->expects($this->atLeastOnce())->method('getConnection')->willReturn($connectionMock);
- $eavDecimal->expects($this->once())
- ->method('reindexEntities')
- ->with($ids);
+ $eavDecimal->expects($this->once())->method('reindexEntities')->with($ids);
- $eavSource->expects($this->once())
- ->method('reindexEntities')
- ->with($ids);
+ $eavSource->expects($this->once())->method('reindexEntities')->with($ids);
- $eavDecimalFactory->expects($this->once())
- ->method('create')
- ->will($this->returnValue($eavSource));
+ $this->eavDecimalFactory->expects($this->once())->method('create')->will($this->returnValue($eavSource));
- $eavSourceFactory->expects($this->once())
- ->method('create')
- ->will($this->returnValue($eavDecimal));
+ $this->eavSourceFactory->expects($this->once())->method('create')->will($this->returnValue($eavDecimal));
- $metadataMock = $this->createMock(\Magento\Framework\EntityManager\MetadataPool::class);
$entityMetadataMock = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
->getMockForAbstractClass();
- $metadataMock->expects($this->atLeastOnce())
+ $this->metadataPool->expects($this->atLeastOnce())
->method('getMetadata')
->with(\Magento\Catalog\Api\Data\ProductInterface::class)
->willReturn($entityMetadataMock);
- $batchProviderMock = $this->createMock(\Magento\Framework\Indexer\BatchProviderInterface::class);
- $batchProviderMock->expects($this->atLeastOnce())
+ $this->batchProvider->expects($this->atLeastOnce())
->method('getBatches')
->willReturn([['from' => 10, 'to' => 100]]);
- $batchProviderMock->expects($this->atLeastOnce())
+ $this->batchProvider->expects($this->atLeastOnce())
->method('getBatchIds')
->willReturn($ids);
- $batchManagementMock = $this->createMock(
- \Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav\BatchSizeCalculator::class
- );
$selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->disableOriginalConstructor()
->getMock();
@@ -134,19 +145,13 @@ public function testExecute()
$selectMock->expects($this->atLeastOnce())->method('distinct')->willReturnSelf();
$selectMock->expects($this->atLeastOnce())->method('from')->willReturnSelf();
- $tableSwitcherMock = $this->getMockBuilder(
- \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher::class
- )->disableOriginalConstructor()->getMock();
-
- $model = new \Magento\Catalog\Model\Indexer\Product\Eav\Action\Full(
- $eavDecimalFactory,
- $eavSourceFactory,
- $metadataMock,
- $batchProviderMock,
- $batchManagementMock,
- $tableSwitcherMock
- );
+ $this->model->execute();
+ }
- $model->execute();
+ public function testExecuteWithDisabledEavIndexer()
+ {
+ $this->scopeConfig->expects($this->once())->method('getValue')->willReturn(0);
+ $this->metadataPool->expects($this->never())->method('getMetadata');
+ $this->model->execute();
}
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
index 2572356cf855d..f095867ed5c39 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
@@ -8,7 +8,9 @@
namespace Magento\Catalog\Test\Unit\Model\Indexer\Product\Flat\Action;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -21,45 +23,48 @@ class RowTest extends \PHPUnit\Framework\TestCase
protected $model;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $storeManager;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $store;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $productIndexerHelper;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $resource;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $connection;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatItemWriter;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatItemEraser;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatTableBuilder;
+ /**
+ * @inheritdoc
+ */
protected function setUp()
{
$objectManager = new ObjectManager($this);
@@ -70,11 +75,11 @@ protected function setUp()
$this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
$this->resource->expects($this->any())->method('getConnection')
->with('default')
- ->will($this->returnValue($this->connection));
+ ->willReturn($this->connection);
$this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class);
$this->store = $this->createMock(\Magento\Store\Model\Store::class);
- $this->store->expects($this->any())->method('getId')->will($this->returnValue('store_id_1'));
- $this->storeManager->expects($this->any())->method('getStores')->will($this->returnValue([$this->store]));
+ $this->store->expects($this->any())->method('getId')->willReturn('store_id_1');
+ $this->storeManager->expects($this->any())->method('getStores')->willReturn([$this->store]);
$this->flatItemEraser = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Eraser::class);
$this->flatItemWriter = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Indexer::class);
$this->flatTableBuilder = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\FlatTableBuilder::class);
@@ -89,9 +94,7 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
$backendMock->expects($this->any())->method('getTable')->willReturn($attributeTable);
- $statusAttributeMock->expects($this->any())->method('getBackend')->willReturn(
- $backendMock
- );
+ $statusAttributeMock->expects($this->any())->method('getBackend')->willReturn($backendMock);
$statusAttributeMock->expects($this->any())->method('getId')->willReturn($statusId);
$selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->disableOriginalConstructor()
@@ -102,19 +105,30 @@ protected function setUp()
['value']
)->willReturnSelf();
$selectMock->expects($this->any())->method('where')->willReturnSelf();
+ $selectMock->expects($this->any())->method('order')->willReturnSelf();
+ $selectMock->expects($this->any())->method('limit')->willReturnSelf();
$pdoMock = $this->createMock(\Zend_Db_Statement_Pdo::class);
- $this->connection->expects($this->any())->method('query')->with($selectMock)->will($this->returnValue($pdoMock));
- $pdoMock->expects($this->any())->method('fetch')->will($this->returnValue(['value' => 1]));
+ $this->connection->expects($this->any())->method('query')->with($selectMock)->willReturn($pdoMock);
+ $pdoMock->expects($this->any())->method('fetchColumn')->willReturn('1');
+
+ $metadataPool = $this->createMock(\Magento\Framework\EntityManager\MetadataPool::class);
+ $productMetadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
+ ->getMockForAbstractClass();
+ $metadataPool->expects($this->any())->method('getMetadata')->with(ProductInterface::class)
+ ->willReturn($productMetadata);
+ $productMetadata->expects($this->any())->method('getLinkField')->willReturn('entity_id');
$this->model = $objectManager->getObject(
\Magento\Catalog\Model\Indexer\Product\Flat\Action\Row::class, [
- 'resource' => $this->resource,
- 'storeManager' => $this->storeManager,
- 'productHelper' => $this->productIndexerHelper,
- 'flatItemEraser' => $this->flatItemEraser,
- 'flatItemWriter' => $this->flatItemWriter,
+ 'resource' => $this->resource,
+ 'storeManager' => $this->storeManager,
+ 'productHelper' => $this->productIndexerHelper,
+ 'flatItemEraser' => $this->flatItemEraser,
+ 'flatItemWriter' => $this->flatItemWriter,
'flatTableBuilder' => $this->flatTableBuilder,
]);
+
+ $objectManager->setBackwardCompatibleProperty($this->model, 'metadataPool', $metadataPool);
}
/**
@@ -129,9 +143,9 @@ public function testExecuteWithEmptyId()
public function testExecuteWithNonExistingFlatTablesCreatesTables()
{
$this->productIndexerHelper->expects($this->any())->method('getFlatTableName')
- ->will($this->returnValue('store_flat_table'));
+ ->willReturn('store_flat_table');
$this->connection->expects($this->any())->method('isTableExists')->with('store_flat_table')
- ->will($this->returnValue(false));
+ ->willReturn(false);
$this->flatItemEraser->expects($this->never())->method('removeDeletedProducts');
$this->flatTableBuilder->expects($this->once())->method('build')->with('store_id_1', ['product_id_1']);
$this->flatItemWriter->expects($this->once())->method('write')->with('store_id_1', 'product_id_1');
@@ -141,12 +155,11 @@ public function testExecuteWithNonExistingFlatTablesCreatesTables()
public function testExecuteWithExistingFlatTablesCreatesTables()
{
$this->productIndexerHelper->expects($this->any())->method('getFlatTableName')
- ->will($this->returnValue('store_flat_table'));
+ ->willReturn('store_flat_table');
$this->connection->expects($this->any())->method('isTableExists')->with('store_flat_table')
- ->will($this->returnValue(true));
+ ->willReturn(true);
$this->flatItemEraser->expects($this->once())->method('removeDeletedProducts');
$this->flatTableBuilder->expects($this->never())->method('build')->with('store_id_1', ['product_id_1']);
$this->model->execute('product_id_1');
}
}
-
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Layer/Filter/DataProvider/PriceTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Layer/Filter/DataProvider/PriceTest.php
index f2c77627e38d0..8ca23df31cdee 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Layer/Filter/DataProvider/PriceTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Layer/Filter/DataProvider/PriceTest.php
@@ -152,7 +152,7 @@ public function testGetMaxPrice()
$this->productCollection->expects($this->once())
->method('getMaxPrice')
->will($this->returnValue($maxPrice));
- $this->assertSame(floatval($maxPrice), $this->target->getMaxPrice());
+ $this->assertSame((float)$maxPrice, $this->target->getMaxPrice());
}
/**
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
index a3b07262379a7..ff680916bd15f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
@@ -9,6 +9,7 @@
namespace Magento\Catalog\Test\Unit\Model;
+use Magento\Catalog\Api\Data\ProductExtensionInterface;
use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper;
@@ -16,17 +17,24 @@
use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap;
use Magento\Catalog\Model\Product\LinkTypeProvider;
use Magento\Catalog\Model\ProductFactory;
+use Magento\Catalog\Model\ProductRepository;
use Magento\Catalog\Model\ProductRepository\MediaGalleryProcessor;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\Api\Data\ImageContentInterface;
use Magento\Framework\Api\Data\ImageContentInterfaceFactory;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\ImageContentValidator;
use Magento\Framework\Api\ImageContentValidatorInterface;
+use Magento\Framework\Api\ImageProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\DB\Adapter\ConnectionException;
+use Magento\Framework\Filesystem;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Store\Api\Data\StoreInterface;
+use Magento\Store\Model\StoreManagerInterface;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
/**
@@ -42,122 +50,122 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase
private $product;
/**
- * @var MockObject
+ * @var Product|MockObject
*/
- private $initializedProductMock;
+ private $initializedProduct;
/**
- * @var \Magento\Catalog\Model\ProductRepository
+ * @var ProductRepository
*/
- protected $model;
+ private $model;
/**
- * @var MockObject
+ * @var Helper|MockObject
*/
- protected $initializationHelperMock;
+ private $initializationHelper;
/**
- * @var MockObject
+ * @var Product|MockObject
*/
- protected $resourceModelMock;
+ private $resourceModel;
/**
* @var ProductFactory|MockObject
*/
- protected $productFactory;
+ private $productFactory;
/**
- * @var MockObject
+ * @var CollectionFactory|MockObject
*/
- protected $collectionFactoryMock;
+ private $collectionFactory;
/**
- * @var MockObject
+ * @var SearchCriteriaBuilder|MockObject
*/
- protected $searchCriteriaBuilderMock;
+ private $searchCriteriaBuilder;
/**
- * @var MockObject
+ * @var FilterBuilder|MockObject
*/
- protected $filterBuilderMock;
+ private $filterBuilder;
/**
- * @var MockObject
+ * @var ProductAttributeRepositoryInterface|MockObject
*/
- protected $metadataServiceMock;
+ private $metadataService;
/**
- * @var MockObject
+ * @var ProductSearchResultsInterfaceFactory|MockObject
*/
private $searchResultsFactory;
/**
- * @var \Magento\Eav\Model\Config|MockObject
- */
- protected $eavConfigMock;
-
- /**
- * @var MockObject
+ * @var ExtensibleDataObjectConverter|MockObject
*/
- protected $extensibleDataObjectConverterMock;
+ private $extensibleDataObjectConverter;
/**
* @var array data to create product
*/
- protected $productData = [
+ private $productData = [
'sku' => 'exisiting',
'name' => 'existing product',
];
/**
- * @var MockObject|\Magento\Framework\Filesystem
+ * @var Filesystem|MockObject
*/
- protected $fileSystemMock;
+ private $fileSystem;
/**
- * @var MockObject|\Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap
+ * @var MimeTypeExtensionMap|MockObject
*/
- protected $mimeTypeExtensionMapMock;
+ private $mimeTypeExtensionMap;
/**
- * @var MockObject
+ * @var ImageContentInterfaceFactory|MockObject
*/
- protected $contentFactoryMock;
+ private $contentFactory;
/**
- * @var MockObject|\Magento\Framework\Api\ImageContentValidator
+ * @var ImageContentValidator|MockObject
*/
- protected $contentValidatorMock;
+ private $contentValidator;
/**
- * @var MockObject
+ * @var LinkTypeProvider|MockObject
*/
- protected $linkTypeProviderMock;
+ private $linkTypeProvider;
/**
- * @var MockObject|\Magento\Framework\Api\ImageProcessorInterface
+ * @var ImageProcessorInterface|MockObject
*/
- protected $imageProcessorMock;
+ private $imageProcessor;
/**
- * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+ * @var ObjectManager
*/
- protected $objectManager;
+ private $objectManager;
/**
- * @var \Magento\Store\Model\StoreManagerInterface|MockObject
+ * @var StoreManagerInterface|MockObject
*/
- protected $storeManagerMock;
+ private $storeManager;
/**
* @var MediaGalleryProcessor|MockObject
*/
- protected $mediaGalleryProcessor;
+ private $mediaGalleryProcessor;
/**
* @var CollectionProcessorInterface|MockObject
*/
- private $collectionProcessorMock;
+ private $collectionProcessor;
+
+ /**
+ * @var ProductExtensionInterface|MockObject
+ */
+ private $productExtension;
/**
* Product repository cache limit.
@@ -183,11 +191,12 @@ protected function setUp()
'load',
'setData',
'getStoreId',
- 'getMediaGalleryEntries'
+ 'getMediaGalleryEntries',
+ 'getExtensionAttributes'
]
);
- $this->initializedProductMock = $this->createPartialMock(
+ $this->initializedProduct = $this->createPartialMock(
\Magento\Catalog\Model\Product::class,
[
'getWebsiteIds',
@@ -204,73 +213,87 @@ protected function setUp()
'validate',
'save',
'getMediaGalleryEntries',
+ 'getExtensionAttributes'
]
);
- $this->initializedProductMock->expects($this->any())
+ $this->initializedProduct->expects($this->any())
->method('hasGalleryAttribute')
->willReturn(true);
- $this->filterBuilderMock = $this->createMock(\Magento\Framework\Api\FilterBuilder::class);
- $this->initializationHelperMock = $this->createMock(Helper::class);
- $this->collectionFactoryMock = $this->createPartialMock(CollectionFactory::class, ['create']);
- $this->searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class);
- $this->metadataServiceMock = $this->createMock(ProductAttributeRepositoryInterface::class);
+ $this->filterBuilder = $this->createMock(FilterBuilder::class);
+ $this->initializationHelper = $this->createMock(Helper::class);
+ $this->collectionFactory = $this->createPartialMock(CollectionFactory::class, ['create']);
+ $this->searchCriteriaBuilder = $this->createMock(SearchCriteriaBuilder::class);
+ $this->metadataService = $this->createMock(ProductAttributeRepositoryInterface::class);
$this->searchResultsFactory = $this->createPartialMock(ProductSearchResultsInterfaceFactory::class, ['create']);
- $this->resourceModelMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product::class);
+ $this->resourceModel = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product::class);
$this->objectManager = new ObjectManager($this);
- $this->extensibleDataObjectConverterMock = $this
- ->getMockBuilder(\Magento\Framework\Api\ExtensibleDataObjectConverter::class)
+ $this->extensibleDataObjectConverter = $this
+ ->getMockBuilder(ExtensibleDataObjectConverter::class)
->setMethods(['toNestedArray'])
->disableOriginalConstructor()
->getMock();
- $this->fileSystemMock = $this->getMockBuilder(\Magento\Framework\Filesystem::class)
+ $this->fileSystem = $this->getMockBuilder(Filesystem::class)
->disableOriginalConstructor()->getMock();
- $this->mimeTypeExtensionMapMock = $this->getMockBuilder(MimeTypeExtensionMap::class)
+ $this->mimeTypeExtensionMap = $this->getMockBuilder(MimeTypeExtensionMap::class)
->getMock();
- $this->contentFactoryMock = $this->createPartialMock(ImageContentInterfaceFactory::class, ['create']);
- $this->contentValidatorMock = $this->getMockBuilder(ImageContentValidatorInterface::class)
+ $this->contentFactory = $this->createPartialMock(ImageContentInterfaceFactory::class, ['create']);
+ $this->contentValidator = $this->getMockBuilder(ImageContentValidatorInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->linkTypeProviderMock = $this->createPartialMock(LinkTypeProvider::class, ['getLinkTypes']);
- $this->imageProcessorMock = $this->createMock(\Magento\Framework\Api\ImageProcessorInterface::class);
+ $this->linkTypeProvider = $this->createPartialMock(LinkTypeProvider::class, ['getLinkTypes']);
+ $this->imageProcessor = $this->createMock(ImageProcessorInterface::class);
- $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
+ $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class)
->disableOriginalConstructor()
->setMethods([])
->getMockForAbstractClass();
- $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
+ $this->productExtension = $this->getMockBuilder(ProductExtensionInterface::class)
+ ->setMethods(['__toArray'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $this->productExtension
+ ->method('__toArray')
+ ->willReturn([]);
+ $this->product
+ ->method('getExtensionAttributes')
+ ->willReturn($this->productExtension);
+ $this->initializedProduct
+ ->method('getExtensionAttributes')
+ ->willReturn($this->productExtension);
+ $storeMock = $this->getMockBuilder(StoreInterface::class)
->disableOriginalConstructor()
->setMethods([])
->getMockForAbstractClass();
$storeMock->expects($this->any())->method('getWebsiteId')->willReturn('1');
$storeMock->expects($this->any())->method('getCode')->willReturn(\Magento\Store\Model\Store::ADMIN_CODE);
- $this->storeManagerMock->expects($this->any())->method('getStore')->willReturn($storeMock);
+ $this->storeManager->expects($this->any())->method('getStore')->willReturn($storeMock);
$this->mediaGalleryProcessor = $this->createMock(MediaGalleryProcessor::class);
- $this->collectionProcessorMock = $this->getMockBuilder(CollectionProcessorInterface::class)
+ $this->collectionProcessor = $this->getMockBuilder(CollectionProcessorInterface::class)
->getMock();
$this->model = $this->objectManager->getObject(
- \Magento\Catalog\Model\ProductRepository::class,
+ ProductRepository::class,
[
'productFactory' => $this->productFactory,
- 'initializationHelper' => $this->initializationHelperMock,
- 'resourceModel' => $this->resourceModelMock,
- 'filterBuilder' => $this->filterBuilderMock,
- 'collectionFactory' => $this->collectionFactoryMock,
- 'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
- 'metadataServiceInterface' => $this->metadataServiceMock,
+ 'initializationHelper' => $this->initializationHelper,
+ 'resourceModel' => $this->resourceModel,
+ 'filterBuilder' => $this->filterBuilder,
+ 'collectionFactory' => $this->collectionFactory,
+ 'searchCriteriaBuilder' => $this->searchCriteriaBuilder,
+ 'metadataServiceInterface' => $this->metadataService,
'searchResultsFactory' => $this->searchResultsFactory,
- 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverterMock,
- 'contentValidator' => $this->contentValidatorMock,
- 'fileSystem' => $this->fileSystemMock,
- 'contentFactory' => $this->contentFactoryMock,
- 'mimeTypeExtensionMap' => $this->mimeTypeExtensionMapMock,
- 'linkTypeProvider' => $this->linkTypeProviderMock,
- 'imageProcessor' => $this->imageProcessorMock,
- 'storeManager' => $this->storeManagerMock,
+ 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter,
+ 'contentValidator' => $this->contentValidator,
+ 'fileSystem' => $this->fileSystem,
+ 'contentFactory' => $this->contentFactory,
+ 'mimeTypeExtensionMap' => $this->mimeTypeExtensionMap,
+ 'linkTypeProvider' => $this->linkTypeProvider,
+ 'imageProcessor' => $this->imageProcessor,
+ 'storeManager' => $this->storeManager,
'mediaGalleryProcessor' => $this->mediaGalleryProcessor,
- 'collectionProcessor' => $this->collectionProcessorMock,
+ 'collectionProcessor' => $this->collectionProcessor,
'serializer' => new Json(),
'cacheLimit' => $this->cacheLimit
]
@@ -285,7 +308,7 @@ public function testGetAbsentProduct()
{
$this->productFactory->expects($this->never())->method('create')
->will($this->returnValue($this->product));
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with('test_sku')
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with('test_sku')
->will($this->returnValue(null));
$this->productFactory->expects($this->never())->method('setData');
$this->model->get('test_sku');
@@ -294,7 +317,7 @@ public function testGetAbsentProduct()
public function testCreateCreatesProduct()
{
$sku = 'test_sku';
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with($sku)
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with($sku)
->will($this->returnValue('test_id'));
$this->productFactory->expects($this->once())->method('create')
->will($this->returnValue($this->product));
@@ -307,7 +330,7 @@ public function testCreateCreatesProduct()
public function testGetProductInEditMode()
{
$sku = 'test_sku';
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with($sku)
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with($sku)
->will($this->returnValue('test_id'));
$this->productFactory->expects($this->once())->method('create')
->will($this->returnValue($this->product));
@@ -322,7 +345,7 @@ public function testGetBySkuWithSpace()
{
$trimmedSku = 'test_sku';
$sku = 'test_sku ';
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with($sku)
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with($sku)
->will($this->returnValue('test_id'));
$this->productFactory->expects($this->once())->method('create')
->will($this->returnValue($this->product));
@@ -337,7 +360,7 @@ public function testGetWithSetStoreId()
$productId = 123;
$sku = 'test-sku';
$storeId = 7;
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with($sku)->willReturn($productId);
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with($sku)->willReturn($productId);
$this->productFactory->expects($this->once())->method('create')->willReturn($this->product);
$this->product->expects($this->once())->method('setData')->with('store_id', $storeId);
$this->product->expects($this->once())->method('load')->with($productId);
@@ -502,7 +525,7 @@ public function testGetForcedReload()
$editMode = false;
$storeId = 0;
- $this->resourceModelMock->expects($this->exactly(2))->method('getIdBySku')
+ $this->resourceModel->expects($this->exactly(2))->method('getIdBySku')
->with($sku)->willReturn($id);
$this->productFactory->expects($this->exactly(2))->method('create')
->will($this->returnValue($this->product));
@@ -555,16 +578,16 @@ public function testGetBySkuFromCacheInitializedInGetById()
public function testSaveExisting()
{
$id = 100;
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->any())->method('getIdBySku')->willReturn($id);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->any())->method('getIdBySku')->willReturn($id);
$this->productFactory->expects($this->any())
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->product)
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->product)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')->with($this->product)->willReturn(true);
- $this->extensibleDataObjectConverterMock
+ $this->resourceModel->expects($this->once())->method('save')->with($this->product)->willReturn(true);
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -578,19 +601,19 @@ public function testSaveExisting()
public function testSaveNew()
{
$id = 100;
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->at(0))->method('getIdBySku')->willReturn(null);
- $this->resourceModelMock->expects($this->at(3))->method('getIdBySku')->willReturn($id);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->at(0))->method('getIdBySku')->willReturn(null);
+ $this->resourceModel->expects($this->at(3))->method('getIdBySku')->willReturn($id);
$this->product->expects($this->at(0))->method('getId')->willReturn(null);
$this->product->expects($this->any())->method('getId')->willReturn($id);
$this->productFactory->expects($this->any())
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->product)
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->product)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')->with($this->product)->willReturn(true);
- $this->extensibleDataObjectConverterMock
+ $this->resourceModel->expects($this->once())->method('save')->with($this->product)->willReturn(true);
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -605,19 +628,19 @@ public function testSaveNew()
*/
public function testSaveUnableToSaveException()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->exactly(1))
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->exactly(1))
->method('getIdBySku')
->willReturn(null);
$this->productFactory->expects($this->exactly(1))
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->product)
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->product)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')->with($this->product)
+ $this->resourceModel->expects($this->once())->method('save')->with($this->product)
->willThrowException(new \Exception());
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -632,20 +655,20 @@ public function testSaveUnableToSaveException()
*/
public function testSaveException()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->exactly(1))
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->exactly(1))
->method('getIdBySku')
->willReturn(null);
$this->productFactory->expects($this->exactly(1))
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->product)
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->product)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')->with($this->product)
+ $this->resourceModel->expects($this->once())->method('save')->with($this->product)
->willThrowException(new \Magento\Eav\Model\Entity\Attribute\Exception(__('123')));
$this->product->expects($this->exactly(2))->method('getId')->willReturn(null);
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -660,22 +683,22 @@ public function testSaveException()
*/
public function testSaveInvalidProductException()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel
->expects($this->exactly(1))
->method('getIdBySku')
->willReturn(null);
$this->productFactory->expects($this->exactly(1))
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel
->expects($this->once())
->method('validate')
->with($this->product)
->willReturn(['error1', 'error2']);
$this->product->expects($this->once())->method('getId')->willReturn(null);
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -690,21 +713,21 @@ public function testSaveInvalidProductException()
*/
public function testSaveThrowsTemporaryStateExceptionIfDatabaseConnectionErrorOccurred()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
$this->productFactory->expects($this->any())
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())
+ $this->initializationHelper->expects($this->never())
->method('initialize');
- $this->resourceModelMock->expects($this->once())
+ $this->resourceModel->expects($this->once())
->method('validate')
->with($this->product)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())
+ $this->resourceModel->expects($this->once())
->method('save')
->with($this->product)
->willThrowException(new ConnectionException('Connection lost'));
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
@@ -718,7 +741,7 @@ public function testDelete()
{
$this->product->expects($this->exactly(2))->method('getSku')->willReturn('product-42');
$this->product->expects($this->exactly(2))->method('getId')->willReturn(42);
- $this->resourceModelMock->expects($this->once())->method('delete')->with($this->product)
+ $this->resourceModel->expects($this->once())->method('delete')->with($this->product)
->willReturn(true);
$this->assertTrue($this->model->delete($this->product));
}
@@ -731,7 +754,7 @@ public function testDeleteException()
{
$this->product->expects($this->exactly(2))->method('getSku')->willReturn('product-42');
$this->product->expects($this->exactly(2))->method('getId')->willReturn(42);
- $this->resourceModelMock->expects($this->once())->method('delete')->with($this->product)
+ $this->resourceModel->expects($this->once())->method('delete')->with($this->product)
->willThrowException(new \Exception());
$this->model->delete($this->product);
}
@@ -741,7 +764,7 @@ public function testDeleteById()
$sku = 'product-42';
$this->productFactory->expects($this->once())->method('create')
->will($this->returnValue($this->product));
- $this->resourceModelMock->expects($this->once())->method('getIdBySku')->with($sku)
+ $this->resourceModel->expects($this->once())->method('getIdBySku')->with($sku)
->will($this->returnValue('42'));
$this->product->expects($this->once())->method('load')->with('42');
$this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($sku);
@@ -754,7 +777,7 @@ public function testGetList()
$searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteriaInterface::class);
$collectionMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class);
- $this->collectionFactoryMock->expects($this->once())->method('create')->willReturn($collectionMock);
+ $this->collectionFactory->expects($this->once())->method('create')->willReturn($collectionMock);
$this->product->method('getSku')
->willReturn('simple');
@@ -764,7 +787,7 @@ public function testGetList()
['status', 'catalog_product/status', 'entity_id', null, 'inner'],
['visibility', 'catalog_product/visibility', 'entity_id', null, 'inner']
);
- $this->collectionProcessorMock->expects($this->once())
+ $this->collectionProcessor->expects($this->once())
->method('process')
->with($searchCriteriaMock, $collectionMock);
$collectionMock->expects($this->once())->method('load');
@@ -846,36 +869,36 @@ public function cacheKeyDataProvider()
public function testSaveExistingWithOptions(array $newOptions, array $existingOptions, array $expectedData)
{
$id = 100;
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->any())->method('getIdBySku')->will($this->returnValue($id));
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->any())->method('getIdBySku')->will($this->returnValue($id));
$this->productFactory->expects($this->any())
->method('create')
- ->willReturn($this->initializedProductMock);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock
+ ->willReturn($this->initializedProduct);
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel
->expects($this->once())->method('validate')
- ->with($this->initializedProductMock)
+ ->with($this->initializedProduct)
->willReturn(true);
- $this->resourceModelMock
+ $this->resourceModel
->expects($this->once())->method('save')
- ->with($this->initializedProductMock)
+ ->with($this->initializedProduct)
->willReturn(true);
//option data
$this->productData['options'] = $newOptions;
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
- $this->initializedProductMock
+ $this->initializedProduct
->expects($this->atLeastOnce())
->method('getSku')
->willReturn($this->productData['sku']);
$this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($this->productData['sku']);
- $this->initializedProductMock->expects($this->at(0))->method('getId')->willReturn(null);
- $this->initializedProductMock->expects($this->any())->method('getId')->willReturn($id);
+ $this->initializedProduct->expects($this->at(0))->method('getId')->willReturn(null);
+ $this->initializedProduct->expects($this->any())->method('getId')->willReturn($id);
- $this->assertEquals($this->initializedProductMock, $this->model->save($this->product));
+ $this->assertEquals($this->initializedProduct, $this->model->save($this->product));
}
/**
@@ -1026,34 +1049,34 @@ public function saveExistingWithOptionsDataProvider()
*/
public function testSaveWithLinks(array $newLinks, array $existingLinks, array $expectedData)
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
- $this->resourceModelMock->expects($this->any())->method('getIdBySku')->willReturn(100);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->resourceModel->expects($this->any())->method('getIdBySku')->willReturn(100);
$this->productFactory
->expects($this->any())
->method('create')
- ->will($this->returnValue($this->initializedProductMock));
- $this->initializedProductMock->method('getId')->willReturn(100);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock
+ ->will($this->returnValue($this->initializedProduct));
+ $this->initializedProduct->method('getId')->willReturn(100);
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel
->expects($this->once())->method('validate')
- ->with($this->initializedProductMock)
+ ->with($this->initializedProduct)
->willReturn(true);
- $this->resourceModelMock
+ $this->resourceModel
->expects($this->once())->method('save')
- ->with($this->initializedProductMock)
+ ->with($this->initializedProduct)
->willReturn(true);
- $this->initializedProductMock->setData("product_links", $existingLinks);
+ $this->initializedProduct->setData("product_links", $existingLinks);
if (!empty($newLinks)) {
$linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3];
- $this->linkTypeProviderMock
+ $this->linkTypeProvider
->expects($this->once())
->method('getLinkTypes')
->willReturn($linkTypes);
- $this->initializedProductMock->setData("ignore_links_flag", false);
- $this->resourceModelMock
+ $this->initializedProduct->setData("ignore_links_flag", false);
+ $this->resourceModel
->expects($this->any())->method('getProductsIdsBySkus')
->willReturn([$newLinks['linked_product_sku'] => $newLinks['linked_product_sku']]);
@@ -1070,31 +1093,31 @@ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $
$this->productData['product_links'] = [$inputLink];
- $this->initializedProductMock
+ $this->initializedProduct
->expects($this->any())
->method('getProductLinks')
->willReturn([$inputLink]);
} else {
- $this->resourceModelMock
+ $this->resourceModel
->expects($this->any())->method('getProductsIdsBySkus')
->willReturn([]);
$this->productData['product_links'] = [];
- $this->initializedProductMock->setData('ignore_links_flag', true);
- $this->initializedProductMock
+ $this->initializedProduct->setData('ignore_links_flag', true);
+ $this->initializedProduct
->expects($this->never())
->method('getProductLinks')
->willReturn([]);
}
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->at(0))
->method('toNestedArray')
->willReturn($this->productData);
if (!empty($newLinks)) {
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->at(1))
->method('toNestedArray')
->willReturn($newLinks);
@@ -1118,22 +1141,22 @@ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $
}
if (!empty($outputLinks)) {
- $this->initializedProductMock
+ $this->initializedProduct
->expects($this->once())
->method('setProductLinks')
->with($outputLinks);
} else {
- $this->initializedProductMock
+ $this->initializedProduct
->expects($this->never())
->method('setProductLinks');
}
- $this->initializedProductMock
+ $this->initializedProduct
->expects($this->atLeastOnce())
->method('getSku')
->willReturn($this->productData['sku']);
- $results = $this->model->save($this->initializedProductMock);
- $this->assertEquals($this->initializedProductMock, $results);
+ $results = $this->model->save($this->initializedProduct);
+ $this->assertEquals($this->initializedProduct, $results);
}
/**
@@ -1210,21 +1233,21 @@ public function saveWithLinksDataProvider()
protected function setupProductMocksForSave()
{
- $this->resourceModelMock->expects($this->any())->method('getIdBySku')->willReturn(100);
+ $this->resourceModel->expects($this->any())->method('getIdBySku')->willReturn(100);
$this->productFactory
->expects($this->any())
->method('create')
- ->willReturn($this->initializedProductMock);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->initializedProductMock)
+ ->willReturn($this->initializedProduct);
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->initializedProduct)
->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')
- ->with($this->initializedProductMock)->willReturn(true);
+ $this->resourceModel->expects($this->once())->method('save')
+ ->with($this->initializedProduct)->willReturn(true);
}
public function testSaveExistingWithNewMediaGalleryEntries()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
$newEntriesData = [
'images' => [
[
@@ -1276,23 +1299,23 @@ public function testSaveExistingWithNewMediaGalleryEntries()
'media_type' => 'media_type',
]
];
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
- $this->initializedProductMock->setData('media_gallery', $newEntriesData);
+ $this->initializedProduct->setData('media_gallery', $newEntriesData);
$this->mediaGalleryProcessor
->expects($this->once())
->method('processMediaGallery')
- ->with($this->initializedProductMock, $expectedEntriesData);
- $this->initializedProductMock
+ ->with($this->initializedProduct, $expectedEntriesData);
+ $this->initializedProduct
->expects($this->atLeastOnce())
->method('getSku')
->willReturn($this->productData['sku']);
$this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($this->productData['sku']);
- $this->initializedProductMock->expects($this->at(0))->method('getId')->willReturn(null);
- $this->initializedProductMock->expects($this->any())->method('getId')->willReturn(100);
+ $this->initializedProduct->expects($this->at(0))->method('getId')->willReturn(null);
+ $this->initializedProduct->expects($this->any())->method('getId')->willReturn(100);
$this->model->save($this->product);
}
@@ -1310,24 +1333,24 @@ public function websitesProvider()
public function testSaveWithDifferentWebsites()
{
$storeMock = $this->createMock(StoreInterface::class);
- $this->resourceModelMock->expects($this->at(0))->method('getIdBySku')->willReturn(null);
- $this->resourceModelMock->expects($this->at(3))->method('getIdBySku')->willReturn(100);
+ $this->resourceModel->expects($this->at(0))->method('getIdBySku')->willReturn(null);
+ $this->resourceModel->expects($this->at(3))->method('getIdBySku')->willReturn(100);
$this->productFactory
->expects($this->any())
->method('create')
->willReturn($this->product);
- $this->initializationHelperMock->expects($this->never())->method('initialize');
- $this->resourceModelMock->expects($this->once())->method('validate')->with($this->product)->willReturn(true);
- $this->resourceModelMock->expects($this->once())->method('save')->with($this->product)->willReturn(true);
- $this->extensibleDataObjectConverterMock
+ $this->initializationHelper->expects($this->never())->method('initialize');
+ $this->resourceModel->expects($this->once())->method('validate')->with($this->product)->willReturn(true);
+ $this->resourceModel->expects($this->once())->method('save')->with($this->product)->willReturn(true);
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
- $this->storeManagerMock
+ $this->storeManager
->expects($this->any())
->method('getStore')
->willReturn($storeMock);
- $this->storeManagerMock
+ $this->storeManager
->expects($this->once())
->method('getWebsites')
->willReturn([
@@ -1346,7 +1369,7 @@ public function testSaveWithDifferentWebsites()
public function testSaveExistingWithMediaGalleryEntries()
{
- $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
+ $this->storeManager->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']);
//update one entry, delete one entry
$newEntries = [
[
@@ -1377,24 +1400,24 @@ public function testSaveExistingWithMediaGalleryEntries()
$this->setupProductMocksForSave();
//media gallery data
$this->productData['media_gallery_entries'] = $newEntries;
- $this->extensibleDataObjectConverterMock
+ $this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->will($this->returnValue($this->productData));
- $this->initializedProductMock->setData('media_gallery', $existingMediaGallery);
+ $this->initializedProduct->setData('media_gallery', $existingMediaGallery);
$this->mediaGalleryProcessor
->expects($this->once())
->method('processMediaGallery')
- ->with($this->initializedProductMock, $newEntries);
- $this->initializedProductMock
+ ->with($this->initializedProduct, $newEntries);
+ $this->initializedProduct
->expects($this->atLeastOnce())
->method('getSku')
->willReturn($this->productData['sku']);
$this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($this->productData['sku']);
$this->product->expects($this->any())->method('getMediaGalleryEntries')->willReturn(null);
- $this->initializedProductMock->expects($this->any())->method('getId')->willReturn(100);
+ $this->initializedProduct->expects($this->any())->method('getId')->willReturn(100);
$this->model->save($this->product);
}
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
index a2e9a8e5060cc..483283e777118 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php
@@ -631,11 +631,11 @@ public function testReindex($productChanged, $isScheduled, $productFlatCount, $c
*/
public function getProductReindexProvider()
{
- return array(
+ return [
'set 1' => [true, false, 1, 1],
'set 2' => [true, true, 1, 0],
'set 3' => [false, false, 1, 0]
- );
+ ];
}
public function testPriceReindexCallback()
diff --git a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Attribute/Backend/AttributeValidationTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Attribute/Backend/AttributeValidationTest.php
new file mode 100644
index 0000000000000..944dc234e928c
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/Attribute/Backend/AttributeValidationTest.php
@@ -0,0 +1,153 @@
+attributeMock = $this->getMockBuilder(AbstractBackend::class)
+ ->setMethods(['getAttributeCode'])
+ ->getMockForAbstractClass();
+ $this->subjectMock = $this->getMockBuilder(AbstractBackend::class)
+ ->setMethods(['getAttribute'])
+ ->getMockForAbstractClass();
+ $this->subjectMock->expects($this->any())
+ ->method('getAttribute')
+ ->willReturn($this->attributeMock);
+
+ $this->storeMock = $this->getMockBuilder(StoreInterface::class)
+ ->setMethods(['getId'])
+ ->getMockForAbstractClass();
+ $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
+ ->setMethods(['getStore'])
+ ->getMockForAbstractClass();
+ $this->storeManagerMock->expects($this->any())
+ ->method('getStore')
+ ->willReturn($this->storeMock);
+
+ $this->entityMock = $this->getMockBuilder(DataObject::class)
+ ->setMethods(['getData'])
+ ->getMock();
+
+ $this->allowedEntityTypes = [$this->entityMock];
+
+ $this->proceedMock = function () {
+ $this->isProceedMockCalled = true;
+ };
+
+ $this->attributeValidation = $objectManager->getObject(
+ AttributeValidation::class,
+ [
+ 'storeManager' => $this->storeManagerMock,
+ 'allowedEntityTypes' => $this->allowedEntityTypes,
+ ]
+ );
+ }
+
+ /**
+ * @param bool $shouldProceedRun
+ * @param bool $defaultStoreUsed
+ * @param null|int|string $storeId
+ * @dataProvider aroundValidateDataProvider
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
+ * @return void
+ */
+ public function testAroundValidate(bool $shouldProceedRun, bool $defaultStoreUsed, $storeId)
+ {
+ $this->isProceedMockCalled = false;
+ $attributeCode = 'code';
+
+ $this->storeMock->expects($this->once())
+ ->method('getId')
+ ->willReturn($storeId);
+ if ($defaultStoreUsed) {
+ $this->attributeMock->expects($this->once())
+ ->method('getAttributeCode')
+ ->willReturn($attributeCode);
+ $this->entityMock->expects($this->at(0))
+ ->method('getData')
+ ->willReturn([$attributeCode => null]);
+ $this->entityMock->expects($this->at(1))
+ ->method('getData')
+ ->with($attributeCode)
+ ->willReturn(null);
+ }
+
+ $this->attributeValidation->aroundValidate($this->subjectMock, $this->proceedMock, $this->entityMock);
+ $this->assertSame($shouldProceedRun, $this->isProceedMockCalled);
+ }
+
+ /**
+ * Data provider for testAroundValidate
+ * @return array
+ */
+ public function aroundValidateDataProvider(): array
+ {
+ return [
+ [true, false, '0'],
+ [true, false, 0],
+ [true, false, null],
+ [false, true, 1],
+ ];
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php
index af10eeea42fd3..473f1aea33618 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php
@@ -63,7 +63,8 @@ protected function setUp()
'getAttributes',
'getStore',
'getAttributeDefaultValue',
- 'getExistsStoreValueFlag'
+ 'getExistsStoreValueFlag',
+ 'isLockedAttribute'
])->getMockForAbstractClass();
$this->storeMock = $this->getMockBuilder(StoreInterface::class)
->setMethods(['load', 'getId', 'getConfig'])
@@ -81,9 +82,6 @@ protected function setUp()
$this->arrayManagerMock->expects($this->any())
->method('set')
->willReturnArgument(1);
- $this->arrayManagerMock->expects($this->any())
- ->method('merge')
- ->willReturnArgument(1);
$this->arrayManagerMock->expects($this->any())
->method('remove')
->willReturnArgument(1);
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php
index c22dde0b456ac..6280de9d3a611 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier;
+use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AttributeSet;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\Collection;
@@ -84,7 +85,34 @@ protected function createModel()
public function testModifyMeta()
{
- $this->assertNotEmpty($this->getModel()->modifyMeta(['test_group' => []]));
+ $modifyMeta = $this->getModel()->modifyMeta(['test_group' => []]);
+ $this->assertNotEmpty($modifyMeta);
+ }
+
+ /**
+ * @param bool $locked
+ * @return void
+ * @dataProvider modifyMetaLockedDataProvider
+ */
+ public function testModifyMetaLocked(bool $locked)
+ {
+ $this->productMock->expects($this->any())
+ ->method('isLockedAttribute')
+ ->willReturn($locked);
+ $modifyMeta = $this->getModel()->modifyMeta([AbstractModifier::DEFAULT_GENERAL_PANEL => []]);
+ $children = $modifyMeta[AbstractModifier::DEFAULT_GENERAL_PANEL]['children'];
+ $this->assertEquals(
+ $locked,
+ $children['attribute_set_id']['arguments']['data']['config']['disabled']
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function modifyMetaLockedDataProvider()
+ {
+ return [[true], [false]];
}
public function testModifyMetaToBeEmpty()
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
index 4daff7e7930e3..cc3dda6e2d7b1 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php
@@ -114,6 +114,48 @@ public function testModifyMeta()
$this->assertArrayHasKey($groupCode, $this->getModel()->modifyMeta($meta));
}
+ /**
+ * @param bool $locked
+ * @return void
+ * @dataProvider modifyMetaLockedDataProvider
+ */
+ public function testModifyMetaLocked(bool $locked)
+ {
+ $groupCode = 'test_group_code';
+ $meta = [
+ $groupCode => [
+ 'children' => [
+ 'category_ids' => [
+ 'sortOrder' => 10,
+ ],
+ ],
+ ],
+ ];
+
+ $this->arrayManagerMock->expects($this->any())
+ ->method('findPath')
+ ->willReturn('path');
+
+ $this->productMock->expects($this->any())
+ ->method('isLockedAttribute')
+ ->willReturn($locked);
+
+ $this->arrayManagerMock->expects($this->any())
+ ->method('merge')
+ ->willReturnArgument(2);
+
+ $modifyMeta = $this->createModel()->modifyMeta($meta);
+ $this->assertEquals($locked, $modifyMeta['arguments']['data']['config']['disabled']);
+ }
+
+ /**
+ * @return array
+ */
+ public function modifyMetaLockedDataProvider()
+ {
+ return [[true], [false]];
+ }
+
public function testModifyMetaWithCaching()
{
$this->arrayManagerMock->expects($this->exactly(2))
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php
index bac75a20ea691..b65aa5fc245d6 100755
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php
@@ -5,12 +5,10 @@
*/
namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier;
-use Magento\Catalog\Model\Product\Type;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav;
use Magento\Eav\Model\Config;
use Magento\Eav\Model\Entity\Attribute\Source\SourceInterface;
use Magento\Framework\App\RequestInterface;
-use Magento\Framework\EntityManager\EventManager;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Ui\DataProvider\EavValidationRules;
@@ -458,15 +456,18 @@ public function testModifyData()
* @param bool $productRequired
* @param string|null $attrValue
* @param array $expected
+ * @param bool $locked
+ * @return void
* @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::isProductExists
* @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::setupAttributeMeta
* @dataProvider setupAttributeMetaDataProvider
*/
public function testSetupAttributeMetaDefaultAttribute(
$productId,
- $productRequired,
+ bool $productRequired,
$attrValue,
- $expected
+ array $expected,
+ bool $locked = false
) {
$configPath = 'arguments/data/config';
$groupCode = 'product-details';
@@ -486,41 +487,26 @@ public function testSetupAttributeMetaDefaultAttribute(
['value' => ['test1', 'test2'], 'label' => 'Array label']
];
- $this->productMock->method('getId')
- ->willReturn($productId);
-
- $this->productAttributeMock->method('getIsRequired')
- ->willReturn($productRequired);
-
- $this->productAttributeMock->method('getDefaultValue')
- ->willReturn('required_value');
-
- $this->productAttributeMock->method('getAttributeCode')
- ->willReturn('code');
-
- $this->productAttributeMock->method('getValue')
- ->willReturn('value');
+ $this->productMock->method('getId')->willReturn($productId);
+ $this->productMock->expects($this->any())->method('isLockedAttribute')->willReturn($locked);
+ $this->productAttributeMock->method('getIsRequired')->willReturn($productRequired);
+ $this->productAttributeMock->method('getDefaultValue')->willReturn('required_value');
+ $this->productAttributeMock->method('getAttributeCode')->willReturn('code');
+ $this->productAttributeMock->method('getValue')->willReturn('value');
$attributeMock = $this->getMockBuilder(AttributeInterface::class)
->setMethods(['getValue'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $attributeMock->method('getValue')
- ->willReturn($attrValue);
-
- $this->productMock->method('getCustomAttribute')
- ->willReturn($attributeMock);
- $this->eavAttributeMock->method('usesSource')
- ->willReturn(true);
+ $attributeMock->method('getValue')->willReturn($attrValue);
+ $this->productMock->method('getCustomAttribute')->willReturn($attributeMock);
+ $this->eavAttributeMock->method('usesSource')->willReturn(true);
- $attributeSource = $this->getMockBuilder(SourceInterface::class)
- ->getMockForAbstractClass();
- $attributeSource->method('getAllOptions')
- ->willReturn($attributeOptions);
+ $attributeSource = $this->getMockBuilder(SourceInterface::class)->getMockForAbstractClass();
+ $attributeSource->method('getAllOptions')->willReturn($attributeOptions);
- $this->eavAttributeMock->method('getSource')
- ->willReturn($attributeSource);
+ $this->eavAttributeMock->method('getSource')->willReturn($attributeSource);
$this->arrayManagerMock->method('set')
->with(
@@ -530,24 +516,22 @@ public function testSetupAttributeMetaDefaultAttribute(
)
->willReturn($expected);
- $this->arrayManagerMock->expects($this->once())
+ $this->arrayManagerMock->expects($this->any())
->method('merge')
->with(
$this->anything(),
$this->anything(),
$this->callback(
function ($value) use ($attributeOptionsExpected) {
- return $value['options'] === $attributeOptionsExpected;
+ return isset($value['options']) ? $value['options'] === $attributeOptionsExpected : true;
}
)
)
->willReturn($expected);
- $this->arrayManagerMock->method('get')
- ->willReturn([]);
+ $this->arrayManagerMock->method('get')->willReturn([]);
- $this->arrayManagerMock->method('exists')
- ->willReturn(true);
+ $this->arrayManagerMock->method('exists')->willReturn(true);
$this->assertEquals(
$expected,
@@ -557,84 +541,105 @@ function ($value) use ($attributeOptionsExpected) {
/**
* @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function setupAttributeMetaDataProvider()
{
return [
'default_null_prod_not_new_and_required' => [
- 'productId' => 1,
- 'productRequired' => true,
- 'attrValue' => 'val',
- 'expected' => [
- 'dataType' => null,
- 'formElement' => null,
- 'visible' => null,
- 'required' => true,
- 'notice' => null,
- 'default' => null,
- 'label' => null,
- 'code' => 'code',
- 'source' => 'product-details',
- 'scopeLabel' => '',
- 'globalScope' => false,
- 'sortOrder' => 0
+ 'productId' => 1,
+ 'productRequired' => true,
+ 'attrValue' => 'val',
+ 'expected' => [
+ 'dataType' => null,
+ 'formElement' => null,
+ 'visible' => null,
+ 'required' => true,
+ 'notice' => null,
+ 'default' => null,
+ 'label' => null,
+ 'code' => 'code',
+ 'source' => 'product-details',
+ 'scopeLabel' => '',
+ 'globalScope' => false,
+ 'sortOrder' => 0
],
],
+ 'default_null_prod_not_new_locked_and_required' => [
+ 'productId' => 1,
+ 'productRequired' => true,
+ 'attrValue' => 'val',
+ 'expected' => [
+ 'dataType' => null,
+ 'formElement' => null,
+ 'visible' => null,
+ 'required' => true,
+ 'notice' => null,
+ 'default' => null,
+ 'label' => null,
+ 'code' => 'code',
+ 'source' => 'product-details',
+ 'scopeLabel' => '',
+ 'globalScope' => false,
+ 'sortOrder' => 0,
+ ],
+ 'locked' => true,
+ ],
'default_null_prod_not_new_and_not_required' => [
- 'productId' => 1,
- 'productRequired' => false,
- 'attrValue' => 'val',
- 'expected' => [
- 'dataType' => null,
- 'formElement' => null,
- 'visible' => null,
- 'required' => false,
- 'notice' => null,
- 'default' => null,
- 'label' => null,
- 'code' => 'code',
- 'source' => 'product-details',
- 'scopeLabel' => '',
- 'globalScope' => false,
- 'sortOrder' => 0
+ 'productId' => 1,
+ 'productRequired' => false,
+ 'attrValue' => 'val',
+ 'expected' => [
+ 'dataType' => null,
+ 'formElement' => null,
+ 'visible' => null,
+ 'required' => false,
+ 'notice' => null,
+ 'default' => null,
+ 'label' => null,
+ 'code' => 'code',
+ 'source' => 'product-details',
+ 'scopeLabel' => '',
+ 'globalScope' => false,
+ 'sortOrder' => 0
],
],
'default_null_prod_new_and_not_required' => [
- 'productId' => null,
- 'productRequired' => false,
- 'attrValue' => null,
- 'expected' => [
- 'dataType' => null,
- 'formElement' => null,
- 'visible' => null,
- 'required' => false,
- 'notice' => null,
- 'default' => 'required_value',
- 'label' => null,
- 'code' => 'code',
- 'source' => 'product-details',
- 'scopeLabel' => '',
- 'globalScope' => false,
- 'sortOrder' => 0
+ 'productId' => null,
+ 'productRequired' => false,
+ 'attrValue' => null,
+ 'expected' => [
+ 'dataType' => null,
+ 'formElement' => null,
+ 'visible' => null,
+ 'required' => false,
+ 'notice' => null,
+ 'default' => 'required_value',
+ 'label' => null,
+ 'code' => 'code',
+ 'source' => 'product-details',
+ 'scopeLabel' => '',
+ 'globalScope' => false,
+ 'sortOrder' => 0
],
],
'default_null_prod_new_and_required' => [
- 'productId' => null,
- 'productRequired' => false,
- 'attrValue' => null,
- 'expected' => [
- 'dataType' => null,
- 'formElement' => null,
- 'visible' => null,
- 'required' => false,
- 'notice' => null,
- 'default' => 'required_value',
- 'label' => null,
- 'code' => 'code',
- 'source' => 'product-details',
- 'scopeLabel' => '',
- 'globalScope' => false,
- 'sortOrder' => 0
+ 'productId' => null,
+ 'productRequired' => false,
+ 'attrValue' => null,
+ 'expected' => [
+ 'dataType' => null,
+ 'formElement' => null,
+ 'visible' => null,
+ 'required' => false,
+ 'notice' => null,
+ 'default' => 'required_value',
+ 'label' => null,
+ 'code' => 'code',
+ 'source' => 'product-details',
+ 'scopeLabel' => '',
+ 'globalScope' => false,
+ 'sortOrder' => 0
],
]
];
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php
index 0eeaa11d57b63..0f247e7cca85f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php
@@ -61,8 +61,14 @@ protected function createModel()
]);
}
+ /**
+ * @return void
+ */
public function testModifyMeta()
{
+ $this->arrayManagerMock->expects($this->any())
+ ->method('merge')
+ ->willReturnArgument(2);
$this->assertNotEmpty($this->getModel()->modifyMeta([
'first_panel_code' => [
'arguments' => [
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php
index d4d4136bf4157..855a756b550a6 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php
@@ -22,8 +22,14 @@ protected function createModel()
]);
}
+ /**
+ * @return void
+ */
public function testModifyMeta()
{
+ $this->arrayManagerMock->expects($this->any())
+ ->method('merge')
+ ->willReturnArgument(1);
$this->assertSame([], $this->getModel()->modifyMeta([]));
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php
index 997b66861c21b..f38e2a0d426d1 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php
@@ -76,7 +76,10 @@ class WebsitesTest extends AbstractModifierTest
protected function setUp()
{
- $this->objectManager = new ObjectManager($this);
+ parent::setUp();
+ $this->productMock->expects($this->any())
+ ->method('getId')
+ ->willReturn(self::PRODUCT_ID);
$this->assignedWebsites = [self::SECOND_WEBSITE_ID];
$this->websiteMock = $this->getMockBuilder(\Magento\Store\Model\Website::class)
->setMethods(['getId', 'getName'])
@@ -87,35 +90,28 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
$this->websiteRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\WebsiteRepositoryInterface::class)
- ->setMethods(['getList', 'getDefault'])
+ ->setMethods(['getDefault'])
->getMockForAbstractClass();
$this->websiteRepositoryMock->expects($this->any())
->method('getDefault')
->willReturn($this->websiteMock);
- $this->websiteRepositoryMock->expects($this->any())
- ->method('getList')
- ->willReturn([$this->websiteMock, $this->secondWebsiteMock]);
$this->groupRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\GroupRepositoryInterface::class)
->setMethods(['getList'])
->getMockForAbstractClass();
$this->storeRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\StoreRepositoryInterface::class)
->setMethods(['getList'])
->getMockForAbstractClass();
- $this->locatorMock = $this->getMockBuilder(\Magento\Catalog\Model\Locator\LocatorInterface::class)
- ->setMethods(['getProduct', 'getWebsiteIds'])
- ->getMockForAbstractClass();
$this->productMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
->setMethods(['getId'])
->getMockForAbstractClass();
- $this->locatorMock->expects($this->any())
- ->method('getProduct')
- ->willReturn($this->productMock);
$this->locatorMock->expects($this->any())
->method('getWebsiteIds')
->willReturn($this->assignedWebsites);
$this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
- ->setMethods(['isSingleStoreMode'])
+ ->setMethods(['isSingleStoreMode', 'getWebsites'])
->getMockForAbstractClass();
+ $this->storeManagerMock->method('getWebsites')
+ ->willReturn([$this->websiteMock, $this->secondWebsiteMock]);
$this->storeManagerMock->expects($this->any())
->method('isSingleStoreMode')
->willReturn(false);
@@ -148,9 +144,6 @@ protected function setUp()
$this->storeRepositoryMock->expects($this->any())
->method('getList')
->willReturn([$this->storeViewMock]);
- $this->productMock->expects($this->any())
- ->method('getId')
- ->willReturn(self::PRODUCT_ID);
$this->secondWebsiteMock->expects($this->any())
->method('getId')
->willReturn($this->assignedWebsites[0]);
diff --git a/app/code/Magento/Catalog/Ui/Component/FilterFactory.php b/app/code/Magento/Catalog/Ui/Component/FilterFactory.php
index fcc500c891607..dd8eaffb0a658 100644
--- a/app/code/Magento/Catalog/Ui/Component/FilterFactory.php
+++ b/app/code/Magento/Catalog/Ui/Component/FilterFactory.php
@@ -71,8 +71,6 @@ public function create($attribute, $context, $config = [])
*/
protected function getFilterType($attribute)
{
- return isset($this->filterMap[$attribute->getFrontendInput()])
- ? $this->filterMap[$attribute->getFrontendInput()]
- : $this->filterMap['default'];
+ return $this->filterMap[$attribute->getFrontendInput()] ?? $this->filterMap['default'];
}
}
diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns.php
index c96498b054d25..8ea6d8b9e5a06 100644
--- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns.php
+++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns.php
@@ -80,6 +80,6 @@ public function prepare()
*/
protected function getFilterType($frontendInput)
{
- return isset($this->filterMap[$frontendInput]) ? $this->filterMap[$frontendInput] : $this->filterMap['default'];
+ return $this->filterMap[$frontendInput] ?? $this->filterMap['default'];
}
}
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
index a17b7071593dc..37b0b328a522b 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
@@ -432,7 +432,8 @@ private function getTierPriceStructure($tierPricePath)
'dndConfig' => [
'enabled' => false,
],
- 'disabled' => false,
+ 'disabled' =>
+ $this->arrayManager->get($tierPricePath . '/arguments/data/config/disabled', $this->meta),
'required' => false,
'sortOrder' =>
$this->arrayManager->get($tierPricePath . '/arguments/data/config/sortOrder', $this->meta),
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php
index a1aacc91f2e47..0733d21bf47d7 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php
@@ -108,6 +108,7 @@ public function modifyMeta(array $meta)
self::ATTRIBUTE_SET_FIELD_ORDER
),
'multiple' => false,
+ 'disabled' => $this->locator->getProduct()->isLockedAttribute('attribute_set_id'),
];
}
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
index 7456c1bfef91f..2dad7e8495b11 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php
@@ -228,6 +228,7 @@ protected function customizeCategoriesField(array $meta)
'componentType' => 'container',
'component' => 'Magento_Ui/js/form/components/group',
'scopeLabel' => __('[GLOBAL]'),
+ 'disabled' => $this->locator->getProduct()->isLockedAttribute($fieldCode),
],
],
],
@@ -288,6 +289,7 @@ protected function customizeCategoriesField(array $meta)
'source' => 'product_details',
'displayArea' => 'insideGroup',
'sortOrder' => 20,
+ 'dataScope' => $fieldCode,
],
],
]
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
index d6103e18c6e36..c56d3d2d7d354 100755
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
@@ -40,6 +40,7 @@
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyFields)
+ * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @since 101.0.0
*/
class Eav extends AbstractModifier
@@ -281,7 +282,7 @@ public function modifyMeta(array $meta)
if ($attributes) {
$meta[$groupCode]['children'] = $this->getAttributesMeta($attributes, $groupCode);
$meta[$groupCode]['arguments']['data']['config']['componentType'] = Fieldset::NAME;
- $meta[$groupCode]['arguments']['data']['config']['label'] = __('%1', $group->getAttributeGroupName());
+ $meta[$groupCode]['arguments']['data']['config']['label'] = __($group->getAttributeGroupName());
$meta[$groupCode]['arguments']['data']['config']['collapsible'] = true;
$meta[$groupCode]['arguments']['data']['config']['dataScope'] = self::DATA_SCOPE_PRODUCT;
$meta[$groupCode]['arguments']['data']['config']['sortOrder'] =
@@ -589,7 +590,7 @@ private function getPreviousSetAttributes()
*/
private function isProductExists()
{
- return (bool) $this->locator->getProduct()->getId();
+ return (bool)$this->locator->getProduct()->getId();
}
/**
@@ -608,7 +609,7 @@ private function isProductExists()
public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupCode, $sortOrder)
{
$configPath = ltrim(static::META_CONFIG_PATH, ArrayManager::DEFAULT_PATH_DELIMITER);
-
+ $attributeCode = $attribute->getAttributeCode();
$meta = $this->arrayManager->set($configPath, [], [
'dataType' => $attribute->getFrontendInput(),
'formElement' => $this->getFormElementsMapValue($attribute->getFrontendInput()),
@@ -617,7 +618,7 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC
'notice' => $attribute->getNote(),
'default' => (!$this->isProductExists()) ? $attribute->getDefaultValue() : null,
'label' => $attribute->getDefaultFrontendLabel(),
- 'code' => $attribute->getAttributeCode(),
+ 'code' => $attributeCode,
'source' => $groupCode,
'scopeLabel' => $this->getScopeLabel($attribute),
'globalScope' => $this->isScopeGlobal($attribute),
@@ -647,7 +648,8 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC
]);
}
- if (in_array($attribute->getAttributeCode(), $this->attributesToDisable)) {
+ $product = $this->locator->getProduct();
+ if (in_array($attributeCode, $this->attributesToDisable) || $product->isLockedAttribute($attributeCode)) {
$meta = $this->arrayManager->merge($configPath, $meta, [
'disabled' => true,
]);
@@ -853,7 +855,7 @@ private function getFormElementsMapValue($value)
{
$valueMap = $this->formElementMapper->getMappings();
- return isset($valueMap[$value]) ? $valueMap[$value] : $value;
+ return $valueMap[$value] ?? $value;
}
/**
@@ -907,6 +909,9 @@ private function canDisplayUseDefault(ProductAttributeInterface $attribute)
$attributeCode = $attribute->getAttributeCode();
/** @var Product $product */
$product = $this->locator->getProduct();
+ if ($product->isLockedAttribute($attributeCode)) {
+ return false;
+ }
if (isset($this->canDisplayUseDefault[$attributeCode])) {
return $this->canDisplayUseDefault[$attributeCode];
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
index 819788d6aa6be..ec3ef58ded569 100755
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php
@@ -202,7 +202,7 @@ protected function customizeStatusField(array $meta)
protected function customizeWeightField(array $meta)
{
$weightPath = $this->arrayManager->findPath(ProductAttributeInterface::CODE_WEIGHT, $meta, null, 'children');
-
+ $disabled = $this->arrayManager->get($weightPath . '/arguments/data/config/disabled', $meta);
if ($weightPath) {
$meta = $this->arrayManager->merge(
$weightPath . static::META_CONFIG_PATH,
@@ -214,7 +214,7 @@ protected function customizeWeightField(array $meta)
],
'additionalClasses' => 'admin__field-small',
'addafter' => $this->locator->getStore()->getConfig('general/locale/weight_unit'),
- 'imports' => [
+ 'imports' => $disabled ? [] : [
'disabled' => '!${$.provider}:' . self::DATA_SCOPE_PRODUCT
. '.product_has_weight:value'
]
@@ -254,6 +254,7 @@ protected function customizeWeightField(array $meta)
],
],
'value' => (int)$this->locator->getProduct()->getTypeInstance()->hasWeight(),
+ 'disabled' => $disabled,
]
);
}
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php
index 298da3d5cd6f2..8166c42a5a8b1 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php
@@ -135,7 +135,6 @@ public function modifyMeta(array $meta)
'collapsible' => true,
'componentType' => Form\Fieldset::NAME,
'dataScope' => self::DATA_SCOPE_PRODUCT,
- 'disabled' => false,
'sortOrder' => $this->getNextGroupSortOrder(
$meta,
'search-engine-optimization',
@@ -176,9 +175,11 @@ protected function getFieldsForFieldset()
$label = __('Websites');
$defaultWebsiteId = $this->websiteRepository->getDefault()->getId();
+ $isOnlyOneWebsiteAvailable = count($websitesList) === 1;
foreach ($websitesList as $website) {
$isChecked = in_array($website['id'], $websiteIds)
- || ($defaultWebsiteId == $website['id'] && $isNewProduct);
+ || ($defaultWebsiteId == $website['id'] && $isNewProduct)
+ || $isOnlyOneWebsiteAvailable;
$children[$website['id']] = [
'arguments' => [
'data' => [
@@ -196,6 +197,7 @@ protected function getFieldsForFieldset()
'false' => '0',
],
'value' => $isChecked ? (string)$website['id'] : '0',
+ 'disabled' => $this->locator->getProduct()->isLockedAttribute('website_ids'),
],
],
],
@@ -397,8 +399,9 @@ protected function getWebsitesList()
$this->websitesList = [];
$groupList = $this->groupRepository->getList();
$storesList = $this->storeRepository->getList();
+ $websiteList = $this->storeManager->getWebsites(true);
- foreach ($this->websiteRepository->getList() as $website) {
+ foreach ($websiteList as $website) {
$websiteId = $website->getId();
if (!$websiteId) {
continue;
diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json
index 57bb7d1e4ccef..4535e527d2dec 100644
--- a/app/code/Magento/Catalog/composer.json
+++ b/app/code/Magento/Catalog/composer.json
@@ -34,7 +34,7 @@
"magento/module-catalog-sample-data": "Sample Data version:100.2.*"
},
"type": "magento2-module",
- "version": "102.0.5",
+ "version": "102.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Catalog/etc/adminhtml/events.xml b/app/code/Magento/Catalog/etc/adminhtml/events.xml
index f4fd7fc30398c..ad83f5898237a 100644
--- a/app/code/Magento/Catalog/etc/adminhtml/events.xml
+++ b/app/code/Magento/Catalog/etc/adminhtml/events.xml
@@ -9,4 +9,7 @@
+
+
+
diff --git a/app/code/Magento/Catalog/etc/config.xml b/app/code/Magento/Catalog/etc/config.xml
index 3569c0a27b83f..74f7a0e082dd6 100644
--- a/app/code/Magento/Catalog/etc/config.xml
+++ b/app/code/Magento/Catalog/etc/config.xml
@@ -52,6 +52,11 @@
php,exe
+
+
+ none
+
+
diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index 3eecfb3c7453a..c64ed54608542 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -70,6 +70,7 @@
+
@@ -549,7 +550,6 @@
- Magento\Catalog\Console\Command\ImagesResizeCommand
- Magento\Catalog\Console\Command\ProductAttributesCleanUp
- - Magento\Catalog\Console\Command\PriceIndexerDimensionsModeSetCommand
@@ -655,12 +655,14 @@
- Magento\Catalog\Model\Product\Gallery\CreateHandler
- Magento\Catalog\Model\Category\Link\SaveHandler
- Magento\Catalog\Model\Product\Website\SaveHandler
+ - Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\SaveHandler
-
- Magento\Catalog\Model\Product\Option\SaveHandler
- Magento\Catalog\Model\Product\Gallery\UpdateHandler
- Magento\Catalog\Model\Category\Link\SaveHandler
- Magento\Catalog\Model\Product\Website\SaveHandler
+ - Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\UpdateHandler
@@ -1127,4 +1129,18 @@
virtual
+
+
+
+ - Magento\Catalog\Model\Indexer\Product\Price\ModeSwitcher
+
+
+
+
+
+
+ - catalog_product_price
+
+
+
diff --git a/app/code/Magento/Catalog/etc/widget.xml b/app/code/Magento/Catalog/etc/widget.xml
index ff3773981d407..ea53f5215b7e6 100644
--- a/app/code/Magento/Catalog/etc/widget.xml
+++ b/app/code/Magento/Catalog/etc/widget.xml
@@ -292,7 +292,7 @@
-
+
diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv
index b8b2d25d58b48..35a2c224c4ed2 100644
--- a/app/code/Magento/Catalog/i18n/en_US.csv
+++ b/app/code/Magento/Catalog/i18n/en_US.csv
@@ -13,8 +13,8 @@ Position,Position
Day,Day
Month,Month
Year,Year
-"from ","from "
-"to ","to "
+from,from
+to,to
[GLOBAL],[GLOBAL]
[WEBSITE],[WEBSITE]
"[STORE VIEW]","[STORE VIEW]"
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/form.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/form.phtml
index 74cf8f5f3a70b..124194519b978 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/form.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/form.phtml
@@ -21,13 +21,13 @@
= $block->getChildHtml('form') ?>
-
-
-
= /* @escapeNotVerified */ $block->getFormScripts() ?>
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml
index 8a5f1919f78be..3cbfa0f29d74f 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml
@@ -55,7 +55,7 @@ function bindAttributeInputType()
{
checkOptionsPanelVisibility();
switchDefaultValueField();
- if($('frontend_input') && ($('frontend_input').value=='select' || $('frontend_input').value=='multiselect' || $('frontend_input').value=='price')){
+ if($('frontend_input') && ($('frontend_input').value=='boolean' || $('frontend_input').value=='select' || $('frontend_input').value=='multiselect' || $('frontend_input').value=='price')){
if($('is_filterable') && !$('is_filterable').getAttribute('readonly')){
$('is_filterable').disabled = false;
}
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml
index 8e5583a6699b7..30c05c2ec689b 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml
@@ -13,7 +13,7 @@
= $block->escapeHtml($_option->getTitle()) ?>
- = /* @escapeNotVerified */ $block->getFormatedPrice() ?>
+ = /* @escapeNotVerified */ $block->getFormattedPrice() ?>
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml
index edf4f68afded7..4ad7a95c91980 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml
@@ -7,6 +7,7 @@
// @codingStandardsIgnoreFile
?>
+
getOption(); ?>
getFileInfo(); ?>
hasData() ? true : false; ?>
@@ -64,7 +65,7 @@ require(['prototype'], function(){
= $block->escapeHtml($_option->getTitle()) ?>
- = /* @escapeNotVerified */ $block->getFormatedPrice() ?>
+ = /* @escapeNotVerified */ $block->getFormattedPrice() ?>
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/text.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/text.phtml
index 14e485c6445e0..11fba22ea8139 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/text.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/text.phtml
@@ -12,7 +12,7 @@
= $block->escapeHtml($_option->getTitle()) ?>
- = /* @escapeNotVerified */ $block->getFormatedPrice() ?>
+ = /* @escapeNotVerified */ $block->getFormattedPrice() ?>
getType() == \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_FIELD): ?>
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/action/attribute.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/action/attribute.phtml
index d1591d70945cf..a3b0b32e4c29a 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/action/attribute.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/action/attribute.phtml
@@ -11,11 +11,12 @@
-
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
index 6a5f6c4648494..a7e8564e7a1d8 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
@@ -14,7 +14,7 @@
<% } %>
<% if (!data.term && data.items.length && !data.allShown()) { %>
diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml
index 923b690eae736..793ed3b1bfc93 100644
--- a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml
+++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml
@@ -42,7 +42,7 @@
-
+
false
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/edit/attribute.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/edit/attribute.js
new file mode 100644
index 0000000000000..407fd1fe28e39
--- /dev/null
+++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/edit/attribute.js
@@ -0,0 +1,18 @@
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+ 'jquery',
+ 'mage/mage'
+], function ($) {
+ 'use strict';
+
+ return function (config, element) {
+
+ $(element).mage('form').mage('validation', {
+ validationUrl: config.validationUrl
+ });
+ };
+});
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js b/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js
index 72cad03eabe1b..1d64418e36ff5 100644
--- a/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js
+++ b/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js
@@ -230,6 +230,7 @@ define([
categoryLoader.on('beforeload', function (treeLoader, node) {
treeLoader.baseParams.id = node.attributes.id;
+ treeLoader.baseParams.selected = options.jsFormObject.updateElement.value;
});
/* eslint-disable */
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js
index 475c9d2dc0601..1c79331253251 100644
--- a/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js
+++ b/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js
@@ -67,7 +67,7 @@ define([
},
/**
- * Has weight swither
+ * Has weight switcher
* @returns {*}
*/
hasWeightSwither: function () {
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html
index a6a1b3e5b05e8..a319576195f75 100644
--- a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html
+++ b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html
@@ -13,7 +13,8 @@
event="load: $parent.onPreviewLoad.bind($parent)"
attr="
src: $parent.getFilePreview($file),
- alt: $file.name">
+ alt: $file.name,
+ title: $file.name">
diff --git a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
index 86168c742c0f1..ce1561e382eed 100644
--- a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
+++ b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml
@@ -19,9 +19,8 @@
= ($block->getPriceDisplayLabel()) ? 'data-label="' . $block->getPriceDisplayLabel() . $block->getPriceDisplayInclExclTaxes() . '"' : '' ?>
data-price-amount="= /* @escapeNotVerified */ $block->getDisplayValue() ?>"
data-price-type="= /* @escapeNotVerified */ $block->getPriceType() ?>"
- class="price-wrapper = /* @escapeNotVerified */ $block->getPriceWrapperCss() ?>">
- = /* @escapeNotVerified */ $block->formatCurrency($block->getDisplayValue(), (bool)$block->getIncludeContainer()) ?>
-
+ class="price-wrapper = /* @escapeNotVerified */ $block->getPriceWrapperCss() ?>"
+ >= /* @escapeNotVerified */ $block->formatCurrency($block->getDisplayValue(), (bool)$block->getIncludeContainer()) ?>
hasAdjustmentsHtml()): ?>
= $block->getAdjustmentsHtml() ?>
diff --git a/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image.html b/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image.html
index 318a6ceed69d1..cf76762b1ff58 100644
--- a/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image.html
+++ b/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image.html
@@ -11,6 +11,7 @@
class="product-image-photo"
attr="src: getImageUrl($row()),
alt: getLabel($row()),
+ title: getLabel($row()),
width: getResizedImageWidth($row()),
height: getResizedImageHeight($row())"/>
diff --git a/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image_with_borders.html b/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image_with_borders.html
index 2baa9926df5f1..68b7f4e386896 100644
--- a/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image_with_borders.html
+++ b/app/code/Magento/Catalog/view/base/web/template/product/list/columns/image_with_borders.html
@@ -14,7 +14,7 @@
data-bind="style: {'padding-bottom': getHeight($row())/getWidth($row()) * 100 + '%'}">
+ alt: getLabel($row()), title: getLabel($row())}" />
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml
index 16a5147e13458..adf0f44d0c831 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml
@@ -6,7 +6,7 @@
// @codingStandardsIgnoreFile
-/** @var $block \Magento\Catalog\Block\Catalog\Product\View\Addto\Compare */
+/** @var $block \Magento\Catalog\Block\Product\View\Addto\Compare */
?>
-
+
diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/catalog-add-to-cart.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/catalog-add-to-cart.js
new file mode 100644
index 0000000000000..3e6a611c268af
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/catalog-add-to-cart.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+require([
+ 'jquery'
+], function ($) {
+ 'use strict';
+
+ /**
+ * Add selected configurable attributes to redirect url
+ *
+ * @see Magento_Catalog/js/catalog-add-to-cart
+ */
+ $('body').on('catalogCategoryAddToCartRedirect', function (event, data) {
+ $(data.form).find('select[name*="super"]').each(function (index, item) {
+ data.redirectParameters.push(item.config.id + '=' + $(item).val());
+ });
+ });
+});
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 8cabe71c17504..6b6c1762fadd9 100644
--- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
+++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js
@@ -360,7 +360,11 @@ define([
index = 1,
allowedProducts,
i,
- j;
+ j,
+ basePrice = parseFloat(this.options.spConfig.prices.basePrice.amount),
+ optionFinalPrice,
+ optionPriceDiff,
+ optionPrices = this.options.spConfig.optionPrices;
this._clearSelect(element);
element.options[0] = new Option('', '');
@@ -374,6 +378,7 @@ define([
if (options) {
for (i = 0; i < options.length; i++) {
allowedProducts = [];
+ optionPriceDiff = 0;
/* eslint-disable max-depth */
if (prevConfig) {
@@ -387,6 +392,20 @@ define([
}
} else {
allowedProducts = options[i].products.slice(0);
+
+ if (typeof allowedProducts[0] !== 'undefined' &&
+ typeof optionPrices[allowedProducts[0]] !== 'undefined') {
+
+ optionFinalPrice = parseFloat(optionPrices[allowedProducts[0]].finalPrice.amount);
+ optionPriceDiff = optionFinalPrice - basePrice;
+
+ if (optionPriceDiff !== 0) {
+ options[i].label = options[i].label + ' ' + priceUtils.formatPrice(
+ optionPriceDiff,
+ this.options.priceFormat,
+ true);
+ }
+ }
}
if (allowedProducts.length > 0) {
@@ -394,7 +413,7 @@ define([
element.options[index] = new Option(this._getOptionLabel(options[i]), options[i].id);
if (typeof options[i].price !== 'undefined') {
- element.options[index].setAttribute('price', options[i].prices);
+ element.options[index].setAttribute('price', options[i].price);
}
element.options[index].config = options[i];
diff --git a/app/code/Magento/ConfigurableProductSales/Test/Mftf/composer.json b/app/code/Magento/ConfigurableProductSales/Test/Mftf/composer.json
deleted file mode 100644
index 21dbce122386f..0000000000000
--- a/app/code/Magento/ConfigurableProductSales/Test/Mftf/composer.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "magento/functional-test-module-configurable-product-sales",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-catalog": "100.0.0-dev",
- "magento/functional-test-module-sales": "100.0.0-dev",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0"
- },
- "suggest": {
- "magento/functional-test-module-configurable-product": "100.0.0-dev"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/ConfigurableProductSales/composer.json b/app/code/Magento/ConfigurableProductSales/composer.json
index d1fbc142b627f..ca6638924b8c6 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.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Contact/Test/Mftf/composer.json b/app/code/Magento/Contact/Test/Mftf/composer.json
deleted file mode 100644
index bdfb3265948ac..0000000000000
--- a/app/code/Magento/Contact/Test/Mftf/composer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "magento/functional-test-module-contact",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-config": "100.0.0-dev",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/functional-test-module-customer": "100.0.0-dev",
- "magento/functional-test-module-cms": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json
index 9ceca3bdfa80b..49ac8ec40dbc4 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.2",
+ "version": "100.2.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cookie/Test/Mftf/composer.json b/app/code/Magento/Cookie/Test/Mftf/composer.json
deleted file mode 100644
index d65a11f025000..0000000000000
--- a/app/code/Magento/Cookie/Test/Mftf/composer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "magento/functional-test-module-cookie",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0"
- },
- "suggest": {
- "magento/functional-test-module-backend": "100.0.0-dev"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/Cookie/composer.json b/app/code/Magento/Cookie/composer.json
index 23bd37234f939..cc04b0ccd5d7d 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.1",
+ "version": "100.2.2",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js
index 253950747ce14..f1f3754ea54b1 100644
--- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js
+++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js
@@ -29,7 +29,7 @@ define([
});
if ($.mage.cookies.get(this.options.cookieName)) {
- window.location.reload();
+ this.element.hide();
} else {
window.location.href = this.options.noCookiesUrl;
}
diff --git a/app/code/Magento/Cron/Console/Command/CronCommand.php b/app/code/Magento/Cron/Console/Command/CronCommand.php
index 78bbb2329f8dc..142a9a397eb5f 100644
--- a/app/code/Magento/Cron/Console/Command/CronCommand.php
+++ b/app/code/Magento/Cron/Console/Command/CronCommand.php
@@ -10,10 +10,12 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
+use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ObjectManagerFactory;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManager;
use Magento\Cron\Observer\ProcessCronQueueObserver;
+use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\Console\Cli;
use Magento\Framework\Shell\ComplexParameter;
@@ -35,13 +37,24 @@ class CronCommand extends Command
private $objectManagerFactory;
/**
- * Constructor
+ * Application deployment configuration
*
+ * @var DeploymentConfig
+ */
+ private $deploymentConfig;
+
+ /**
* @param ObjectManagerFactory $objectManagerFactory
+ * @param DeploymentConfig $deploymentConfig Application deployment configuration
*/
- public function __construct(ObjectManagerFactory $objectManagerFactory)
- {
+ public function __construct(
+ ObjectManagerFactory $objectManagerFactory,
+ DeploymentConfig $deploymentConfig = null
+ ) {
$this->objectManagerFactory = $objectManagerFactory;
+ $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(
+ DeploymentConfig::class
+ );
parent::__construct();
}
@@ -71,10 +84,16 @@ protected function configure()
}
/**
+ * Runs cron jobs if cron is not disabled in Magento configurations
+ *
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ if (!$this->deploymentConfig->get('cron/enabled', 1)) {
+ $output->writeln('' . 'Cron is disabled. Jobs were not run.' . ' ');
+ return;
+ }
$omParams = $_SERVER;
$omParams[StoreManager::PARAM_RUN_CODE] = 'admin';
$omParams[Store::CUSTOM_ENTRY_POINT_PARAM] = true;
diff --git a/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php b/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php
index 2fc0f0ab4c1a0..87618785adb1d 100644
--- a/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php
+++ b/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php
@@ -72,14 +72,14 @@ public function afterSave()
$frequency = $this->getData('groups/productalert_cron/fields/frequency/value');
$cronExprArray = [
- intval($time[1]), //Minute
- intval($time[0]), //Hour
+ (int)$time[1], //Minute
+ (int)$time[0], //Hour
$frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_MONTHLY ? '1' : '*', //Day of the Month
'*', //Month of the Year
$frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_WEEKLY ? '1' : '*', //Day of the Week
];
- $cronExprString = join(' ', $cronExprArray);
+ $cronExprString = implode(' ', $cronExprArray);
try {
$this->_configValueFactory->create()->load(
diff --git a/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php b/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php
index 681129916647d..31d8ba59ee42d 100644
--- a/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php
+++ b/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php
@@ -70,8 +70,8 @@ public function afterSave()
$frequency = $this->getData('groups/generate/fields/frequency/value');
$cronExprArray = [
- intval($time[1]), //Minute
- intval($time[0]), //Hour
+ (int)$time[1], //Minute
+ (int)$time[0], //Hour
$frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_MONTHLY ? '1' : '*', //Day of the Month
'*', //Month of the Year
$frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_WEEKLY ? '1' : '*', //# Day of the Week
diff --git a/app/code/Magento/Cron/Test/Mftf/composer.json b/app/code/Magento/Cron/Test/Mftf/composer.json
deleted file mode 100644
index cdee4efef8a24..0000000000000
--- a/app/code/Magento/Cron/Test/Mftf/composer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "magento/functional-test-module-cron",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0"
- },
- "suggest": {
- "magento/functional-test-module-config": "100.0.0-dev"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/Cron/Test/Unit/Console/Command/CronCommandTest.php b/app/code/Magento/Cron/Test/Unit/Console/Command/CronCommandTest.php
index 8b3e50d6afb3a..6b1af9323cc93 100644
--- a/app/code/Magento/Cron/Test/Unit/Console/Command/CronCommandTest.php
+++ b/app/code/Magento/Cron/Test/Unit/Console/Command/CronCommandTest.php
@@ -6,19 +6,74 @@
namespace Magento\Cron\Test\Unit\Console\Command;
use Magento\Cron\Console\Command\CronCommand;
+use Magento\Framework\App\DeploymentConfig;
+use Magento\Framework\App\ObjectManagerFactory;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Symfony\Component\Console\Tester\CommandTester;
class CronCommandTest extends \PHPUnit\Framework\TestCase
{
+ /**
+ * @var ObjectManagerFactory|MockObject
+ */
+ private $objectManagerFactory;
+
+ /**
+ * @var DeploymentConfig|MockObject
+ */
+ private $deploymentConfigMock;
+
+ protected function setUp()
+ {
+ $this->objectManagerFactory = $this->createMock(ObjectManagerFactory::class);
+ $this->deploymentConfigMock = $this->createMock(DeploymentConfig::class);
+ }
+
+ /**
+ * Test command with disables cron
+ *
+ * @return void
+ */
+ public function testExecuteWithDisabledCrons()
+ {
+ $this->objectManagerFactory->expects($this->never())
+ ->method('create');
+ $this->deploymentConfigMock->expects($this->once())
+ ->method('get')
+ ->with('cron/enabled', 1)
+ ->willReturn(0);
+ $commandTester = new CommandTester(
+ new CronCommand($this->objectManagerFactory, $this->deploymentConfigMock)
+ );
+ $commandTester->execute([]);
+ $expectedMsg = 'Cron is disabled. Jobs were not run.' . PHP_EOL;
+ $this->assertEquals($expectedMsg, $commandTester->getDisplay());
+ }
+
+ /**
+ * Test command with enabled cron
+ *
+ * @return void
+ */
public function testExecute()
{
- $objectManagerFactory = $this->createMock(\Magento\Framework\App\ObjectManagerFactory::class);
$objectManager = $this->createMock(\Magento\Framework\ObjectManagerInterface::class);
$cron = $this->createMock(\Magento\Framework\App\Cron::class);
- $objectManager->expects($this->once())->method('create')->willReturn($cron);
- $cron->expects($this->once())->method('launch');
- $objectManagerFactory->expects($this->once())->method('create')->willReturn($objectManager);
- $commandTester = new CommandTester(new CronCommand($objectManagerFactory));
+ $objectManager->expects($this->once())
+ ->method('create')
+ ->willReturn($cron);
+ $cron->expects($this->once())
+ ->method('launch');
+ $this->objectManagerFactory->expects($this->once())
+ ->method('create')
+ ->willReturn($objectManager);
+ $this->deploymentConfigMock->expects($this->once())
+ ->method('get')
+ ->with('cron/enabled', 1)
+ ->willReturn(1);
+ $commandTester = new CommandTester(
+ new CronCommand($this->objectManagerFactory, $this->deploymentConfigMock)
+ );
$commandTester->execute([]);
$expectedMsg = 'Ran jobs by schedule.' . PHP_EOL;
$this->assertEquals($expectedMsg, $commandTester->getDisplay());
diff --git a/app/code/Magento/Cron/Test/Unit/Model/System/Config/Initial/ConverterTest.php b/app/code/Magento/Cron/Test/Unit/Model/System/Config/Initial/ConverterTest.php
new file mode 100644
index 0000000000000..703926b4c0116
--- /dev/null
+++ b/app/code/Magento/Cron/Test/Unit/Model/System/Config/Initial/ConverterTest.php
@@ -0,0 +1,89 @@
+groupsConfigMock = $this->getMockBuilder(
+ GroupsConfigModel::class
+ )->disableOriginalConstructor()->getMock();
+ $this->converterMock = $this->getMockBuilder(Converter::class)->getMock();
+ $this->converterPlugin = new ConverterPlugin($this->groupsConfigMock);
+ }
+
+ /**
+ * Tests afterConvert method with no $result['data']['default']['system'] set
+ */
+ public function testAfterConvertWithNoData()
+ {
+ $expectedResult = ['test'];
+ $this->groupsConfigMock->expects($this->never())
+ ->method('get');
+
+ $result = $this->converterPlugin->afterConvert($this->converterMock, $expectedResult);
+
+ self::assertSame($expectedResult, $result);
+ }
+
+ /**
+ * Tests afterConvert method with $result['data']['default']['system'] set
+ */
+ public function testAfterConvertWithData()
+ {
+ $groups = [
+ 'group1' => ['val1' => ['value' => '1']],
+ 'group2' => ['val2' => ['value' => '2']]
+ ];
+ $expectedResult['data']['default']['system']['cron'] = [
+ 'group1' => [
+ 'val1' => '1'
+ ],
+ 'group2' => [
+ 'val2' => '2'
+ ]
+ ];
+ $result['data']['default']['system']['cron'] = '1';
+
+ $this->groupsConfigMock->expects($this->once())
+ ->method('get')
+ ->willReturn($groups);
+
+ $result = $this->converterPlugin->afterConvert($this->converterMock, $result);
+
+ self::assertEquals($expectedResult, $result);
+ }
+}
diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json
index 5faf1d15e7782..a8c124dc57207 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.3",
+ "version": "100.2.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Cron/etc/cron_groups.xml b/app/code/Magento/Cron/etc/cron_groups.xml
index a01426eab723e..9aa57662427c8 100644
--- a/app/code/Magento/Cron/etc/cron_groups.xml
+++ b/app/code/Magento/Cron/etc/cron_groups.xml
@@ -11,8 +11,8 @@
20
15
10
- 10080
- 10080
+ 60
+ 4320
0
diff --git a/app/code/Magento/Cron/etc/di.xml b/app/code/Magento/Cron/etc/di.xml
index a37f3760b70a5..3e3bdc2053576 100644
--- a/app/code/Magento/Cron/etc/di.xml
+++ b/app/code/Magento/Cron/etc/di.xml
@@ -16,6 +16,18 @@
+
+
+ /var/log/cron.log
+
+
+
+
+
+ - Magento\Cron\Model\VirtualLoggerHandler
+
+
+
@@ -25,6 +37,7 @@
shellBackground
+ Magento\Cron\Model\VirtualLogger
diff --git a/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php b/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php
index fcde688a1e145..518e7fcf4181f 100644
--- a/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php
+++ b/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php
@@ -192,9 +192,11 @@ public function getCurrencySymbolsData()
*/
public function setCurrencySymbolsData($symbols = [])
{
- foreach ($this->getCurrencySymbolsData() as $code => $values) {
- if (isset($symbols[$code]) && ($symbols[$code] == $values['parentSymbol'] || empty($symbols[$code]))) {
- unset($symbols[$code]);
+ if (!$this->_storeManager->isSingleStoreMode()) {
+ foreach ($this->getCurrencySymbolsData() as $code => $values) {
+ if (isset($symbols[$code]) && ($symbols[$code] == $values['parentSymbol'] || empty($symbols[$code]))) {
+ unset($symbols[$code]);
+ }
}
}
$value = [];
diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/composer.json b/app/code/Magento/CurrencySymbol/Test/Mftf/composer.json
deleted file mode 100644
index e6815bb61a2d3..0000000000000
--- a/app/code/Magento/CurrencySymbol/Test/Mftf/composer.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "name": "magento/functional-test-module-currency-symbol",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-config": "100.0.0-dev",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/functional-test-module-page-cache": "100.0.0-dev",
- "magento/functional-test-module-directory": "100.0.0-dev",
- "magento/functional-test-module-backend": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json
index 3afa8c6338378..da76425436038 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.1",
+ "version": "100.2.2",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml
index 0ba3c7ed2d7d6..6e9b9a396ec2f 100644
--- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml
+++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml
@@ -23,10 +23,9 @@
name="custom_currency_symbol[= /* @escapeNotVerified */ $code ?>]">
diff --git a/app/code/Magento/Customer/Api/AccountManagementInterface.php b/app/code/Magento/Customer/Api/AccountManagementInterface.php
index d2f9fb7ebc420..0bda1fc4bb815 100644
--- a/app/code/Magento/Customer/Api/AccountManagementInterface.php
+++ b/app/code/Magento/Customer/Api/AccountManagementInterface.php
@@ -7,6 +7,8 @@
namespace Magento\Customer\Api;
+use Magento\Framework\Exception\InputException;
+
/**
* Interface for managing customers accounts.
* @api
@@ -144,19 +146,24 @@ public function initiatePasswordReset($email, $template, $websiteId = null);
/**
* Reset customer password.
*
- * @param string $email
+ * @param string $email If empty value given then the customer
+ * will be matched by the RP token.
* @param string $resetToken
* @param string $newPassword
+ *
* @return bool true on success
* @throws \Magento\Framework\Exception\LocalizedException
+ * @throws InputException
*/
public function resetPassword($email, $resetToken, $newPassword);
/**
* Check if password reset token is valid.
*
- * @param int $customerId
+ * @param int $customerId If 0 is given then a customer
+ * will be matched by the RP token.
* @param string $resetPasswordLinkToken
+ *
* @return bool True if the token is valid
* @throws \Magento\Framework\Exception\State\InputMismatchException If token is mismatched
* @throws \Magento\Framework\Exception\State\ExpiredException If token is expired
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
index 81b7b8b3f96b5..c7023d0404f75 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
@@ -461,7 +461,7 @@ protected function getOnlineMinutesInterval()
'customer/online_customers/online_minutes_interval',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
- return intval($configValue) > 0 ? intval($configValue) : self::DEFAULT_ONLINE_MINUTES_INTERVAL;
+ return (int)$configValue > 0 ? (int)$configValue : self::DEFAULT_ONLINE_MINUTES_INTERVAL;
}
/**
diff --git a/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php b/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php
new file mode 100644
index 0000000000000..2be340c8ccca4
--- /dev/null
+++ b/app/code/Magento/Customer/Block/DataProviders/AddressAttributeData.php
@@ -0,0 +1,62 @@
+addressMetadata = $addressMetadata;
+ $this->escaper = $escaper;
+ }
+
+ /**
+ * Returns frontend label for attribute.
+ *
+ * @param string $attributeCode
+ * @return string
+ * @throws LocalizedException
+ */
+ public function getFrontendLabel(string $attributeCode): string
+ {
+ try {
+ $attribute = $this->addressMetadata->getAttributeMetadata($attributeCode);
+ $frontendLabel = $attribute->getFrontendLabel();
+ } catch (NoSuchEntityException $e) {
+ $frontendLabel = '';
+ }
+
+ return $this->escaper->escapeHtml(__($frontendLabel));
+ }
+}
diff --git a/app/code/Magento/Customer/Controller/Account/CreatePassword.php b/app/code/Magento/Customer/Controller/Account/CreatePassword.php
index fb2e3dd42908b..a86f42c14a027 100644
--- a/app/code/Magento/Customer/Controller/Account/CreatePassword.php
+++ b/app/code/Magento/Customer/Controller/Account/CreatePassword.php
@@ -54,27 +54,30 @@ public function __construct(
public function execute()
{
$resetPasswordToken = (string)$this->getRequest()->getParam('token');
- $customerId = (int)$this->getRequest()->getParam('id');
- $isDirectLink = $resetPasswordToken != '' && $customerId != 0;
+ $isDirectLink = $resetPasswordToken != '';
if (!$isDirectLink) {
$resetPasswordToken = (string)$this->session->getRpToken();
- $customerId = (int)$this->session->getRpCustomerId();
}
try {
- $this->accountManagement->validateResetPasswordLinkToken($customerId, $resetPasswordToken);
+ $this->accountManagement->validateResetPasswordLinkToken(
+ 0,
+ $resetPasswordToken
+ );
if ($isDirectLink) {
$this->session->setRpToken($resetPasswordToken);
- $this->session->setRpCustomerId($customerId);
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('*/*/createpassword');
+
return $resultRedirect;
} else {
/** @var \Magento\Framework\View\Result\Page $resultPage */
$resultPage = $this->resultPageFactory->create();
- $resultPage->getLayout()->getBlock('resetPassword')->setCustomerId($customerId)
+ $resultPage->getLayout()
+ ->getBlock('resetPassword')
->setResetPasswordLinkToken($resetPasswordToken);
+
return $resultPage;
}
} catch (\Exception $exception) {
diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php
index 3f895ad2f17ac..da0ad29c5c72f 100644
--- a/app/code/Magento/Customer/Controller/Account/EditPost.php
+++ b/app/code/Magento/Customer/Controller/Account/EditPost.php
@@ -20,6 +20,7 @@
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\InvalidEmailOrPasswordException;
use Magento\Framework\Exception\State\UserLockedException;
+use Magento\Framework\Escaper;
/**
* Class EditPost
@@ -72,6 +73,9 @@ class EditPost extends \Magento\Customer\Controller\AbstractAccount
*/
private $customerMapper;
+ /** @var Escaper */
+ private $escaper;
+
/**
* @param Context $context
* @param Session $customerSession
@@ -79,6 +83,7 @@ class EditPost extends \Magento\Customer\Controller\AbstractAccount
* @param CustomerRepositoryInterface $customerRepository
* @param Validator $formKeyValidator
* @param CustomerExtractor $customerExtractor
+ * @param Escaper|null $escaper
*/
public function __construct(
Context $context,
@@ -86,7 +91,8 @@ public function __construct(
AccountManagementInterface $customerAccountManagement,
CustomerRepositoryInterface $customerRepository,
Validator $formKeyValidator,
- CustomerExtractor $customerExtractor
+ CustomerExtractor $customerExtractor,
+ Escaper $escaper = null
) {
parent::__construct($context);
$this->session = $customerSession;
@@ -94,6 +100,7 @@ public function __construct(
$this->customerRepository = $customerRepository;
$this->formKeyValidator = $formKeyValidator;
$this->customerExtractor = $customerExtractor;
+ $this->escaper = $escaper ?: ObjectManager::getInstance()->get(Escaper::class);
}
/**
@@ -175,9 +182,9 @@ public function execute()
$this->messageManager->addError($message);
return $resultRedirect->setPath('customer/account/login');
} catch (InputException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage()));
foreach ($e->getErrors() as $error) {
- $this->messageManager->addError($error->getMessage());
+ $this->messageManager->addErrorMessage($this->escaper->escapeHtml($error->getMessage()));
}
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addError($e->getMessage());
diff --git a/app/code/Magento/Customer/Controller/Account/LoginPost.php b/app/code/Magento/Customer/Controller/Account/LoginPost.php
index b55863a3b486a..c2bf31ca83e0e 100644
--- a/app/code/Magento/Customer/Controller/Account/LoginPost.php
+++ b/app/code/Magento/Customer/Controller/Account/LoginPost.php
@@ -171,27 +171,24 @@ public function execute()
'This account is not confirmed.
Click here to resend confirmation email.',
$value
);
- $this->messageManager->addError($message);
- $this->session->setUsername($login['username']);
} catch (UserLockedException $e) {
$message = __(
'You did not sign in correctly or your account is temporarily disabled.'
);
- $this->messageManager->addError($message);
- $this->session->setUsername($login['username']);
} catch (AuthenticationException $e) {
$message = __('You did not sign in correctly or your account is temporarily disabled.');
- $this->messageManager->addError($message);
- $this->session->setUsername($login['username']);
} catch (LocalizedException $e) {
$message = $e->getMessage();
- $this->messageManager->addError($message);
- $this->session->setUsername($login['username']);
} catch (\Exception $e) {
// PA DSS violation: throwing or logging an exception here can disclose customer password
$this->messageManager->addError(
__('An unspecified error occurred. Please contact us for assistance.')
);
+ } finally {
+ if (isset($message)) {
+ $this->messageManager->addError($message);
+ $this->session->setUsername($login['username']);
+ }
}
} else {
$this->messageManager->addError(__('A login and a password are required.'));
diff --git a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php
index 3de44e35d2447..ab6944a995d84 100644
--- a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php
+++ b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php
@@ -12,7 +12,6 @@
use Magento\Framework\App\Action\Context;
use Magento\Framework\Exception\InputException;
use Magento\Customer\Model\Customer\CredentialsValidator;
-use Magento\Framework\App\ObjectManager;
class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount
{
@@ -31,17 +30,14 @@ class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount
*/
protected $session;
- /**
- * @var CredentialsValidator
- */
- private $credentialsValidator;
-
/**
* @param Context $context
* @param Session $customerSession
* @param AccountManagementInterface $accountManagement
* @param CustomerRepositoryInterface $customerRepository
* @param CredentialsValidator|null $credentialsValidator
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
Context $context,
@@ -53,8 +49,6 @@ public function __construct(
$this->session = $customerSession;
$this->accountManagement = $accountManagement;
$this->customerRepository = $customerRepository;
- $this->credentialsValidator = $credentialsValidator ?: ObjectManager::getInstance()
- ->get(CredentialsValidator::class);
parent::__construct($context);
}
@@ -70,27 +64,33 @@ public function execute()
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
$resetPasswordToken = (string)$this->getRequest()->getQuery('token');
- $customerId = (int)$this->getRequest()->getQuery('id');
$password = (string)$this->getRequest()->getPost('password');
$passwordConfirmation = (string)$this->getRequest()->getPost('password_confirmation');
if ($password !== $passwordConfirmation) {
$this->messageManager->addError(__("New Password and Confirm New Password values didn't match."));
- $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]);
+ $resultRedirect->setPath(
+ '*/*/createPassword',
+ ['token' => $resetPasswordToken]
+ );
return $resultRedirect;
}
if (iconv_strlen($password) <= 0) {
$this->messageManager->addError(__('Please enter a new password.'));
- $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]);
+ $resultRedirect->setPath(
+ '*/*/createPassword',
+ ['token' => $resetPasswordToken]
+ );
return $resultRedirect;
}
try {
- $customerEmail = $this->customerRepository->getById($customerId)->getEmail();
- $this->credentialsValidator->checkPasswordDifferentFromEmail($customerEmail, $password);
- $this->accountManagement->resetPassword($customerEmail, $resetPasswordToken, $password);
+ $this->accountManagement->resetPassword(
+ '',
+ $resetPasswordToken,
+ $password
+ );
$this->session->unsRpToken();
- $this->session->unsRpCustomerId();
$this->messageManager->addSuccess(__('You updated your password.'));
$resultRedirect->setPath('*/*/login');
return $resultRedirect;
@@ -102,7 +102,11 @@ public function execute()
} catch (\Exception $exception) {
$this->messageManager->addError(__('Something went wrong while saving the new password.'));
}
- $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]);
+
+ $resultRedirect->setPath(
+ '*/*/createPassword',
+ ['token' => $resetPasswordToken]
+ );
return $resultRedirect;
}
}
diff --git a/app/code/Magento/Customer/Controller/Address/FormPost.php b/app/code/Magento/Customer/Controller/Address/FormPost.php
index 21334f51b1752..3d995fef4c5f7 100644
--- a/app/code/Magento/Customer/Controller/Address/FormPost.php
+++ b/app/code/Magento/Customer/Controller/Address/FormPost.php
@@ -197,17 +197,17 @@ public function execute()
try {
$address = $this->_extractAddress();
$this->_addressRepository->save($address);
- $this->messageManager->addSuccess(__('You saved the address.'));
+ $this->messageManager->addSuccessMessage(__('You saved the address.'));
$url = $this->_buildUrl('*/*/index', ['_secure' => true]);
return $this->resultRedirectFactory->create()->setUrl($this->_redirect->success($url));
} catch (InputException $e) {
- $this->messageManager->addError($e->getMessage());
+ $this->messageManager->addErrorMessage($e->getMessage());
foreach ($e->getErrors() as $error) {
- $this->messageManager->addError($error->getMessage());
+ $this->messageManager->addErrorMessage($error->getMessage());
}
} catch (\Exception $e) {
$redirectUrl = $this->_buildUrl('*/*/index');
- $this->messageManager->addException($e, __('We can\'t save the address.'));
+ $this->messageManager->addExceptionMessage($e, __('We can\'t save the address.'));
}
$url = $redirectUrl;
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php
index ebab2a42a02ec..6b80cd5b3a6a5 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/AbstractMassAction.php
@@ -10,6 +10,7 @@
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Backend\App\Action\Context;
+use Magento\Framework\Exception\NotFoundException;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory;
@@ -60,6 +61,10 @@ public function __construct(Context $context, Filter $filter, CollectionFactory
*/
public function execute()
{
+ if (!$this->getRequest()->isPost()) {
+ throw new NotFoundException(__('Page not found'));
+ }
+
try {
$collection = $this->filter->getCollection($this->collectionFactory->create());
return $this->massAction($collection);
@@ -73,7 +78,7 @@ public function execute()
/**
* Return component referer url
- * TODO: Technical dept referer url should be implement as a part of Action configuration in in appropriate way
+ * TODO: Technical dept referer url should be implement as a part of Action configuration in appropriate way
*
* @return null|string
*/
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php
index 2d0ee3ae13da4..6753a48d02d6a 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/InlineEdit.php
@@ -6,13 +6,15 @@
namespace Magento\Customer\Controller\Adminhtml\Index;
use Magento\Backend\App\Action;
+use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Model\EmailNotificationInterface;
-use Magento\Customer\Test\Block\Form\Login;
use Magento\Customer\Ui\Component\Listing\AttributeRepository;
-use Magento\Customer\Api\Data\CustomerInterface;
-use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Framework\Message\MessageInterface;
/**
+ * Customer inline edit action
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class InlineEdit extends \Magento\Backend\App\Action
@@ -101,7 +103,11 @@ private function getEmailNotification()
}
/**
+ * Inline edit action execute
+ *
* @return \Magento\Framework\Controller\Result\Json
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function execute()
{
@@ -249,7 +255,7 @@ protected function processAddressData(array $data)
protected function getErrorMessages()
{
$messages = [];
- foreach ($this->getMessageManager()->getMessages()->getItems() as $error) {
+ foreach ($this->getMessageManager()->getMessages()->getErrors() as $error) {
$messages[] = $error->getText();
}
return $messages;
@@ -262,7 +268,7 @@ protected function getErrorMessages()
*/
protected function isErrorExists()
{
- return (bool)$this->getMessageManager()->getMessages(true)->getCount();
+ return (bool)$this->getMessageManager()->getMessages(true)->getCountByType(MessageInterface::TYPE_ERROR);
}
/**
diff --git a/app/code/Magento/Customer/Controller/Section/Load.php b/app/code/Magento/Customer/Controller/Section/Load.php
index 7a2345c91750c..e37461d20f5de 100644
--- a/app/code/Magento/Customer/Controller/Section/Load.php
+++ b/app/code/Magento/Customer/Controller/Section/Load.php
@@ -70,11 +70,11 @@ public function execute()
$sectionNames = $this->getRequest()->getParam('sections');
$sectionNames = $sectionNames ? array_unique(\explode(',', $sectionNames)) : null;
- $updateSectionId = $this->getRequest()->getParam('update_section_id');
- if ('false' === $updateSectionId) {
- $updateSectionId = false;
+ $forceNewSectionTimestamp = $this->getRequest()->getParam('force_new_section_timestamp');
+ if ('false' === $forceNewSectionTimestamp) {
+ $forceNewSectionTimestamp = false;
}
- $response = $this->sectionPool->getSectionsData($sectionNames, (bool)$updateSectionId);
+ $response = $this->sectionPool->getSectionsData($sectionNames, (bool)$forceNewSectionTimestamp);
} catch (\Exception $e) {
$resultJson->setStatusHeader(
\Zend\Http\Response::STATUS_CODE_400,
diff --git a/app/code/Magento/Customer/CustomerData/Section/Identifier.php b/app/code/Magento/Customer/CustomerData/Section/Identifier.php
index 2a770925d1c37..54d7cee2d90bd 100644
--- a/app/code/Magento/Customer/CustomerData/Section/Identifier.php
+++ b/app/code/Magento/Customer/CustomerData/Section/Identifier.php
@@ -43,12 +43,12 @@ public function __construct(
/**
* Init mark(identifier) for sections
*
- * @param bool $forceUpdate
+ * @param bool $forceNewTimestamp
* @return int
*/
- public function initMark($forceUpdate)
+ public function initMark($forceNewTimestamp)
{
- if ($forceUpdate) {
+ if ($forceNewTimestamp) {
$this->markId = time();
return $this->markId;
}
@@ -68,18 +68,18 @@ public function initMark($forceUpdate)
*
* @param array $sectionsData
* @param null $sectionNames
- * @param bool $updateIds
+ * @param bool $forceNewTimestamp
* @return array
*/
- public function markSections(array $sectionsData, $sectionNames = null, $updateIds = false)
+ public function markSections(array $sectionsData, $sectionNames = null, $forceNewTimestamp = false)
{
if (!$sectionNames) {
$sectionNames = array_keys($sectionsData);
}
- $markId = $this->initMark($updateIds);
+ $markId = $this->initMark($forceNewTimestamp);
foreach ($sectionNames as $name) {
- if ($updateIds || !array_key_exists(self::SECTION_KEY, $sectionsData[$name])) {
+ if ($forceNewTimestamp || !array_key_exists(self::SECTION_KEY, $sectionsData[$name])) {
$sectionsData[$name][self::SECTION_KEY] = $markId;
}
}
diff --git a/app/code/Magento/Customer/CustomerData/SectionPool.php b/app/code/Magento/Customer/CustomerData/SectionPool.php
index 26e9140c63df5..be5ea09c0db33 100644
--- a/app/code/Magento/Customer/CustomerData/SectionPool.php
+++ b/app/code/Magento/Customer/CustomerData/SectionPool.php
@@ -55,10 +55,10 @@ public function __construct(
/**
* {@inheritdoc}
*/
- public function getSectionsData(array $sectionNames = null, $updateIds = false)
+ public function getSectionsData(array $sectionNames = null, $forceNewTimestamp = false)
{
$sectionsData = $sectionNames ? $this->getSectionDataByNames($sectionNames) : $this->getAllSectionData();
- $sectionsData = $this->identifier->markSections($sectionsData, $sectionNames, $updateIds);
+ $sectionsData = $this->identifier->markSections($sectionsData, $sectionNames, $forceNewTimestamp);
return $sectionsData;
}
diff --git a/app/code/Magento/Customer/CustomerData/SectionPoolInterface.php b/app/code/Magento/Customer/CustomerData/SectionPoolInterface.php
index c308804fd0f8d..ad73b9722b133 100644
--- a/app/code/Magento/Customer/CustomerData/SectionPoolInterface.php
+++ b/app/code/Magento/Customer/CustomerData/SectionPoolInterface.php
@@ -14,8 +14,8 @@ interface SectionPoolInterface
* Get section data by section names. If $sectionNames is null then return all sections data
*
* @param array $sectionNames
- * @param bool $updateIds
+ * @param bool $forceNewTimestamp
* @return array
*/
- public function getSectionsData(array $sectionNames = null, $updateIds = false);
+ public function getSectionsData(array $sectionNames = null, $forceNewTimestamp = false);
}
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index 81e299c9591fb..8f2565189ef4c 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -19,6 +19,7 @@
use Magento\Customer\Model\Metadata\Validator;
use Magento\Eav\Model\Validator\Attribute\Backend;
use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\App\Area;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
@@ -40,6 +41,7 @@
use Magento\Framework\Intl\DateTimeFactory;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Math\Random;
+use Magento\Framework\Phrase;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Framework\Registry;
use Magento\Framework\Stdlib\DateTime;
@@ -325,6 +327,11 @@ class AccountManagement implements AccountManagementInterface
*/
private $accountConfirmation;
+ /**
+ * @var SearchCriteriaBuilder
+ */
+ private $searchCriteriaBuilder;
+
/**
* @param CustomerFactory $customerFactory
* @param ManagerInterface $eventManager
@@ -356,6 +363,7 @@ class AccountManagement implements AccountManagementInterface
* @param SessionManagerInterface|null $sessionManager
* @param SaveHandlerInterface|null $saveHandler
* @param CollectionFactory|null $visitorCollectionFactory
+ * @param SearchCriteriaBuilder|null $searchCriteriaBuilder
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -387,7 +395,8 @@ public function __construct(
AccountConfirmation $accountConfirmation = null,
SessionManagerInterface $sessionManager = null,
SaveHandlerInterface $saveHandler = null,
- CollectionFactory $visitorCollectionFactory = null
+ CollectionFactory $visitorCollectionFactory = null,
+ SearchCriteriaBuilder $searchCriteriaBuilder = null
) {
$this->customerFactory = $customerFactory;
$this->eventManager = $eventManager;
@@ -423,6 +432,8 @@ public function __construct(
?: ObjectManager::getInstance()->get(SaveHandlerInterface::class);
$this->visitorCollectionFactory = $visitorCollectionFactory
?: ObjectManager::getInstance()->get(CollectionFactory::class);
+ $this->searchCriteriaBuilder = $searchCriteriaBuilder
+ ?: ObjectManager::getInstance()->get(SearchCriteriaBuilder::class);
}
/**
@@ -596,14 +607,62 @@ public function initiatePasswordReset($email, $template, $websiteId = null)
return false;
}
+ /**
+ * Match a customer by their RP token.
+ *
+ * @param string $rpToken
+ * @throws ExpiredException
+ * @throws NoSuchEntityException
+ *
+ * @return CustomerInterface
+ */
+ private function matchCustomerByRpToken(string $rpToken): CustomerInterface
+ {
+
+ $this->searchCriteriaBuilder->addFilter(
+ 'rp_token',
+ $rpToken
+ );
+ $this->searchCriteriaBuilder->setPageSize(1);
+ $found = $this->customerRepository->getList(
+ $this->searchCriteriaBuilder->create()
+ );
+
+ if ($found->getTotalCount() > 1) {
+ //Failed to generated unique RP token
+ throw new ExpiredException(
+ new Phrase('Reset password token expired.')
+ );
+ }
+ if ($found->getTotalCount() === 0) {
+ //Customer with such token not found.
+ throw NoSuchEntityException::singleField(
+ 'rp_token',
+ $rpToken
+ );
+ }
+
+ //Unique customer found.
+ return $found->getItems()[0];
+ }
+
/**
* {@inheritdoc}
*/
public function resetPassword($email, $resetToken, $newPassword)
{
- $customer = $this->customerRepository->get($email);
+ if (!$email) {
+ $customer = $this->matchCustomerByRpToken($resetToken);
+ $email = $customer->getEmail();
+ } else {
+ $customer = $this->customerRepository->get($email);
+ }
//Validate Token and new password strength
$this->validateResetPasswordToken($customer->getId(), $resetToken);
+ $this->credentialsValidator->checkPasswordDifferentFromEmail(
+ $email,
+ $newPassword
+ );
$this->checkPasswordStrength($newPassword);
//Update secure data
$customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
@@ -1012,12 +1071,9 @@ public function isCustomerInStore($customerWebsiteId, $storeId)
private function validateResetPasswordToken($customerId, $resetPasswordLinkToken)
{
if (empty($customerId) || $customerId < 0) {
- throw new InputException(
- __(
- 'Invalid value of "%value" provided for the %fieldName field.',
- ['value' => $customerId, 'fieldName' => 'customerId']
- )
- );
+ //Looking for the customer.
+ $customerId = $this->matchCustomerByRpToken($resetPasswordLinkToken)
+ ->getId();
}
if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) {
$params = ['fieldName' => 'resetPasswordLinkToken'];
@@ -1430,9 +1486,7 @@ private function destroyCustomerSessions($customerId)
/** @var \Magento\Customer\Model\Visitor $visitor */
foreach ($visitorCollection->getItems() as $visitor) {
$sessionId = $visitor->getSessionId();
- $this->sessionManager->start();
$this->saveHandler->destroy($sessionId);
- $this->sessionManager->writeClose();
}
}
}
diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
index d9419bc0b8329..db3436c441ec2 100644
--- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php
+++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
@@ -648,7 +648,7 @@ public function validate()
//If country actually has regions and requires you to
//select one then it must be selected.
$errors[] = __('%fieldName is a required field.', ['fieldName' => 'regionId']);
- } elseif ($regionId && !in_array($regionId, $allowedRegions, true)) {
+ } elseif ($allowedRegions && $regionId && !in_array($regionId, $allowedRegions, true)) {
//If a region is selected then checking if it exists.
$errors[] = __(
'Invalid value of "%value" provided for the %fieldName field.',
diff --git a/app/code/Magento/Customer/Model/GroupManagement.php b/app/code/Magento/Customer/Model/GroupManagement.php
index 47d7d7ad1ac41..eb5d90f2fd7ea 100644
--- a/app/code/Magento/Customer/Model/GroupManagement.php
+++ b/app/code/Magento/Customer/Model/GroupManagement.php
@@ -8,16 +8,20 @@
namespace Magento\Customer\Model;
use Magento\Customer\Api\Data\GroupInterface;
+use Magento\Customer\Api\Data\GroupInterfaceFactory;
+use Magento\Customer\Api\GroupRepositoryInterface;
+use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\Collection;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Model\StoreManagerInterface;
-use Magento\Customer\Api\GroupRepositoryInterface;
-use Magento\Customer\Api\Data\GroupInterfaceFactory;
-use Magento\Customer\Model\GroupFactory;
/**
+ * The class contains methods for getting information about a customer group
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class GroupManagement implements \Magento\Customer\Api\GroupManagementInterface
@@ -65,6 +69,11 @@ class GroupManagement implements \Magento\Customer\Api\GroupManagementInterface
*/
protected $filterBuilder;
+ /**
+ * @var SortOrderBuilder
+ */
+ private $sortOrderBuilder;
+
/**
* @param StoreManagerInterface $storeManager
* @param ScopeConfigInterface $scopeConfig
@@ -73,6 +82,7 @@ class GroupManagement implements \Magento\Customer\Api\GroupManagementInterface
* @param GroupInterfaceFactory $groupDataFactory
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param FilterBuilder $filterBuilder
+ * @param SortOrderBuilder $sortOrderBuilder
*/
public function __construct(
StoreManagerInterface $storeManager,
@@ -81,7 +91,8 @@ public function __construct(
GroupRepositoryInterface $groupRepository,
GroupInterfaceFactory $groupDataFactory,
SearchCriteriaBuilder $searchCriteriaBuilder,
- FilterBuilder $filterBuilder
+ FilterBuilder $filterBuilder,
+ SortOrderBuilder $sortOrderBuilder = null
) {
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
@@ -90,10 +101,12 @@ public function __construct(
$this->groupDataFactory = $groupDataFactory;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->filterBuilder = $filterBuilder;
+ $this->sortOrderBuilder = $sortOrderBuilder ?: ObjectManager::getInstance()
+ ->get(SortOrderBuilder::class);
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function isReadonly($groupId)
{
@@ -107,7 +120,7 @@ public function isReadonly($groupId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getDefaultGroup($storeId = null)
{
@@ -133,7 +146,7 @@ public function getDefaultGroup($storeId = null)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getNotLoggedInGroup()
{
@@ -141,7 +154,7 @@ public function getNotLoggedInGroup()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getLoggedInGroups()
{
@@ -155,15 +168,20 @@ public function getLoggedInGroups()
->setConditionType('neq')
->setValue(self::CUST_GROUP_ALL)
->create();
+ $groupNameSortOrder = $this->sortOrderBuilder
+ ->setField('customer_group_code')
+ ->setDirection(Collection::SORT_ORDER_ASC)
+ ->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilters($notLoggedInFilter)
->addFilters($groupAll)
+ ->addSortOrder($groupNameSortOrder)
->create();
return $this->groupRepository->getList($searchCriteria)->getItems();
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getAllCustomersGroup()
{
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Date.php b/app/code/Magento/Customer/Model/Metadata/Form/Date.php
index b27f6627439e4..6f14b2e6f1dad 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/Date.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/Date.php
@@ -12,7 +12,7 @@
class Date extends AbstractData
{
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function extractValue(\Magento\Framework\App\RequestInterface $request)
{
@@ -21,7 +21,7 @@ public function extractValue(\Magento\Framework\App\RequestInterface $request)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
@@ -95,21 +95,15 @@ public function validateValue($value)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function compactValue($value)
{
- if ($value !== false) {
- if (empty($value)) {
- $value = null;
- }
- return $value;
- }
- return false;
+ return $value;
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function restoreValue($value)
{
@@ -117,7 +111,7 @@ public function restoreValue($value)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function outputValue($format = \Magento\Customer\Model\Metadata\ElementFactory::OUTPUT_FORMAT_TEXT)
{
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Text.php b/app/code/Magento/Customer/Model/Metadata/Form/Text.php
index 9ef6df0a6d36e..ecbe1976f1cfa 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/Text.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/Text.php
@@ -5,8 +5,10 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Customer\Model\Metadata\Form;
+use Magento\Customer\Api\Data\AttributeMetadataInterface;
use Magento\Framework\Api\ArrayObjectSearch;
class Text extends AbstractData
@@ -19,7 +21,7 @@ class Text extends AbstractData
/**
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Psr\Log\LoggerInterface $logger
- * @param \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute
+ * @param AttributeMetadataInterface $attribute
* @param \Magento\Framework\Locale\ResolverInterface $localeResolver
* @param string $value
* @param string $entityTypeCode
@@ -29,7 +31,7 @@ class Text extends AbstractData
public function __construct(
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Psr\Log\LoggerInterface $logger,
- \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute,
+ AttributeMetadataInterface $attribute,
\Magento\Framework\Locale\ResolverInterface $localeResolver,
$value,
$entityTypeCode,
@@ -72,26 +74,7 @@ public function validateValue($value)
return true;
}
- // validate length
- $length = $this->_string->strlen(trim($value));
-
- $validateRules = $attribute->getValidationRules();
-
- $minTextLength = ArrayObjectSearch::getArrayElementByName(
- $validateRules,
- 'min_text_length'
- );
- if ($minTextLength !== null && $length < $minTextLength) {
- $errors[] = __('"%1" length must be equal or greater than %2 characters.', $label, $minTextLength);
- }
-
- $maxTextLength = ArrayObjectSearch::getArrayElementByName(
- $validateRules,
- 'max_text_length'
- );
- if ($maxTextLength !== null && $length > $maxTextLength) {
- $errors[] = __('"%1" length must be equal or less than %2 characters.', $label, $maxTextLength);
- }
+ $errors = $this->validateLength($value, $attribute, $errors);
$result = $this->_validateInputRule($value);
if ($result !== true) {
@@ -127,4 +110,42 @@ public function outputValue($format = \Magento\Customer\Model\Metadata\ElementFa
{
return $this->_applyOutputFilter($this->_value);
}
+
+ /**
+ * Length validation
+ *
+ * @param mixed $value
+ * @param AttributeMetadataInterface $attribute
+ * @param array $errors
+ * @return array
+ */
+ protected function validateLength($value, AttributeMetadataInterface $attribute, array $errors): array
+ {
+ // validate length
+ $label = __($attribute->getStoreLabel());
+
+ $length = $this->_string->strlen(trim($value));
+
+ $validateRules = $attribute->getValidationRules();
+
+ if (!empty(ArrayObjectSearch::getArrayElementByName($validateRules, 'input_validation'))) {
+ $minTextLength = ArrayObjectSearch::getArrayElementByName(
+ $validateRules,
+ 'min_text_length'
+ );
+ if ($minTextLength !== null && $length < $minTextLength) {
+ $errors[] = __('"%1" length must be equal or greater than %2 characters.', $label, $minTextLength);
+ }
+
+ $maxTextLength = ArrayObjectSearch::getArrayElementByName(
+ $validateRules,
+ 'max_text_length'
+ );
+ if ($maxTextLength !== null && $length > $maxTextLength) {
+ $errors[] = __('"%1" length must be equal or less than %2 characters.', $label, $maxTextLength);
+ }
+ }
+
+ return $errors;
+ }
}
diff --git a/app/code/Magento/Customer/Model/Renderer/Region.php b/app/code/Magento/Customer/Model/Renderer/Region.php
index 5c7fcd38d6c52..ad620e4e4b3f2 100644
--- a/app/code/Magento/Customer/Model/Renderer/Region.php
+++ b/app/code/Magento/Customer/Model/Renderer/Region.php
@@ -80,7 +80,7 @@ public function render(AbstractElement $element)
$regionCollection = self::$_regionCollections[$countryId];
}
- $regionId = intval($element->getForm()->getElement('region_id')->getValue());
+ $regionId = (int)$element->getForm()->getElement('region_id')->getValue();
$htmlAttributes = $element->getHtmlAttributes();
foreach ($htmlAttributes as $key => $attribute) {
diff --git a/app/code/Magento/Customer/Model/Vat.php b/app/code/Magento/Customer/Model/Vat.php
index 9822e2ad1b80e..f608a6cf4c11c 100644
--- a/app/code/Magento/Customer/Model/Vat.php
+++ b/app/code/Magento/Customer/Model/Vat.php
@@ -184,10 +184,15 @@ public function checkVatNumber($countryCode, $vatNumber, $requesterCountryCode =
$requestParams = [];
$requestParams['countryCode'] = $countryCode;
- $requestParams['vatNumber'] = str_replace([' ', '-'], ['', ''], $vatNumber);
+ $vatNumberSanitized = $this->isCountryInEU($countryCode)
+ ? str_replace([' ', '-', $countryCode], ['', '', ''], $vatNumber)
+ : str_replace([' ', '-'], ['', ''], $vatNumber);
+ $requestParams['vatNumber'] = $vatNumberSanitized;
$requestParams['requesterCountryCode'] = $requesterCountryCode;
- $requestParams['requesterVatNumber'] = str_replace([' ', '-'], ['', ''], $requesterVatNumber);
-
+ $reqVatNumSanitized = $this->isCountryInEU($requesterCountryCode)
+ ? str_replace([' ', '-', $requesterCountryCode], ['', '', ''], $requesterVatNumber)
+ : str_replace([' ', '-'], ['', ''], $requesterVatNumber);
+ $requestParams['requesterVatNumber'] = $reqVatNumSanitized;
// Send request to service
$result = $soapClient->checkVatApprox($requestParams);
diff --git a/app/code/Magento/Customer/Model/Visitor.php b/app/code/Magento/Customer/Model/Visitor.php
index a0530389f902a..d144b7f6b70ec 100644
--- a/app/code/Magento/Customer/Model/Visitor.php
+++ b/app/code/Magento/Customer/Model/Visitor.php
@@ -320,11 +320,9 @@ public function clean()
*/
public function getOnlineInterval()
{
- $configValue = intval(
- $this->scopeConfig->getValue(
- static::XML_PATH_ONLINE_INTERVAL,
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- )
+ $configValue = (int)$this->scopeConfig->getValue(
+ static::XML_PATH_ONLINE_INTERVAL,
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
return $configValue ?: static::DEFAULT_ONLINE_MINUTES_INTERVAL;
}
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/CustomerActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/CustomerActionGroup.xml
index 3f816425a81f7..6a253a6053076 100644
--- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/CustomerActionGroup.xml
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/CustomerActionGroup.xml
@@ -17,6 +17,10 @@
-
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/RemoveCustomerFromAdminActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/RemoveCustomerFromAdminActionGroup.xml
new file mode 100644
index 0000000000000..a53968a920806
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/RemoveCustomerFromAdminActionGroup.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml
new file mode 100644
index 0000000000000..a8ee604edee0a
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
index fc7c5b3005488..e4420f189900e 100644
--- a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml
@@ -13,7 +13,7 @@
12
CustomerRegionOne
0
-
USA
+
US
- 7700 W Parmer Ln
- Bld D
@@ -49,4 +49,44 @@
Yes
RegionTX
+
+
+ GB
+
+
+ John
+ Doe
+ qa
+ 13456768768
+ 987654321
+
+ - Main st1
+ - ap.66
+
+ Culver City
+ California
+ 90230
+ US
+ Yes
+ Yes
+ RegionCA
+
+
+ John
+ Doe
+ qa
+ 13456768768
+ 987654321
+
+ - Main st1
+ - ap.66
+
+ New York
+ New York
+ 11001
+ US
+ Yes
+ Yes
+ RegionNY
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml
index 6627277e911c1..74da84c01b861 100644
--- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml
@@ -48,4 +48,30 @@
Jane
+
+ 1
+ true
+ true
+ John.Doe@example.com
+ John
+ Doe
+ John Doe
+ pwdTest123!
+ 0
+ 0
+ US_Address_CA
+
+
+ 1
+ true
+ true
+ John.Doe@example.com
+ John
+ Doe
+ John Doe
+ pwdTest123!
+ 0
+ 0
+ US_Address_NY
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Data/RegionData.xml b/app/code/Magento/Customer/Test/Mftf/Data/RegionData.xml
index 630d060a29bd6..9f31e5994eaae 100644
--- a/app/code/Magento/Customer/Test/Mftf/Data/RegionData.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Data/RegionData.xml
@@ -15,6 +15,16 @@
Texas
TX
- 1
+ 57
+
+
+ California
+ CA
+ 12
+
+
+ New York
+ NY
+ 43
diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml
index 941e247e18b8c..788a23fb539c5 100644
--- a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDashboardPage.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/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Page/TemplatePageFile.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml
similarity index 76%
rename from dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Page/TemplatePageFile.xml
rename to app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml
index 3c4d85019fe54..4e89e5476c3bc 100644
--- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Page/TemplatePageFile.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml
@@ -8,7 +8,5 @@
-
-
-
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml
new file mode 100644
index 0000000000000..7eef792f0f048
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml
index 7d106a35f0e13..5414b449ca470 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerFiltersSection.xml
@@ -13,5 +13,6 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerGridSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerGridSection.xml
index ba2c17051567b..73a53d334db5f 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerGridSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerGridSection.xml
@@ -5,11 +5,15 @@
* See COPYING.txt for license details.
*/
-->
-
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminNewCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminNewCustomerAccountInformationSection.xml
index 6246891423129..868ffd8e034db 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/AdminNewCustomerAccountInformationSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminNewCustomerAccountInformationSection.xml
@@ -13,5 +13,6 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
index c39dfef5f74e7..7957fa0350fa5 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
@@ -9,6 +9,7 @@
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
index 52aa077fff8db..01b758c9c3e3b 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
@@ -13,5 +13,6 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml
new file mode 100644
index 0000000000000..7482193031091
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AddingProductWithExpiredSessionTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AddingProductWithExpiredSessionTest.xml
new file mode 100644
index 0000000000000..7951c91aab61a
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Mftf/Test/AddingProductWithExpiredSessionTest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml
index 87361539c691e..e5dc187e8ab7a 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="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd">
@@ -18,16 +18,14 @@
-
-
+
-
-
-
+
+
diff --git a/app/code/Magento/Customer/Test/Mftf/composer.json b/app/code/Magento/Customer/Test/Mftf/composer.json
deleted file mode 100644
index 4290fbad458c6..0000000000000
--- a/app/code/Magento/Customer/Test/Mftf/composer.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "name": "magento/functional-test-module-customer",
- "description": "N/A",
- "config": {
- "sort-packages": true
- },
- "require": {
- "php": "~7.0.13|~7.1.0",
- "magento/functional-test-module-store": "100.0.0-dev",
- "magento/functional-test-module-eav": "100.0.0-dev",
- "magento/functional-test-module-directory": "100.0.0-dev",
- "magento/functional-test-module-catalog": "100.0.0-dev",
- "magento/functional-test-module-newsletter": "100.0.0-dev",
- "magento/functional-test-module-sales": "100.0.0-dev",
- "magento/functional-test-module-checkout": "100.0.0-dev",
- "magento/functional-test-module-wishlist": "100.0.0-dev",
- "magento/functional-test-module-theme": "100.0.0-dev",
- "magento/functional-test-module-backend": "100.0.0-dev",
- "magento/functional-test-module-review": "100.0.0-dev",
- "magento/functional-test-module-tax": "100.0.0-dev",
- "magento/functional-test-module-page-cache": "100.0.0-dev",
- "magento/magento2-functional-testing-framework": "2.2.0",
- "magento/functional-test-module-authorization": "100.0.0-dev",
- "magento/functional-test-module-integration": "100.0.0-dev",
- "magento/functional-test-module-media-storage": "100.0.0-dev",
- "magento/functional-test-module-ui": "100.0.0-dev",
- "magento/functional-test-module-config": "100.0.0-dev",
- "magento/functional-test-module-quote": "100.0.0-dev"
- },
- "suggest": {
- "magento/functional-test-module-cookie": "100.0.0-dev",
- "magento/functional-test-module-customer-sample-data": "100.0.0-dev"
- },
- "type": "magento2-test",
- "license": [
- "OSL-3.0",
- "AFL-3.0"
- ]
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php
deleted file mode 100644
index 77f41024ba02f..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php
+++ /dev/null
@@ -1,233 +0,0 @@
-sessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
- ->disableOriginalConstructor()
- ->setMethods(['setRpToken', 'setRpCustomerId', 'getRpToken', 'getRpCustomerId'])
- ->getMock();
- $this->pageFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Result\PageFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->accountManagementMock = $this->getMockBuilder(\Magento\Customer\Api\AccountManagementInterface::class)
- ->getMockForAbstractClass();
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
- ->getMockForAbstractClass();
- $this->redirectFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\RedirectFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
- ->getMockForAbstractClass();
-
- $this->objectManagerHelper = new ObjectManagerHelper($this);
- $this->model = $this->objectManagerHelper->getObject(
- \Magento\Customer\Controller\Account\CreatePassword::class,
- [
- 'customerSession' => $this->sessionMock,
- 'resultPageFactory' => $this->pageFactoryMock,
- 'accountManagement' => $this->accountManagementMock,
- 'request' => $this->requestMock,
- 'resultRedirectFactory' => $this->redirectFactoryMock,
- 'messageManager' => $this->messageManagerMock,
- ]
- );
- }
-
- public function testExecuteWithLink()
- {
- $token = 'token';
- $customerId = '11';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getParam')
- ->willReturnMap(
- [
- ['token', null, $token],
- ['id', null, $customerId],
- ]
- );
-
- $this->accountManagementMock->expects($this->once())
- ->method('validateResetPasswordLinkToken')
- ->with($customerId, $token)
- ->willReturn(true);
-
- $this->sessionMock->expects($this->once())
- ->method('setRpToken')
- ->with($token);
- $this->sessionMock->expects($this->once())
- ->method('setRpCustomerId')
- ->with($customerId);
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/createpassword', [])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-
- public function testExecuteWithSession()
- {
- $token = 'token';
- $customerId = '11';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getParam')
- ->willReturnMap(
- [
- ['token', null, null],
- ['id', null, $customerId],
- ]
- );
-
- $this->sessionMock->expects($this->once())
- ->method('getRpToken')
- ->willReturn($token);
- $this->sessionMock->expects($this->once())
- ->method('getRpCustomerId')
- ->willReturn($customerId);
-
- $this->accountManagementMock->expects($this->once())
- ->method('validateResetPasswordLinkToken')
- ->with($customerId, $token)
- ->willReturn(true);
-
- /** @var \Magento\Framework\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject $pageMock */
- $pageMock = $this->getMockBuilder(\Magento\Framework\View\Result\Page::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->pageFactoryMock->expects($this->once())
- ->method('create')
- ->with(false, [])
- ->willReturn($pageMock);
-
- /** @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject $layoutMock */
- $layoutMock = $this->getMockBuilder(\Magento\Framework\View\Layout::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $pageMock->expects($this->once())
- ->method('getLayout')
- ->willReturn($layoutMock);
-
- /** @var \Magento\Customer\Block\Account\Resetpassword|\PHPUnit_Framework_MockObject_MockObject $layoutMock */
- $blockMock = $this->getMockBuilder(\Magento\Customer\Block\Account\Resetpassword::class)
- ->disableOriginalConstructor()
- ->setMethods(['setCustomerId', 'setResetPasswordLinkToken'])
- ->getMock();
-
- $layoutMock->expects($this->once())
- ->method('getBlock')
- ->with('resetPassword')
- ->willReturn($blockMock);
-
- $blockMock->expects($this->once())
- ->method('setCustomerId')
- ->with($customerId)
- ->willReturnSelf();
- $blockMock->expects($this->once())
- ->method('setResetPasswordLinkToken')
- ->with($token)
- ->willReturnSelf();
-
- $this->assertEquals($pageMock, $this->model->execute());
- }
-
- public function testExecuteWithException()
- {
- $token = 'token';
- $customerId = '11';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getParam')
- ->willReturnMap(
- [
- ['token', null, $token],
- ['id', null, null],
- ]
- );
-
- $this->sessionMock->expects($this->once())
- ->method('getRpToken')
- ->willReturn($token);
- $this->sessionMock->expects($this->once())
- ->method('getRpCustomerId')
- ->willReturn($customerId);
-
- $this->accountManagementMock->expects($this->once())
- ->method('validateResetPasswordLinkToken')
- ->with($customerId, $token)
- ->willThrowException(new \Exception('Exception.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with(__('Your password reset link has expired.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/forgotpassword', [])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php
deleted file mode 100644
index b79ad008e5e44..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php
+++ /dev/null
@@ -1,379 +0,0 @@
-sessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
- ->disableOriginalConstructor()
- ->setMethods(['unsRpToken', 'unsRpCustomerId'])
- ->getMock();
- $this->pageFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Result\PageFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->accountManagementMock = $this->getMockBuilder(\Magento\Customer\Api\AccountManagementInterface::class)
- ->getMockForAbstractClass();
- $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)
- ->getMockForAbstractClass();
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
- ->setMethods(['getQuery', 'getPost'])
- ->getMockForAbstractClass();
- $this->redirectFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\RedirectFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
- ->getMockForAbstractClass();
-
- $this->objectManagerHelper = new ObjectManagerHelper($this);
- $this->model = $this->objectManagerHelper->getObject(
- \Magento\Customer\Controller\Account\ResetPasswordPost::class,
- [
- 'customerSession' => $this->sessionMock,
- 'resultPageFactory' => $this->pageFactoryMock,
- 'accountManagement' => $this->accountManagementMock,
- 'customerRepository' => $this->customerRepositoryMock,
- 'request' => $this->requestMock,
- 'resultRedirectFactory' => $this->redirectFactoryMock,
- 'messageManager' => $this->messageManagerMock,
- ]
- );
- }
-
- public function testExecute()
- {
- $token = 'token';
- $customerId = '11';
- $password = 'password';
- $passwordConfirmation = 'password';
- $email = 'email@email.com';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getQuery')
- ->willReturnMap(
- [
- ['token', $token],
- ['id', $customerId],
- ]
- );
- $this->requestMock->expects($this->exactly(2))
- ->method('getPost')
- ->willReturnMap(
- [
- ['password', $password],
- ['password_confirmation', $passwordConfirmation],
- ]
- );
-
- /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMockForAbstractClass();
-
- $this->customerRepositoryMock->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customerMock);
-
- $customerMock->expects($this->once())
- ->method('getEmail')
- ->willReturn($email);
-
- $this->accountManagementMock->expects($this->once())
- ->method('resetPassword')
- ->with($email, $token, $password)
- ->willReturn(true);
-
- $this->sessionMock->expects($this->once())
- ->method('unsRpToken');
- $this->sessionMock->expects($this->once())
- ->method('unsRpCustomerId');
-
- $this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
- ->with(__('You updated your password.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/login', [])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-
- public function testExecuteWithException()
- {
- $token = 'token';
- $customerId = '11';
- $password = 'password';
- $passwordConfirmation = 'password';
- $email = 'email@email.com';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getQuery')
- ->willReturnMap(
- [
- ['token', $token],
- ['id', $customerId],
- ]
- );
- $this->requestMock->expects($this->exactly(2))
- ->method('getPost')
- ->willReturnMap(
- [
- ['password', $password],
- ['password_confirmation', $passwordConfirmation],
- ]
- );
-
- /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMockForAbstractClass();
-
- $this->customerRepositoryMock->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customerMock);
-
- $customerMock->expects($this->once())
- ->method('getEmail')
- ->willReturn($email);
-
- $this->accountManagementMock->expects($this->once())
- ->method('resetPassword')
- ->with($email, $token, $password)
- ->willThrowException(new \Exception('Exception.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with(__('Something went wrong while saving the new password.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-
- /**
- * Test for InputException
- */
- public function testExecuteWithInputException()
- {
- $token = 'token';
- $customerId = '11';
- $password = 'password';
- $passwordConfirmation = 'password';
- $email = 'email@email.com';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getQuery')
- ->willReturnMap(
- [
- ['token', $token],
- ['id', $customerId],
- ]
- );
- $this->requestMock->expects($this->exactly(2))
- ->method('getPost')
- ->willReturnMap(
- [
- ['password', $password],
- ['password_confirmation', $passwordConfirmation],
- ]
- );
-
- /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMockForAbstractClass();
-
- $this->customerRepositoryMock->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customerMock);
-
- $customerMock->expects($this->once())
- ->method('getEmail')
- ->willReturn($email);
-
- $this->accountManagementMock->expects($this->once())
- ->method('resetPassword')
- ->with($email, $token, $password)
- ->willThrowException(new \Magento\Framework\Exception\InputException(__('InputException.')));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with(__('InputException.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-
- public function testExecuteWithWrongConfirmation()
- {
- $token = 'token';
- $customerId = '11';
- $password = 'password';
- $passwordConfirmation = 'wrong_password';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getQuery')
- ->willReturnMap(
- [
- ['token', $token],
- ['id', $customerId],
- ]
- );
- $this->requestMock->expects($this->exactly(2))
- ->method('getPost')
- ->willReturnMap(
- [
- ['password', $password],
- ['password_confirmation', $passwordConfirmation],
- ]
- );
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with(__('New Password and Confirm New Password values didn\'t match.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-
- public function testExecuteWithEmptyPassword()
- {
- $token = 'token';
- $customerId = '11';
- $password = '';
- $passwordConfirmation = '';
-
- $this->requestMock->expects($this->exactly(2))
- ->method('getQuery')
- ->willReturnMap(
- [
- ['token', $token],
- ['id', $customerId],
- ]
- );
- $this->requestMock->expects($this->exactly(2))
- ->method('getPost')
- ->willReturnMap(
- [
- ['password', $password],
- ['password_confirmation', $passwordConfirmation],
- ]
- );
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with(__('Please enter a new password.'))
- ->willReturnSelf();
-
- /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */
- $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->redirectFactoryMock->expects($this->once())
- ->method('create')
- ->with([])
- ->willReturn($redirectMock);
-
- $redirectMock->expects($this->once())
- ->method('setPath')
- ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token])
- ->willReturnSelf();
-
- $this->assertEquals($redirectMock, $this->model->execute());
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Address/FormPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Address/FormPostTest.php
index 4ad1b5cbc96bd..a2766d42403ba 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Address/FormPostTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Address/FormPostTest.php
@@ -549,7 +549,7 @@ public function testExecute(
->willReturnSelf();
$this->messageManager->expects($this->once())
- ->method('addSuccess')
+ ->method('addSuccessMessage')
->with(__('You saved the address.'))
->willReturnSelf();
@@ -640,7 +640,7 @@ public function testExecuteInputException()
->willThrowException(new InputException(__('InputException')));
$this->messageManager->expects($this->once())
- ->method('addError')
+ ->method('addErrorMessage')
->with('InputException')
->willReturnSelf();
@@ -703,7 +703,7 @@ public function testExecuteException()
->willThrowException($exception);
$this->messageManager->expects($this->once())
- ->method('addException')
+ ->method('addExceptionMessage')
->with($exception, __('We can\'t save the address.'))
->willReturnSelf();
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php
index 913c41070856e..78d9dd7003522 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/InlineEditTest.php
@@ -6,6 +6,7 @@
namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index;
use Magento\Customer\Model\EmailNotificationInterface;
+use Magento\Framework\Message\MessageInterface;
/**
* @SuppressWarnings(PHPMD.TooManyFields)
@@ -242,10 +243,11 @@ protected function prepareMocksForErrorMessagesProcessing()
->method('getMessages')
->willReturn($this->messageCollection);
$this->messageCollection->expects($this->once())
- ->method('getItems')
+ ->method('getErrors')
->willReturn([$this->message]);
$this->messageCollection->expects($this->once())
- ->method('getCount')
+ ->method('getCountByType')
+ ->with(MessageInterface::TYPE_ERROR)
->willReturn(1);
$this->message->expects($this->once())
->method('getText')
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassAssignGroupTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassAssignGroupTest.php
deleted file mode 100644
index 884aab711d168..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassAssignGroupTest.php
+++ /dev/null
@@ -1,189 +0,0 @@
-contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class);
- $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class);
- $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class);
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
- ->disableOriginalConstructor()->getMock();
- $this->objectManagerMock = $this->createPartialMock(
- \Magento\Framework\ObjectManager\ObjectManager::class,
- ['create']
- );
- $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class);
- $this->customerCollectionMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->customerCollectionFactoryMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock->expects($this->any())
- ->method('create')
- ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
- ->willReturn($redirectMock);
-
- $this->resultRedirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
-
- $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
- $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
- $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
- $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
- $this->contextMock->expects($this->any())
- ->method('getResultRedirectFactory')
- ->willReturn($resultRedirectFactory);
- $this->contextMock->expects($this->any())
- ->method('getResultFactory')
- ->willReturn($resultFactoryMock);
-
- $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class);
- $this->filterMock->expects($this->once())
- ->method('getCollection')
- ->with($this->customerCollectionMock)
- ->willReturnArgument(0);
- $this->customerCollectionFactoryMock->expects($this->once())
- ->method('create')
- ->willReturn($this->customerCollectionMock);
- $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)
- ->getMockForAbstractClass();
- $this->massAction = $objectManagerHelper->getObject(
- \Magento\Customer\Controller\Adminhtml\Index\MassAssignGroup::class,
- [
- 'context' => $this->contextMock,
- 'filter' => $this->filterMock,
- 'collectionFactory' => $this->customerCollectionFactoryMock,
- 'customerRepository' => $this->customerRepositoryMock,
- ]
- );
- }
-
- public function testExecute()
- {
- $customersIds = [10, 11, 12];
- $customerMock = $this->getMockBuilder(
- \Magento\Customer\Api\Data\CustomerInterface::class
- )->getMockForAbstractClass();
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willReturnMap([[10, $customerMock], [11, $customerMock], [12, $customerMock]]);
-
- $this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
- ->with(__('A total of %1 record(s) were updated.', count($customersIds)));
-
- $this->resultRedirectMock->expects($this->any())
- ->method('setPath')
- ->with('customer/*/index')
- ->willReturnSelf();
-
- $this->massAction->execute();
- }
-
- public function testExecuteWithException()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willThrowException(new \Exception('Some message.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with('Some message.');
-
- $this->massAction->execute();
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php
deleted file mode 100644
index 190ff2c06618f..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassDeleteTest.php
+++ /dev/null
@@ -1,187 +0,0 @@
-contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class);
- $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class);
- $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class);
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
- ->disableOriginalConstructor()->getMock();
- $this->objectManagerMock = $this->createPartialMock(
- \Magento\Framework\ObjectManager\ObjectManager::class,
- ['create']
- );
- $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class);
- $this->customerCollectionMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->customerCollectionFactoryMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock->expects($this->any())
- ->method('create')
- ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
- ->willReturn($redirectMock);
-
- $this->resultRedirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
-
- $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
- $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
- $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
- $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
- $this->contextMock->expects($this->any())
- ->method('getResultRedirectFactory')
- ->willReturn($resultRedirectFactory);
- $this->contextMock->expects($this->any())
- ->method('getResultFactory')
- ->willReturn($resultFactoryMock);
-
- $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class);
- $this->filterMock->expects($this->once())
- ->method('getCollection')
- ->with($this->customerCollectionMock)
- ->willReturnArgument(0);
- $this->customerCollectionFactoryMock->expects($this->once())
- ->method('create')
- ->willReturn($this->customerCollectionMock);
- $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)
- ->getMockForAbstractClass();
- $this->massAction = $objectManagerHelper->getObject(
- \Magento\Customer\Controller\Adminhtml\Index\MassDelete::class,
- [
- 'context' => $this->contextMock,
- 'filter' => $this->filterMock,
- 'collectionFactory' => $this->customerCollectionFactoryMock,
- 'customerRepository' => $this->customerRepositoryMock,
- ]
- );
- }
-
- public function testExecute()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('deleteById')
- ->willReturnMap([[10, true], [11, true], [12, true]]);
-
- $this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
- ->with(__('A total of %1 record(s) were deleted.', count($customersIds)));
-
- $this->resultRedirectMock->expects($this->any())
- ->method('setPath')
- ->with('customer/*/index')
- ->willReturnSelf();
-
- $this->massAction->execute();
- }
-
- public function testExecuteWithException()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('deleteById')
- ->willThrowException(new \Exception('Some message.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with('Some message.');
-
- $this->massAction->execute();
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php
deleted file mode 100644
index daf9c64fe7b7b..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassSubscribeTest.php
+++ /dev/null
@@ -1,203 +0,0 @@
-contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class);
- $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class);
- $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class);
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
- ->disableOriginalConstructor()->getMock();
- $this->objectManagerMock = $this->createPartialMock(
- \Magento\Framework\ObjectManager\ObjectManager::class,
- ['create']
- );
- $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class);
- $this->customerCollectionMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->customerCollectionFactoryMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock->expects($this->any())
- ->method('create')
- ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
- ->willReturn($redirectMock);
- $this->subscriberMock = $this->createMock(\Magento\Newsletter\Model\Subscriber::class);
- $subscriberFactoryMock = $this->getMockBuilder(\Magento\Newsletter\Model\SubscriberFactory::class)
- ->setMethods(['create'])
- ->disableOriginalConstructor()
- ->getMock();
- $subscriberFactoryMock->expects($this->any())
- ->method('create')
- ->willReturn($this->subscriberMock);
-
- $this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class);
- $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
-
- $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
- $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
- $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
- $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
- $this->contextMock->expects($this->any())
- ->method('getResultRedirectFactory')
- ->willReturn($resultRedirectFactory);
- $this->contextMock->expects($this->any())
- ->method('getResultFactory')
- ->willReturn($resultFactoryMock);
-
- $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class);
- $this->filterMock->expects($this->once())
- ->method('getCollection')
- ->with($this->customerCollectionMock)
- ->willReturnArgument(0);
- $this->customerCollectionFactoryMock->expects($this->once())
- ->method('create')
- ->willReturn($this->customerCollectionMock);
- $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)
- ->getMockForAbstractClass();
- $this->massAction = $objectManagerHelper->getObject(
- \Magento\Customer\Controller\Adminhtml\Index\MassSubscribe::class,
- [
- 'context' => $this->contextMock,
- 'filter' => $this->filterMock,
- 'collectionFactory' => $this->customerCollectionFactoryMock,
- 'customerRepository' => $this->customerRepositoryMock,
- 'subscriberFactory' => $subscriberFactoryMock,
- ]
- );
- }
-
- public function testExecute()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willReturnMap([[10, true], [11, true], [12, true]]);
-
- $this->subscriberMock->expects($this->any())
- ->method('subscribeCustomerById')
- ->willReturnMap([[10, true], [11, true], [12, true]]);
-
- $this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
- ->with(__('A total of %1 record(s) were updated.', count($customersIds)));
-
- $this->resultRedirectMock->expects($this->any())
- ->method('setPath')
- ->with('customer/*/index')
- ->willReturnSelf();
-
- $this->massAction->execute();
- }
-
- public function testExecuteWithException()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willThrowException(new \Exception('Some message.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with('Some message.');
-
- $this->massAction->execute();
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php
deleted file mode 100644
index 05624661a2de4..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/MassUnsubscribeTest.php
+++ /dev/null
@@ -1,203 +0,0 @@
-contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class);
- $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class);
- $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class);
- $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
- ->disableOriginalConstructor()->getMock();
- $this->objectManagerMock = $this->createPartialMock(
- \Magento\Framework\ObjectManager\ObjectManager::class,
- ['create']
- );
- $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class);
- $this->customerCollectionMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->customerCollectionFactoryMock =
- $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $resultFactoryMock->expects($this->any())
- ->method('create')
- ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
- ->willReturn($redirectMock);
- $this->subscriberMock = $this->createMock(\Magento\Newsletter\Model\Subscriber::class);
- $subscriberFactoryMock = $this->getMockBuilder(\Magento\Newsletter\Model\SubscriberFactory::class)
- ->setMethods(['create'])
- ->disableOriginalConstructor()
- ->getMock();
- $subscriberFactoryMock->expects($this->any())
- ->method('create')
- ->willReturn($this->subscriberMock);
-
- $this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class);
- $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
-
- $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
- $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
- $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
- $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
- $this->contextMock->expects($this->any())
- ->method('getResultRedirectFactory')
- ->willReturn($resultRedirectFactory);
- $this->contextMock->expects($this->any())
- ->method('getResultFactory')
- ->willReturn($resultFactoryMock);
-
- $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class);
- $this->filterMock->expects($this->once())
- ->method('getCollection')
- ->with($this->customerCollectionMock)
- ->willReturnArgument(0);
- $this->customerCollectionFactoryMock->expects($this->once())
- ->method('create')
- ->willReturn($this->customerCollectionMock);
- $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)
- ->getMockForAbstractClass();
- $this->massAction = $objectManagerHelper->getObject(
- \Magento\Customer\Controller\Adminhtml\Index\MassUnsubscribe::class,
- [
- 'context' => $this->contextMock,
- 'filter' => $this->filterMock,
- 'collectionFactory' => $this->customerCollectionFactoryMock,
- 'customerRepository' => $this->customerRepositoryMock,
- 'subscriberFactory' => $subscriberFactoryMock,
- ]
- );
- }
-
- public function testExecute()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willReturnMap([[10, true], [11, true], [12, true]]);
-
- $this->subscriberMock->expects($this->any())
- ->method('unsubscribeCustomerById')
- ->willReturnMap([[10, true], [11, true], [12, true]]);
-
- $this->messageManagerMock->expects($this->once())
- ->method('addSuccess')
- ->with(__('A total of %1 record(s) were updated.', count($customersIds)));
-
- $this->resultRedirectMock->expects($this->any())
- ->method('setPath')
- ->with('customer/*/index')
- ->willReturnSelf();
-
- $this->massAction->execute();
- }
-
- public function testExecuteWithException()
- {
- $customersIds = [10, 11, 12];
-
- $this->customerCollectionMock->expects($this->any())
- ->method('getAllIds')
- ->willReturn($customersIds);
-
- $this->customerRepositoryMock->expects($this->any())
- ->method('getById')
- ->willThrowException(new \Exception('Some message.'));
-
- $this->messageManagerMock->expects($this->once())
- ->method('addError')
- ->with('Some message.');
-
- $this->massAction->execute();
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Section/LoadTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Section/LoadTest.php
index 8fc4df1515b94..04da8e77867d8 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Section/LoadTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Section/LoadTest.php
@@ -81,13 +81,13 @@ protected function setUp()
}
/**
- * @param $sectionNames
- * @param $updateSectionID
- * @param $sectionNamesAsArray
- * @param $updateIds
+ * @param string $sectionNames
+ * @param bool $forceNewSectionTimestamp
+ * @param string[] $sectionNamesAsArray
+ * @param bool $forceNewTimestamp
* @dataProvider executeDataProvider
*/
- public function testExecute($sectionNames, $updateSectionID, $sectionNamesAsArray, $updateIds)
+ public function testExecute($sectionNames, $forceNewSectionTimestamp, $sectionNamesAsArray, $forceNewTimestamp)
{
$this->resultJsonFactoryMock->expects($this->once())
->method('create')
@@ -101,12 +101,12 @@ public function testExecute($sectionNames, $updateSectionID, $sectionNamesAsArra
$this->httpRequestMock->expects($this->exactly(2))
->method('getParam')
- ->withConsecutive(['sections'], ['update_section_id'])
- ->willReturnOnConsecutiveCalls($sectionNames, $updateSectionID);
+ ->withConsecutive(['sections'], ['force_new_section_timestamp'])
+ ->willReturnOnConsecutiveCalls($sectionNames, $forceNewSectionTimestamp);
$this->sectionPoolMock->expects($this->once())
->method('getSectionsData')
- ->with($sectionNamesAsArray, $updateIds)
+ ->with($sectionNamesAsArray, $forceNewTimestamp)
->willReturn([
'message' => 'some message',
'someKey' => 'someValue'
@@ -131,15 +131,15 @@ public function executeDataProvider()
return [
[
'sectionNames' => 'sectionName1,sectionName2,sectionName3',
- 'updateSectionID' => 'updateSectionID',
+ 'forceNewSectionTimestamp' => 'forceNewSectionTimestamp',
'sectionNamesAsArray' => ['sectionName1', 'sectionName2', 'sectionName3'],
- 'updateIds' => true
+ 'forceNewTimestamp' => true
],
[
'sectionNames' => null,
- 'updateSectionID' => null,
+ 'forceNewSectionTimestamp' => null,
'sectionNamesAsArray' => null,
- 'updateIds' => false
+ 'forceNewTimestamp' => false
],
];
}
diff --git a/app/code/Magento/Customer/Test/Unit/CustomerData/SectionPoolTest.php b/app/code/Magento/Customer/Test/Unit/CustomerData/SectionPoolTest.php
index 98fee70e335f7..2b67df1aee292 100644
--- a/app/code/Magento/Customer/Test/Unit/CustomerData/SectionPoolTest.php
+++ b/app/code/Magento/Customer/Test/Unit/CustomerData/SectionPoolTest.php
@@ -63,7 +63,7 @@ public function testGetSectionsDataAllSections()
$this->identifierMock->expects($this->once())
->method('markSections')
- //check also default value for $updateIds = false
+ //check also default value for $forceTimestamp = false
->with($allSectionsData, $sectionNames, false)
->willReturn($identifierResult);
$modelResult = $this->model->getSectionsData($sectionNames);
diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
deleted file mode 100644
index 9d32065c6b64b..0000000000000
--- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
+++ /dev/null
@@ -1,1983 +0,0 @@
-customerFactory = $this->createPartialMock(\Magento\Customer\Model\CustomerFactory::class, ['create']);
- $this->manager = $this->createMock(\Magento\Framework\Event\ManagerInterface::class);
- $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class);
- $this->random = $this->createMock(\Magento\Framework\Math\Random::class);
- $this->validator = $this->createMock(\Magento\Customer\Model\Metadata\Validator::class);
- $this->validationResultsInterfaceFactory = $this->createMock(
- \Magento\Customer\Api\Data\ValidationResultsInterfaceFactory::class
- );
- $this->addressRepository = $this->createMock(\Magento\Customer\Api\AddressRepositoryInterface::class);
- $this->customerMetadata = $this->createMock(\Magento\Customer\Api\CustomerMetadataInterface::class);
- $this->customerRegistry = $this->createMock(\Magento\Customer\Model\CustomerRegistry::class);
- $this->logger = $this->createMock(\Psr\Log\LoggerInterface::class);
- $this->encryptor = $this->getMockBuilder(\Magento\Framework\Encryption\EncryptorInterface::class)
- ->disableOriginalConstructor()
- ->getMockForAbstractClass();
- $this->share = $this->createMock(\Magento\Customer\Model\Config\Share::class);
- $this->string = $this->createMock(\Magento\Framework\Stdlib\StringUtils::class);
- $this->customerRepository = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class);
- $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->transportBuilder = $this->createMock(\Magento\Framework\Mail\Template\TransportBuilder::class);
- $this->dataObjectProcessor = $this->createMock(\Magento\Framework\Reflection\DataObjectProcessor::class);
- $this->registry = $this->createMock(\Magento\Framework\Registry::class);
- $this->customerViewHelper = $this->createMock(\Magento\Customer\Helper\View::class);
- $this->dateTime = $this->createMock(\Magento\Framework\Stdlib\DateTime::class);
- $this->customer = $this->createMock(\Magento\Customer\Model\Customer::class);
- $this->objectFactory = $this->createMock(\Magento\Framework\DataObjectFactory::class);
- $this->extensibleDataObjectConverter = $this->createMock(
- \Magento\Framework\Api\ExtensibleDataObjectConverter::class
- );
- $this->authenticationMock = $this->getMockBuilder(AuthenticationInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->emailNotificationMock = $this->getMockBuilder(EmailNotificationInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->setMethods(['setRpToken', 'addData', 'setRpTokenCreatedAt', 'setData', 'getPasswordHash'])
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->visitorCollectionFactory = $this->getMockBuilder(
- \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class
- )
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $this->sessionManager = $this->getMockBuilder(\Magento\Framework\Session\SessionManagerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->saveHandler = $this->getMockBuilder(\Magento\Framework\Session\SaveHandlerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->dateTimeFactory = $this->createMock(DateTimeFactory::class);
- $this->accountConfirmation = $this->createMock(AccountConfirmation::class);
-
- $this->objectManagerHelper = new ObjectManagerHelper($this);
- $this->accountManagement = $this->objectManagerHelper->getObject(
- \Magento\Customer\Model\AccountManagement::class,
- [
- 'customerFactory' => $this->customerFactory,
- 'eventManager' => $this->manager,
- 'storeManager' => $this->storeManager,
- 'mathRandom' => $this->random,
- 'validator' => $this->validator,
- 'validationResultsDataFactory' => $this->validationResultsInterfaceFactory,
- 'addressRepository' => $this->addressRepository,
- 'customerMetadataService' => $this->customerMetadata,
- 'customerRegistry' => $this->customerRegistry,
- 'logger' => $this->logger,
- 'encryptor' => $this->encryptor,
- 'configShare' => $this->share,
- 'stringHelper' => $this->string,
- 'customerRepository' => $this->customerRepository,
- 'scopeConfig' => $this->scopeConfig,
- 'transportBuilder' => $this->transportBuilder,
- 'dataProcessor' => $this->dataObjectProcessor,
- 'registry' => $this->registry,
- 'customerViewHelper' => $this->customerViewHelper,
- 'dateTime' => $this->dateTime,
- 'customerModel' => $this->customer,
- 'objectFactory' => $this->objectFactory,
- 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter,
- 'dateTimeFactory' => $this->dateTimeFactory,
- 'accountConfirmation' => $this->accountConfirmation,
- 'sessionManager' => $this->sessionManager,
- 'saveHandler' => $this->saveHandler,
- 'visitorCollectionFactory' => $this->visitorCollectionFactory,
- ]
- );
- $reflection = new \ReflectionClass(get_class($this->accountManagement));
- $reflectionProperty = $reflection->getProperty('authentication');
- $reflectionProperty->setAccessible(true);
- $reflectionProperty->setValue($this->accountManagement, $this->authenticationMock);
- $reflectionProperty = $reflection->getProperty('emailNotification');
- $reflectionProperty->setAccessible(true);
- $reflectionProperty->setValue($this->accountManagement, $this->emailNotificationMock);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\InputException
- */
- public function testCreateAccountWithPasswordHashWithExistingCustomer()
- {
- $websiteId = 1;
- $storeId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->once())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->once())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->once())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->once())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share
- ->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager
- ->expects($this->once())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $this->accountManagement->createAccountWithPasswordHash($customer, $hash);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\State\InputMismatchException
- */
- public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->once())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->once())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer
- ->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer
- ->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share
- ->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager
- ->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $exception = new \Magento\Framework\Exception\AlreadyExistsException(
- new \Magento\Framework\Phrase('Exception message')
- );
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customer, $hash)
- ->willThrowException($exception);
-
- $this->accountManagement->createAccountWithPasswordHash($customer, $hash);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- */
- public function testCreateAccountWithPasswordHashWithLocalizedException()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->once())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->once())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer
- ->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer
- ->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share
- ->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager
- ->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $exception = new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Exception message')
- );
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customer, $hash)
- ->willThrowException($exception);
-
- $this->accountManagement->createAccountWithPasswordHash($customer, $hash);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- */
- public function testCreateAccountWithPasswordHashWithAddressException()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $address->expects($this->once())
- ->method('setCustomerId')
- ->with($customerId);
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->once())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->once())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer
- ->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer
- ->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share
- ->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager
- ->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customer, $hash)
- ->willReturn($customer);
- $exception = new \Magento\Framework\Exception\InputException(
- new \Magento\Framework\Phrase('Exception message')
- );
- $this->addressRepository
- ->expects($this->atLeastOnce())
- ->method('save')
- ->with($address)
- ->willThrowException($exception);
- $this->customerRepository
- ->expects($this->once())
- ->method('delete')
- ->with($customer);
-
- $this->accountManagement->createAccountWithPasswordHash($customer, $hash);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- */
- public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedException()
- {
- $storeId = 1;
- $storeName = 'store_name';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMockForAbstractClass();
-
- $customerMock->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn(null);
- $customerMock->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customerMock->expects($this->once())
- ->method('setCreatedIn')
- ->with($storeName)
- ->willReturnSelf();
- $customerMock->expects($this->once())
- ->method('getAddresses')
- ->willReturn([]);
- $customerMock->expects($this->once())
- ->method('setAddresses')
- ->with(null)
- ->willReturnSelf();
-
- $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $storeMock->expects($this->once())
- ->method('getName')
- ->willReturn($storeName);
-
- $this->storeManager->expects($this->exactly(2))
- ->method('getStore')
- ->with($storeId)
- ->willReturn($storeMock);
- $exception = new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Exception message')
- );
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customerMock, $hash)
- ->willThrowException($exception);
-
- $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash);
- }
-
- /**
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function testCreateAccountWithoutPassword()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu';
-
- $datetime = $this->prepareDateTimeFactory();
-
- $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $address->expects($this->once())
- ->method('setCustomerId')
- ->with($customerId);
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->atLeastOnce())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->atLeastOnce())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $this->customerRepository->expects($this->atLeastOnce())
- ->method('save')
- ->willReturn($customer);
- $this->addressRepository->expects($this->atLeastOnce())
- ->method('save')
- ->with($address);
- $this->customerRepository->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customer);
- $this->random->expects($this->once())
- ->method('getUniqueHash')
- ->willReturn($newLinkToken);
- $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'])
- ->disableOriginalConstructor()
- ->getMock();
- $customerSecure->expects($this->any())
- ->method('setRpToken')
- ->with($newLinkToken);
- $customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt')
- ->with($datetime)
- ->willReturnSelf();
- $customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn(null);
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($customerSecure);
- $this->emailNotificationMock->expects($this->once())
- ->method('newAccount')
- ->willReturnSelf();
-
- $this->accountManagement->createAccount($customer);
- }
-
- /**
- * Data provider for testCreateAccountWithPasswordInputException test
- *
- * @return array
- */
- public function dataProviderCheckPasswordStrength()
- {
- return [
- [
- 'testNumber' => 1,
- 'password' => 'qwer',
- 'minPasswordLength' => 5,
- 'minCharacterSetsNum' => 1
- ],
- [
- 'testNumber' => 2,
- 'password' => 'wrfewqedf1',
- 'minPasswordLength' => 5,
- 'minCharacterSetsNum' => 3
- ]
- ];
- }
-
- /**
- * @param int $testNumber
- * @param string $password
- * @param int $minPasswordLength
- * @param int $minCharacterSetsNum
- * @dataProvider dataProviderCheckPasswordStrength
- */
- public function testCreateAccountWithPasswordInputException(
- $testNumber,
- $password,
- $minPasswordLength,
- $minCharacterSetsNum
- ) {
- $this->scopeConfig->expects($this->any())
- ->method('getValue')
- ->will(
- $this->returnValueMap(
- [
- [
- AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH,
- 'default',
- null,
- $minPasswordLength,
- ],
- [
- AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER,
- 'default',
- null,
- $minCharacterSetsNum],
- ]
- )
- );
-
- $this->string->expects($this->any())
- ->method('strlen')
- ->with($password)
- ->willReturn(iconv_strlen($password, 'UTF-8'));
-
- if ($testNumber == 1) {
- $this->expectException(
- \Magento\Framework\Exception\InputException::class,
- 'Please enter a password with at least ' . $minPasswordLength . ' characters.'
- );
- }
-
- if ($testNumber == 2) {
- $this->expectException(
- \Magento\Framework\Exception\InputException::class,
- 'Minimum of different classes of characters in password is ' . $minCharacterSetsNum .
- '. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.'
- );
- }
-
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $this->accountManagement->createAccount($customer, $password);
- }
-
- public function testCreateAccountInputExceptionExtraLongPassword()
- {
- $password = '257*chars*************************************************************************************'
- . '****************************************************************************************************'
- . '***************************************************************';
-
- $this->string->expects($this->any())
- ->method('strlen')
- ->with($password)
- ->willReturn(iconv_strlen($password, 'UTF-8'));
-
- $this->expectException(
- \Magento\Framework\Exception\InputException::class,
- 'Please enter a password with at most 256 characters.'
- );
-
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $this->accountManagement->createAccount($customer, $password);
- }
-
- /**
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function testCreateAccountWithPassword()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
- $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu';
- $templateIdentifier = 'Template Identifier';
- $sender = 'Sender';
- $password = 'wrfewqedf1';
- $minPasswordLength = 5;
- $minCharacterSetsNum = 2;
-
- $datetime = $this->prepareDateTimeFactory();
-
- $this->scopeConfig->expects($this->any())
- ->method('getValue')
- ->willReturnMap(
- [
- [
- AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH,
- 'default',
- null,
- $minPasswordLength,
- ],
- [
- AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER,
- 'default',
- null,
- $minCharacterSetsNum],
- [
- AccountManagement::XML_PATH_REGISTER_EMAIL_TEMPLATE,
- ScopeInterface::SCOPE_STORE,
- $defaultStoreId,
- $templateIdentifier,
- ],
- [
- AccountManagement::XML_PATH_REGISTER_EMAIL_IDENTITY,
- ScopeInterface::SCOPE_STORE,
- 1,
- $sender
- ]
- ]
- );
- $this->string->expects($this->any())
- ->method('strlen')
- ->with($password)
- ->willReturn(iconv_strlen($password, 'UTF-8'));
- $this->encryptor->expects($this->once())
- ->method('getHash')
- ->with($password, true)
- ->willReturn($hash);
- $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $address->expects($this->once())
- ->method('setCustomerId')
- ->with($customerId);
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock();
- $website->expects($this->atLeastOnce())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->atLeastOnce())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $this->customerRepository->expects($this->atLeastOnce())
- ->method('save')
- ->willReturn($customer);
- $this->addressRepository->expects($this->atLeastOnce())
- ->method('save')
- ->with($address);
- $this->customerRepository->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customer);
- $this->random->expects($this->once())
- ->method('getUniqueHash')
- ->willReturn($newLinkToken);
- $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'])
- ->disableOriginalConstructor()
- ->getMock();
- $customerSecure->expects($this->any())
- ->method('setRpToken')
- ->with($newLinkToken);
- $customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt')
- ->with($datetime)
- ->willReturnSelf();
- $customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn($hash);
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($customerSecure);
- $this->emailNotificationMock->expects($this->once())
- ->method('newAccount')
- ->willReturnSelf();
-
- $this->accountManagement->createAccount($customer, $password);
- }
-
- /**
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function testSendPasswordReminderEmail()
- {
- $customerId = 1;
- $customerStoreId = 2;
- $customerEmail = 'email@email.com';
- $customerData = ['key' => 'value'];
- $customerName = 'Customer Name';
- $templateIdentifier = 'Template Identifier';
- $sender = 'Sender';
-
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMock();
- $customer->expects($this->any())
- ->method('getStoreId')
- ->willReturn($customerStoreId);
- $customer->expects($this->any())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->any())
- ->method('getEmail')
- ->willReturn($customerEmail);
-
- $this->store->expects($this->any())
- ->method('getId')
- ->willReturn($customerStoreId);
-
- $this->storeManager->expects($this->at(0))
- ->method('getStore')
- ->willReturn($this->store);
-
- $this->storeManager->expects($this->at(1))
- ->method('getStore')
- ->with($customerStoreId)
- ->willReturn($this->store);
-
- $this->customerRegistry->expects($this->once())
- ->method('retrieveSecureData')
- ->with($customerId)
- ->willReturn($this->customerSecure);
-
- $this->dataObjectProcessor->expects($this->once())
- ->method('buildOutputDataArray')
- ->with($customer, \Magento\Customer\Api\Data\CustomerInterface::class)
- ->willReturn($customerData);
-
- $this->customerViewHelper->expects($this->any())
- ->method('getCustomerName')
- ->with($customer)
- ->willReturn($customerName);
-
- $this->customerSecure->expects($this->once())
- ->method('addData')
- ->with($customerData)
- ->willReturnSelf();
- $this->customerSecure->expects($this->once())
- ->method('setData')
- ->with('name', $customerName)
- ->willReturnSelf();
-
- $this->scopeConfig->expects($this->at(0))
- ->method('getValue')
- ->with(AccountManagement::XML_PATH_REMIND_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $customerStoreId)
- ->willReturn($templateIdentifier);
- $this->scopeConfig->expects($this->at(1))
- ->method('getValue')
- ->with(AccountManagement::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId)
- ->willReturn($sender);
-
- $transport = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class)
- ->getMock();
-
- $this->transportBuilder->expects($this->once())
- ->method('setTemplateIdentifier')
- ->with($templateIdentifier)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->once())
- ->method('setTemplateOptions')
- ->with(['area' => Area::AREA_FRONTEND, 'store' => $customerStoreId])
- ->willReturnSelf();
- $this->transportBuilder->expects($this->once())
- ->method('setTemplateVars')
- ->with(['customer' => $this->customerSecure, 'store' => $this->store])
- ->willReturnSelf();
- $this->transportBuilder->expects($this->once())
- ->method('setFrom')
- ->with($sender)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->once())
- ->method('addTo')
- ->with($customerEmail, $customerName)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->once())
- ->method('getTransport')
- ->willReturn($transport);
-
- $transport->expects($this->once())
- ->method('sendMessage');
-
- $this->assertEquals($this->accountManagement, $this->accountManagement->sendPasswordReminderEmail($customer));
- }
-
- /**
- * @param string $email
- * @param string $templateIdentifier
- * @param string $sender
- * @param int $storeId
- * @param int $customerId
- * @param string $hash
- */
- protected function prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash)
- {
- $websiteId = 1;
-
- $datetime = $this->prepareDateTimeFactory();
-
- $customerData = ['key' => 'value'];
- $customerName = 'Customer Name';
-
- $this->store->expects($this->once())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $this->store->expects($this->any())
- ->method('getId')
- ->willReturn($storeId);
-
- $this->storeManager->expects($this->any())
- ->method('getStore')
- ->willReturn($this->store);
-
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMock();
- $customer->expects($this->any())
- ->method('getEmail')
- ->willReturn($email);
- $customer->expects($this->any())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->any())
- ->method('getStoreId')
- ->willReturn($storeId);
-
- $this->customerRepository->expects($this->once())
- ->method('get')
- ->with($email, $websiteId)
- ->willReturn($customer);
- $this->customerRepository->expects($this->once())
- ->method('save')
- ->with($customer)
- ->willReturnSelf();
-
- $this->random->expects($this->once())
- ->method('getUniqueHash')
- ->willReturn($hash);
-
- $this->customerViewHelper->expects($this->any())
- ->method('getCustomerName')
- ->with($customer)
- ->willReturn($customerName);
-
- $this->customerSecure->expects($this->any())
- ->method('setRpToken')
- ->with($hash)
- ->willReturnSelf();
- $this->customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt')
- ->with($datetime)
- ->willReturnSelf();
- $this->customerSecure->expects($this->any())
- ->method('addData')
- ->with($customerData)
- ->willReturnSelf();
- $this->customerSecure->expects($this->any())
- ->method('setData')
- ->with('name', $customerName)
- ->willReturnSelf();
-
- $this->customerRegistry->expects($this->any())
- ->method('retrieveSecureData')
- ->with($customerId)
- ->willReturn($this->customerSecure);
-
- $this->dataObjectProcessor->expects($this->any())
- ->method('buildOutputDataArray')
- ->with($customer, \Magento\Customer\Api\Data\CustomerInterface::class)
- ->willReturn($customerData);
-
- $this->prepareEmailSend($email, $templateIdentifier, $sender, $storeId, $customerName);
- }
-
- /**
- * @param $email
- * @param $templateIdentifier
- * @param $sender
- * @param $storeId
- * @param $customerName
- */
- protected function prepareEmailSend($email, $templateIdentifier, $sender, $storeId, $customerName)
- {
- $transport = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class)
- ->getMock();
-
- $this->transportBuilder->expects($this->any())
- ->method('setTemplateIdentifier')
- ->with($templateIdentifier)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->any())
- ->method('setTemplateOptions')
- ->with(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
- ->willReturnSelf();
- $this->transportBuilder->expects($this->any())
- ->method('setTemplateVars')
- ->with(['customer' => $this->customerSecure, 'store' => $this->store])
- ->willReturnSelf();
- $this->transportBuilder->expects($this->any())
- ->method('setFrom')
- ->with($sender)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->any())
- ->method('addTo')
- ->with($email, $customerName)
- ->willReturnSelf();
- $this->transportBuilder->expects($this->any())
- ->method('getTransport')
- ->willReturn($transport);
-
- $transport->expects($this->any())
- ->method('sendMessage');
- }
-
- public function testInitiatePasswordResetEmailReminder()
- {
- $customerId = 1;
-
- $email = 'test@example.com';
- $template = AccountManagement::EMAIL_REMINDER;
- $templateIdentifier = 'Template Identifier';
- $sender = 'Sender';
-
- $storeId = 1;
-
- mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX);
- $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true));
-
- $this->emailNotificationMock->expects($this->once())
- ->method('passwordReminder')
- ->willReturnSelf();
-
- $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash);
-
- $this->assertTrue($this->accountManagement->initiatePasswordReset($email, $template));
- }
-
- public function testInitiatePasswordResetEmailReset()
- {
- $storeId = 1;
- $customerId = 1;
-
- $email = 'test@example.com';
- $template = AccountManagement::EMAIL_RESET;
- $templateIdentifier = 'Template Identifier';
- $sender = 'Sender';
-
- mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX);
- $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true));
-
- $this->emailNotificationMock->expects($this->once())
- ->method('passwordResetConfirmation')
- ->willReturnSelf();
-
- $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash);
-
- $this->assertTrue($this->accountManagement->initiatePasswordReset($email, $template));
- }
-
- public function testInitiatePasswordResetNoTemplate()
- {
- $storeId = 1;
- $customerId = 1;
-
- $email = 'test@example.com';
- $template = null;
- $templateIdentifier = 'Template Identifier';
- $sender = 'Sender';
-
- mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX);
- $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true));
-
- $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash);
-
- $this->expectException(\Magento\Framework\Exception\InputException::class);
- $this->expectExceptionMessage(
- 'Invalid value of "" provided for the template field. Possible values: email_reminder or email_reset.'
- );
- $this->accountManagement->initiatePasswordReset($email, $template);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\InputException
- * @expectedExceptionMessage Invalid value of "" provided for the customerId field
- */
- public function testValidateResetPasswordTokenBadCustomerId()
- {
- $this->accountManagement->validateResetPasswordLinkToken(null, '');
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\InputException
- * @expectedExceptionMessage resetPasswordLinkToken is a required field
- */
- public function testValidateResetPasswordTokenBadResetPasswordLinkToken()
- {
- $this->accountManagement->validateResetPasswordLinkToken(22, null);
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\State\InputMismatchException
- * @expectedExceptionMessage Reset password token mismatch
- */
- public function testValidateResetPasswordTokenTokenMismatch()
- {
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($this->customerSecure);
-
- $this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken');
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\State\ExpiredException
- * @expectedExceptionMessage Reset password token expired
- */
- public function testValidateResetPasswordTokenTokenExpired()
- {
- $this->reInitModel();
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($this->customerSecure);
-
- $this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken');
- }
-
- /**
- * return bool
- */
- public function testValidateResetPasswordToken()
- {
- $this->reInitModel();
-
- $this->customer
- ->expects($this->once())
- ->method('getResetPasswordLinkExpirationPeriod')
- ->willReturn(100000);
-
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($this->customerSecure);
-
- $this->assertTrue($this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken'));
- }
-
- /**
- * reInit $this->accountManagement object
- */
- private function reInitModel()
- {
- $this->customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->disableOriginalConstructor()
- ->setMethods(
- [
- 'getRpToken',
- 'getRpTokenCreatedAt',
- 'getPasswordHash',
- 'setPasswordHash',
- 'setRpToken',
- 'setRpTokenCreatedAt',
- ]
- )
- ->getMock();
-
- $this->customerSecure
- ->expects($this->any())
- ->method('getRpToken')
- ->willReturn('newStringToken');
-
- $pastDateTime = '2016-10-25 00:00:00';
-
- $this->customerSecure
- ->expects($this->any())
- ->method('getRpTokenCreatedAt')
- ->willReturn($pastDateTime);
-
- $this->customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
- ->disableOriginalConstructor()
- ->setMethods(['getResetPasswordLinkExpirationPeriod'])
- ->getMock();
-
- $this->prepareDateTimeFactory();
-
- $this->sessionManager = $this->getMockBuilder(\Magento\Framework\Session\SessionManagerInterface::class)
- ->disableOriginalConstructor()
- ->setMethods(['destroy', 'start', 'writeClose'])
- ->getMockForAbstractClass();
- $this->visitorCollectionFactory = $this->getMockBuilder(
- \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class
- )
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $this->saveHandler = $this->getMockBuilder(\Magento\Framework\Session\SaveHandlerInterface::class)
- ->disableOriginalConstructor()
- ->setMethods(['destroy'])
- ->getMockForAbstractClass();
-
- $dateTime = '2017-10-25 18:57:08';
- $timestamp = '1508983028';
- $dateTimeMock = $this->createMock(\DateTime::class);
- $dateTimeMock->expects($this->any())
- ->method('format')
- ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)
- ->willReturn($dateTime);
-
- $dateTimeMock
- ->expects($this->any())
- ->method('getTimestamp')
- ->willReturn($timestamp);
-
- $dateTimeMock
- ->expects($this->any())
- ->method('setTimestamp')
- ->willReturnSelf();
-
- $dateTimeFactory = $this->createMock(DateTimeFactory::class);
- $dateTimeFactory->expects($this->any())->method('create')->willReturn($dateTimeMock);
-
- $this->objectManagerHelper = new ObjectManagerHelper($this);
- $this->accountManagement = $this->objectManagerHelper->getObject(
- \Magento\Customer\Model\AccountManagement::class,
- [
- 'customerFactory' => $this->customerFactory,
- 'customerRegistry' => $this->customerRegistry,
- 'customerRepository' => $this->customerRepository,
- 'customerModel' => $this->customer,
- 'dateTimeFactory' => $dateTimeFactory,
- 'stringHelper' => $this->string,
- 'scopeConfig' => $this->scopeConfig,
- 'sessionManager' => $this->sessionManager,
- 'visitorCollectionFactory' => $this->visitorCollectionFactory,
- 'saveHandler' => $this->saveHandler,
- 'encryptor' => $this->encryptor,
- 'dataProcessor' => $this->dataObjectProcessor,
- 'storeManager' => $this->storeManager,
- 'transportBuilder' => $this->transportBuilder,
- ]
- );
- $reflection = new \ReflectionClass(get_class($this->accountManagement));
- $reflectionProperty = $reflection->getProperty('authentication');
- $reflectionProperty->setAccessible(true);
- $reflectionProperty->setValue($this->accountManagement, $this->authenticationMock);
- }
-
- /**
- * @return void
- */
- public function testChangePassword()
- {
- $customerId = 7;
- $email = 'test@example.com';
- $currentPassword = '1234567';
- $newPassword = 'abcdefg';
- $passwordHash = '1a2b3f4c';
-
- $this->reInitModel();
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMock();
- $customer->expects($this->any())
- ->method('getId')
- ->willReturn($customerId);
-
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($email)
- ->willReturn($customer);
-
- $this->authenticationMock->expects($this->once())
- ->method('authenticate');
-
- $this->customerSecure->expects($this->once())
- ->method('setRpToken')
- ->with(null);
- $this->customerSecure->expects($this->once())
- ->method('setRpTokenCreatedAt')
- ->willReturnSelf();
- $this->customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn($passwordHash);
-
- $this->customerRegistry->expects($this->any())
- ->method('retrieveSecureData')
- ->with($customerId)
- ->willReturn($this->customerSecure);
-
- $this->scopeConfig->expects($this->any())
- ->method('getValue')
- ->willReturnMap(
- [
- [
- AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH,
- 'default',
- null,
- 7,
- ],
- [
- AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER,
- 'default',
- null,
- 1
- ],
- ]
- );
- $this->string->expects($this->any())
- ->method('strlen')
- ->with($newPassword)
- ->willReturn(7);
-
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customer);
-
- $this->sessionManager->expects($this->atLeastOnce())->method('start');
- $this->sessionManager->expects($this->atLeastOnce())->method('writeClose');
- $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId');
-
- $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class)
- ->disableOriginalConstructor()
- ->setMethods(['getSessionId'])
- ->getMock();
- $visitor->expects($this->at(0))->method('getSessionId')->willReturn('session_id_1');
- $visitor->expects($this->at(1))->method('getSessionId')->willReturn('session_id_2');
- $visitorCollection = $this->getMockBuilder(
- \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class
- )
- ->disableOriginalConstructor()->setMethods(['addFieldToFilter', 'getItems'])->getMock();
- $visitorCollection->expects($this->atLeastOnce())->method('addFieldToFilter')->willReturnSelf();
- $visitorCollection->expects($this->atLeastOnce())->method('getItems')->willReturn([$visitor, $visitor]);
- $this->visitorCollectionFactory->expects($this->atLeastOnce())->method('create')
- ->willReturn($visitorCollection);
- $this->saveHandler->expects($this->at(0))->method('destroy')->with('session_id_1');
- $this->saveHandler->expects($this->at(1))->method('destroy')->with('session_id_2');
-
- $this->assertTrue($this->accountManagement->changePassword($email, $currentPassword, $newPassword));
- }
-
- public function testResetPassword()
- {
- $customerEmail = 'customer@example.com';
- $customerId = '1';
- $resetToken = 'newStringToken';
- $newPassword = 'new_password';
-
- $this->reInitModel();
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer->expects($this->any())->method('getId')->willReturn($customerId);
- $this->customerRepository->expects($this->atLeastOnce())->method('get')->with($customerEmail)
- ->willReturn($customer);
- $this->customer->expects($this->atLeastOnce())->method('getResetPasswordLinkExpirationPeriod')
- ->willReturn(100000);
- $this->string->expects($this->any())->method('strlen')->willReturnCallback(
- function ($string) {
- return strlen($string);
- }
- );
- $this->customerRegistry->expects($this->atLeastOnce())->method('retrieveSecureData')
- ->willReturn($this->customerSecure);
-
- $this->customerSecure->expects($this->once())
- ->method('setRpToken')
- ->with(null);
- $this->customerSecure->expects($this->once())
- ->method('setRpTokenCreatedAt')
- ->with(null);
- $this->customerSecure->expects($this->any())
- ->method('setPasswordHash')
- ->willReturn(null);
-
- $this->sessionManager->expects($this->atLeastOnce())->method('destroy');
- $this->sessionManager->expects($this->atLeastOnce())->method('start');
- $this->sessionManager->expects($this->atLeastOnce())->method('writeClose');
- $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId');
- $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class)
- ->disableOriginalConstructor()
- ->setMethods(['getSessionId'])
- ->getMock();
- $visitor->expects($this->at(0))->method('getSessionId')->willReturn('session_id_1');
- $visitor->expects($this->at(1))->method('getSessionId')->willReturn('session_id_2');
- $visitorCollection = $this->getMockBuilder(
- \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class
- )
- ->disableOriginalConstructor()->setMethods(['addFieldToFilter', 'getItems'])->getMock();
- $visitorCollection->expects($this->atLeastOnce())->method('addFieldToFilter')->willReturnSelf();
- $visitorCollection->expects($this->atLeastOnce())->method('getItems')->willReturn([$visitor, $visitor]);
- $this->visitorCollectionFactory->expects($this->atLeastOnce())->method('create')
- ->willReturn($visitorCollection);
- $this->saveHandler->expects($this->at(0))->method('destroy')->with('session_id_1');
- $this->saveHandler->expects($this->at(1))->method('destroy')->with('session_id_2');
- $this->assertTrue($this->accountManagement->resetPassword($customerEmail, $resetToken, $newPassword));
- }
-
- /**
- * @return void
- */
- public function testChangePasswordException()
- {
- $email = 'test@example.com';
- $currentPassword = '1234567';
- $newPassword = 'abcdefg';
-
- $exception = new NoSuchEntityException(
- new \Magento\Framework\Phrase('Exception message')
- );
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($email)
- ->willThrowException($exception);
-
- $this->expectException(
- \Magento\Framework\Exception\InvalidEmailOrPasswordException::class,
- 'Invalid login or password.'
- );
-
- $this->accountManagement->changePassword($email, $currentPassword, $newPassword);
- }
-
- /**
- * @return void
- */
- public function testAuthenticate()
- {
- $username = 'login';
- $password = '1234567';
- $passwordHash = '1a2b3f4c';
-
- $customerData = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMock();
-
- $customerModel = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
- ->disableOriginalConstructor()
- ->getMock();
- $customerModel->expects($this->once())
- ->method('updateData')
- ->willReturn($customerModel);
-
- $this->customerRepository
- ->expects($this->once())
- ->method('get')
- ->with($username)
- ->willReturn($customerData);
-
- $this->authenticationMock->expects($this->once())
- ->method('authenticate');
-
- $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->setMethods(['getPasswordHash'])
- ->disableOriginalConstructor()
- ->getMock();
- $customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn($passwordHash);
-
- $this->customerRegistry->expects($this->any())
- ->method('retrieveSecureData')
- ->willReturn($customerSecure);
-
- $this->customerFactory->expects($this->once())
- ->method('create')
- ->willReturn($customerModel);
-
- $this->manager->expects($this->exactly(2))
- ->method('dispatch')
- ->withConsecutive(
- [
- 'customer_customer_authenticated',
- ['model' => $customerModel, 'password' => $password]
- ],
- [
- 'customer_data_object_login', ['customer' => $customerData]
- ]
- );
-
- $this->assertEquals($customerData, $this->accountManagement->authenticate($username, $password));
- }
-
- /**
- * @param int $isConfirmationRequired
- * @param string|null $confirmation
- * @param string $expected
- * @dataProvider dataProviderGetConfirmationStatus
- */
- public function testGetConfirmationStatus(
- $isConfirmationRequired,
- $confirmation,
- $expected
- ) {
- $websiteId = 1;
- $customerId = 1;
- $customerEmail = 'test1@example.com';
-
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $customerMock->expects($this->once())
- ->method('getId')
- ->willReturn($customerId);
- $customerMock->expects($this->any())
- ->method('getConfirmation')
- ->willReturn($confirmation);
- $customerMock->expects($this->once())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customerMock->expects($this->once())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
-
- $this->accountConfirmation->expects($this->once())
- ->method('isConfirmationRequired')
- ->with($websiteId, $customerId, $customerEmail)
- ->willReturn($isConfirmationRequired);
-
- $this->customerRepository->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customerMock);
-
- $this->assertEquals($expected, $this->accountManagement->getConfirmationStatus($customerId));
- }
-
- /**
- * @return array
- */
- public function dataProviderGetConfirmationStatus()
- {
- return [
- [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED],
- [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED],
- [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED],
- [1, null, AccountManagement::ACCOUNT_CONFIRMED],
- [1, 'test', AccountManagement::ACCOUNT_CONFIRMATION_REQUIRED],
- ];
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- */
- public function testCreateAccountWithPasswordHashForGuest()
- {
- $storeId = 1;
- $storeName = 'store_name';
- $websiteId = 1;
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
- ->disableOriginalConstructor()
- ->getMock();
- $storeMock->expects($this->once())
- ->method('getId')
- ->willReturn($storeId);
- $storeMock->expects($this->once())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $storeMock->expects($this->once())
- ->method('getName')
- ->willReturn($storeName);
-
- $this->storeManager->expects($this->exactly(3))
- ->method('getStore')
- ->willReturn($storeMock);
-
- $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
- ->getMockForAbstractClass();
- $customerMock->expects($this->exactly(2))
- ->method('getId')
- ->willReturn(null);
- $customerMock->expects($this->exactly(3))
- ->method('getStoreId')
- ->willReturn(null);
- $customerMock->expects($this->exactly(2))
- ->method('getWebsiteId')
- ->willReturn(null);
- $customerMock->expects($this->once())
- ->method('setStoreId')
- ->with($storeId)
- ->willReturnSelf();
- $customerMock->expects($this->once())
- ->method('setWebsiteId')
- ->with($websiteId)
- ->willReturnSelf();
- $customerMock->expects($this->once())
- ->method('setCreatedIn')
- ->with($storeName)
- ->willReturnSelf();
- $customerMock->expects($this->once())
- ->method('getAddresses')
- ->willReturn(null);
- $customerMock->expects($this->once())
- ->method('setAddresses')
- ->with(null)
- ->willReturnSelf();
-
- $this->customerRepository
- ->expects($this->once())
- ->method('save')
- ->with($customerMock, $hash)
- ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('Exception message')));
-
- $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash);
- }
-
- public function testCreateAccountWithPasswordHashWithCustomerAddresses()
- {
- $websiteId = 1;
- $addressId = 2;
- $customerId = null;
- $storeId = 1;
- $hash = '4nj54lkj5jfi03j49f8bgujfgsd';
-
- $this->prepareDateTimeFactory();
-
- //Handle store
- $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
- $store->expects($this->any())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- //Handle address - existing and non-existing. Non-Existing should return null when call getId method
- $existingAddress = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $nonExistingAddress = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- //Ensure that existing address is not in use
- $this->addressRepository
- ->expects($this->atLeastOnce())
- ->method("save")
- ->withConsecutive(
- [$this->logicalNot($this->identicalTo($existingAddress))],
- [$this->identicalTo($nonExistingAddress)]
- );
-
- $existingAddress
- ->expects($this->any())
- ->method("getId")
- ->willReturn($addressId);
- //Expects that id for existing address should be unset
- $existingAddress
- ->expects($this->once())
- ->method("setId")
- ->with(null);
- //Handle Customer calls
- $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock();
- $customer
- ->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer
- ->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer
- ->expects($this->any())
- ->method("getId")
- ->willReturn($customerId);
- //Return Customer from customer repository
- $this->customerRepository
- ->expects($this->atLeastOnce())
- ->method('save')
- ->willReturn($customer);
- $this->customerRepository
- ->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customer);
- $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class)
- ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'])
- ->disableOriginalConstructor()
- ->getMock();
- $customerSecure->expects($this->once())
- ->method('setRpToken')
- ->with($hash);
-
- $customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn($hash);
-
- $this->customerRegistry->expects($this->any())
- ->method('retrieveSecureData')
- ->with($customerId)
- ->willReturn($customerSecure);
-
- $this->random->expects($this->once())
- ->method('getUniqueHash')
- ->willReturn($hash);
-
- $customer
- ->expects($this->atLeastOnce())
- ->method('getAddresses')
- ->willReturn([$existingAddress, $nonExistingAddress]);
-
- $this->storeManager
- ->expects($this->atLeastOnce())
- ->method('getStore')
- ->willReturn($store);
-
- $this->assertSame($customer, $this->accountManagement->createAccountWithPasswordHash($customer, $hash));
- }
-
- /**
- * @return string
- */
- private function prepareDateTimeFactory()
- {
- $dateTime = '2017-10-25 18:57:08';
- $timestamp = '1508983028';
- $dateTimeMock = $this->createMock(\DateTime::class);
- $dateTimeMock->expects($this->any())
- ->method('format')
- ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)
- ->willReturn($dateTime);
-
- $dateTimeMock
- ->expects($this->any())
- ->method('getTimestamp')
- ->willReturn($timestamp);
-
- $this->dateTimeFactory
- ->expects($this->any())
- ->method('create')
- ->willReturn($dateTimeMock);
-
- return $dateTime;
- }
-
- public function testCreateAccountUnexpectedValueException()
- {
- $websiteId = 1;
- $storeId = null;
- $defaultStoreId = 1;
- $customerId = 1;
- $customerEmail = 'email@email.com';
- $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu';
- $exception = new \UnexpectedValueException('Template file was not found');
-
- $datetime = $this->prepareDateTimeFactory();
-
- $address = $this->createMock(\Magento\Customer\Api\Data\AddressInterface::class);
- $address->expects($this->once())
- ->method('setCustomerId')
- ->with($customerId);
- $store = $this->createMock(\Magento\Store\Model\Store::class);
- $store->expects($this->once())
- ->method('getId')
- ->willReturn($defaultStoreId);
- $website = $this->createMock(\Magento\Store\Model\Website::class);
- $website->expects($this->atLeastOnce())
- ->method('getStoreIds')
- ->willReturn([1, 2, 3]);
- $website->expects($this->once())
- ->method('getDefaultStore')
- ->willReturn($store);
- $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class);
- $customer->expects($this->atLeastOnce())
- ->method('getId')
- ->willReturn($customerId);
- $customer->expects($this->atLeastOnce())
- ->method('getEmail')
- ->willReturn($customerEmail);
- $customer->expects($this->atLeastOnce())
- ->method('getWebsiteId')
- ->willReturn($websiteId);
- $customer->expects($this->atLeastOnce())
- ->method('getStoreId')
- ->willReturn($storeId);
- $customer->expects($this->once())
- ->method('setStoreId')
- ->with($defaultStoreId);
- $customer->expects($this->once())
- ->method('getAddresses')
- ->willReturn([$address]);
- $customer->expects($this->once())
- ->method('setAddresses')
- ->with(null);
- $this->customerRepository->expects($this->once())
- ->method('get')
- ->with($customerEmail)
- ->willReturn($customer);
- $this->share->expects($this->once())
- ->method('isWebsiteScope')
- ->willReturn(true);
- $this->storeManager->expects($this->atLeastOnce())
- ->method('getWebsite')
- ->with($websiteId)
- ->willReturn($website);
- $this->customerRepository->expects($this->atLeastOnce())
- ->method('save')
- ->willReturn($customer);
- $this->addressRepository->expects($this->atLeastOnce())
- ->method('save')
- ->with($address);
- $this->customerRepository->expects($this->once())
- ->method('getById')
- ->with($customerId)
- ->willReturn($customer);
- $this->random->expects($this->once())
- ->method('getUniqueHash')
- ->willReturn($newLinkToken);
- $customerSecure = $this->createPartialMock(
- \Magento\Customer\Model\Data\CustomerSecure::class,
- ['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash']
- );
- $customerSecure->expects($this->any())
- ->method('setRpToken')
- ->with($newLinkToken);
- $customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt')
- ->with($datetime)
- ->willReturnSelf();
- $customerSecure->expects($this->any())
- ->method('getPasswordHash')
- ->willReturn(null);
- $this->customerRegistry->expects($this->atLeastOnce())
- ->method('retrieveSecureData')
- ->willReturn($customerSecure);
- $this->emailNotificationMock->expects($this->once())
- ->method('newAccount')
- ->willThrowException($exception);
- $this->logger->expects($this->once())->method('error')->with($exception);
-
- $this->accountManagement->createAccount($customer);
- }
-}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php
index 556dfe0b6f4c9..a3b0dc257515b 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php
@@ -311,7 +311,8 @@ public function testValidate(array $data, $expected)
->will($this->returnValue([]));
$this->directoryDataMock->expects($this->any())
- ->method('isRegionRequired');
+ ->method('isRegionRequired')
+ ->willReturn($data['region_required']);
$countryCollectionMock = $this->getMockBuilder(\Magento\Directory\Model\ResourceModel\Country\Collection::class)
->disableOriginalConstructor()
@@ -326,14 +327,18 @@ public function testValidate(array $data, $expected)
$regionModelMock = $this->getMockBuilder(\Magento\Directory\Model\Region::class)
->disableOriginalConstructor()
- ->setMethods(['getCountryId', 'getName', 'load'])
+ ->setMethods(['getCountryId', 'getName', 'load', 'loadByCode'])
->getMock();
$this->regionFactoryMock->expects($this->any())->method('create')->willReturn($regionModelMock);
$regionModelMock->expects($this->any())->method('load')->with($data['region_id'])->willReturnSelf();
$regionModelMock->expects($this->any())->method('getCountryId')->willReturn($countryId);
- $regionModelMock->expects($this->any())->method('getName')->willReturn('RegionName');
+ $regionModelMock->expects($this->any())->method('getName')->willReturn($data['region']);
+ $regionModelMock->expects($this->any())
+ ->method('loadByCode')
+ ->with($data['region'], $countryId)
+ ->willReturnSelf();
$countryModelMock = $this->getMockBuilder(\Magento\Directory\Model\Country::class)
->disableOriginalConstructor()
@@ -352,7 +357,7 @@ public function testValidate(array $data, $expected)
->setMethods(['getAllIds'])
->getMock();
$countryModelMock->expects($this->any())->method('getRegionCollection')->willReturn($regionCollectionMock);
- $regionCollectionMock->expects($this->any())->method('getAllIds')->willReturn(['1']);
+ $regionCollectionMock->expects($this->any())->method('getAllIds')->willReturn($data['allowed_regions']);
foreach ($data as $key => $value) {
$this->model->setData($key, $value);
@@ -377,8 +382,11 @@ public function validateDataProvider()
'country_id' => $countryId,
'postcode' => 07201,
'region_id' => 1,
+ 'region' => 'RegionName',
+ 'region_required' => false,
'company' => 'Magento',
- 'fax' => '222-22-22'
+ 'fax' => '222-22-22',
+ 'allowed_regions' => ['1'],
];
return [
'firstname' => [
@@ -405,8 +413,28 @@ public function validateDataProvider()
array_merge(array_diff_key($data, ['postcode' => '']), ['country_id' => $countryId++]),
['postcode is a required field.'],
],
- 'region_id' => [
- array_merge($data, ['country_id' => $countryId++, 'region_id' => 2]),
+ 'region' => [
+ array_merge(
+ $data,
+ [
+ 'region_required' => true,
+ 'country_id' => $countryId++,
+ 'allowed_regions' => [],
+ 'region' => '',
+ ]
+ ),
+ ['region is a required field.'],
+ ],
+ 'region_id1' => [
+ array_merge($data, ['country_id' => $countryId, 'region_required' => true, 'region_id' => '']),
+ ['regionId is a required field.'],
+ ],
+ 'region_id2' => [
+ array_merge($data, ['country_id' => $countryId, 'region_id' => 2, 'allowed_regions' => []]),
+ true,
+ ],
+ 'region_id3' => [
+ array_merge($data, ['country_id' => $countryId, 'region_id' => 2, 'allowed_regions' => [1, 3]]),
['Invalid value of "2" provided for the regionId field.'],
],
'country_id' => [
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/DateTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/DateTest.php
index 6329970e0ca9c..553efea38a82b 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/DateTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/DateTest.php
@@ -12,6 +12,9 @@ class DateTest extends AbstractFormTestCase
/** @var \Magento\Customer\Model\Metadata\Form\Date */
protected $date;
+ /**
+ * @inheritdoc
+ */
protected function setUp()
{
parent::setUp();
@@ -46,6 +49,9 @@ protected function setUp()
);
}
+ /**
+ * Test extractValue
+ */
public function testExtractValue()
{
$requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
@@ -174,7 +180,7 @@ public function compactAndRestoreValueDataProvider()
return [
[1, 1],
[false, false],
- ['', null],
+ [null, null],
['test', 'test'],
[['element1', 'element2'], ['element1', 'element2']]
];
@@ -191,6 +197,9 @@ public function testRestoreValue($value, $expected)
$this->assertSame($expected, $this->date->restoreValue($value));
}
+ /**
+ * Test outputValue
+ */
public function testOutputValue()
{
$this->assertEquals(null, $this->date->outputValue());
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/TextTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/TextTest.php
index b95987cba1dcf..292d46a936092 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/TextTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/TextTest.php
@@ -5,8 +5,10 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Customer\Test\Unit\Model\Metadata\Form;
+use Magento\Customer\Api\Data\ValidationRuleInterface;
use Magento\Customer\Model\Metadata\Form\Text;
class TextTest extends AbstractFormTestCase
@@ -111,7 +113,7 @@ public function validateValueRequiredDataProvider()
*/
public function testValidateValueLength($value, $expected)
{
- $minTextLengthRule = $this->getMockBuilder(\Magento\Customer\Api\Data\ValidationRuleInterface::class)
+ $minTextLengthRule = $this->getMockBuilder(ValidationRuleInterface::class)
->disableOriginalConstructor()
->setMethods(['getName', 'getValue'])
->getMockForAbstractClass();
@@ -122,7 +124,7 @@ public function testValidateValueLength($value, $expected)
->method('getValue')
->will($this->returnValue(4));
- $maxTextLengthRule = $this->getMockBuilder(\Magento\Customer\Api\Data\ValidationRuleInterface::class)
+ $maxTextLengthRule = $this->getMockBuilder(ValidationRuleInterface::class)
->disableOriginalConstructor()
->setMethods(['getName', 'getValue'])
->getMockForAbstractClass();
@@ -133,7 +135,19 @@ public function testValidateValueLength($value, $expected)
->method('getValue')
->will($this->returnValue(8));
+ $inputValidationRule = $this->getMockBuilder(ValidationRuleInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getName', 'getValue'])
+ ->getMockForAbstractClass();
+ $inputValidationRule->expects($this->any())
+ ->method('getName')
+ ->will($this->returnValue('input_validation'));
+ $inputValidationRule->expects($this->any())
+ ->method('getValue')
+ ->will($this->returnValue('other'));
+
$validationRules = [
+ 'input_validation' => $inputValidationRule,
'min_text_length' => $minTextLengthRule,
'max_text_length' => $maxTextLengthRule,
];
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index 65cb1e257f5b6..e3d8f22088ef6 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.5",
+ "version": "101.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Customer/etc/acl.xml b/app/code/Magento/Customer/etc/acl.xml
index a500608e1cdf5..e8e6219bef4fe 100644
--- a/app/code/Magento/Customer/etc/acl.xml
+++ b/app/code/Magento/Customer/etc/acl.xml
@@ -12,6 +12,7 @@
+
@@ -19,10 +20,7 @@
-
-
-
-
+
diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html
index 6c17762a88227..59e7f16adfd51 100644
--- a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html
+++ b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html
@@ -21,7 +21,7 @@
diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml
index 8f65d54f458bc..fd5ecbfa7f277 100644
--- a/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml
+++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml
@@ -12,6 +12,9 @@
+
+ Magento\Customer\Block\DataProviders\AddressAttributeData
+
diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml b/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml
index 194dfd1bc7d2b..f053805409fe5 100644
--- a/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml
+++ b/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml
@@ -17,7 +17,11 @@
-
+
+
+ Magento\Customer\Block\DataProviders\AddressAttributeData
+
+