diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php
index 8e4b59d396986..38216ef98d2dd 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php
@@ -53,8 +53,10 @@ public function __construct(
*/
public function execute()
{
- $collection = $this->filter->getCollection($this->collectionFactory->create());
- $this->attributeHelper->setProductIds($collection->getAllIds());
+ if ($this->getRequest()->getParam('filters')) {
+ $collection = $this->filter->getCollection($this->collectionFactory->create());
+ $this->attributeHelper->setProductIds($collection->getAllIds());
+ }
if (!$this->_validateProducts()) {
return $this->resultRedirectFactory->create()->setPath('catalog/product/', ['_current' => true]);
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
new file mode 100644
index 0000000000000..9ce9d43db7b60
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php
@@ -0,0 +1,176 @@
+attributeHelper = $this->getMockBuilder('Magento\Catalog\Helper\Product\Edit\Action\Attribute')
+ ->setMethods(['getProductIds', 'setProductIds'])
+ ->disableOriginalConstructor()->getMock();
+
+ $this->resultRedirectFactory = $this->getMockBuilder('Magento\Backend\Model\View\Result\RedirectFactory')
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+
+ $this->filter = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter')
+ ->setMethods(['getCollection'])->disableOriginalConstructor()->getMock();
+
+ $this->collectionFactory = $this->getMockBuilder(
+ 'Magento\Catalog\Model\ResourceModel\Product\CollectionFactory'
+ )->setMethods(['create'])->disableOriginalConstructor()->getMock();
+
+ $this->resultPage = $this->getMockBuilder('Magento\Framework\View\Result\Page')
+ ->setMethods(['getConfig'])->disableOriginalConstructor()->getMock();
+
+ $resultPageFactory = $this->getMockBuilder('Magento\Framework\View\Result\PageFactory')
+ ->setMethods(['create'])->disableOriginalConstructor()->getMock();
+ $resultPageFactory->expects($this->any())->method('create')->willReturn($this->resultPage);
+
+ $this->prepareContext();
+
+ $this->object = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
+ 'Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Edit',
+ [
+ 'context' => $this->context,
+ 'attributeHelper' => $this->attributeHelper,
+ 'filter' => $this->filter,
+ 'resultPageFactory' => $resultPageFactory,
+ 'collectionFactory' => $this->collectionFactory
+ ]
+ );
+ }
+
+ private function prepareContext()
+ {
+ $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http')
+ ->setMethods(['getParam', 'getParams', 'setParams'])
+ ->disableOriginalConstructor()->getMock();
+
+ $objectManager = $this->getMock('Magento\Framework\ObjectManagerInterface');
+ $product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+ ->setMethods(['isProductsHasSku'])
+ ->disableOriginalConstructor()->getMock();
+ $product->expects($this->any())->method('isProductsHasSku')
+ ->with([1, 2, 3])
+ ->willReturn(true);
+ $objectManager->expects($this->any())->method('create')
+ ->with('Magento\Catalog\Model\Product')
+ ->willReturn($product);
+ $messageManager = $this->getMockBuilder('\Magento\Framework\Message\ManagerInterface')
+ ->setMethods([])
+ ->disableOriginalConstructor()->getMock();
+ $messageManager->expects($this->any())->method('addError')->willReturn(true);
+ $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context')
+ ->setMethods(['getRequest', 'getObjectManager', 'getMessageManager', 'getResultRedirectFactory'])
+ ->disableOriginalConstructor()->getMock();
+ $this->context->expects($this->any())->method('getRequest')->willReturn($this->request);
+ $this->context->expects($this->any())->method('getObjectManager')->willReturn($objectManager);
+ $this->context->expects($this->any())->method('getMessageManager')->willReturn($messageManager);
+ $this->context->expects($this->any())->method('getResultRedirectFactory')
+ ->willReturn($this->resultRedirectFactory);
+ }
+
+ public function testExecutePageRequested()
+ {
+ $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(['placeholder' => true]);
+ $this->request->expects($this->any())->method('getParams')->willReturn(
+ [
+ 'namespace' => 'product_listing',
+ 'exclude' => true,
+ 'filters' => ['placeholder' => true]
+ ]
+ );
+
+ $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn([1, 2, 3]);
+ $this->attributeHelper->expects($this->any())->method('setProductIds')->with([1, 2, 3]);
+
+ $collection = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Collection')
+ ->setMethods(['getAllIds'])
+ ->disableOriginalConstructor()->getMock();
+ $collection->expects($this->any())->method('getAllIds')->willReturn([1, 2, 3]);
+ $this->filter->expects($this->any())->method('getCollection')->with($collection)->willReturn($collection);
+ $this->collectionFactory->expects($this->any())->method('create')->willReturn($collection);
+
+ $title = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+ ->setMethods(['prepend'])
+ ->disableOriginalConstructor()->getMock();
+ $config = $this->getMockBuilder('Magento\Framework\View\Page\Config')
+ ->setMethods(['getTitle'])
+ ->disableOriginalConstructor()->getMock();
+ $config->expects($this->any())->method('getTitle')->willReturn($title);
+ $this->resultPage->expects($this->any())->method('getConfig')->willReturn($config);
+
+ $this->assertSame($this->resultPage, $this->object->execute());
+ }
+
+ public function testExecutePageReload()
+ {
+ $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(null);
+ $this->request->expects($this->any())->method('getParams')->willReturn([]);
+
+ $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn([1, 2, 3]);
+ $this->attributeHelper->expects($this->any())->method('setProductIds')->with([1, 2, 3]);
+
+ $title = $this->getMockBuilder('Magento\Framework\View\Page\Title')
+ ->setMethods(['prepend'])
+ ->disableOriginalConstructor()->getMock();
+ $config = $this->getMockBuilder('Magento\Framework\View\Page\Config')
+ ->setMethods(['getTitle'])
+ ->disableOriginalConstructor()->getMock();
+ $config->expects($this->any())->method('getTitle')->willReturn($title);
+ $this->resultPage->expects($this->any())->method('getConfig')->willReturn($config);
+
+ $this->assertSame($this->resultPage, $this->object->execute());
+ }
+
+ public function testExecutePageDirectAccess()
+ {
+ $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(null);
+ $this->request->expects($this->any())->method('getParams')->willReturn([]);
+ $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn(null);
+
+ $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect')
+ ->setMethods(['setPath'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $resultRedirect->expects($this->any())->method('setPath')
+ ->with('catalog/product/', ['_current' => true])
+ ->willReturnSelf();
+ $this->resultRedirectFactory->expects($this->any())
+ ->method('create')
+ ->willReturn($resultRedirect);
+
+ $this->assertSame($resultRedirect, $this->object->execute());
+ }
+}
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/form/renderer/fieldset/element.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/form/renderer/fieldset/element.phtml
index 5b50cdb8a1eaf..22f4385773240 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/form/renderer/fieldset/element.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/form/renderer/fieldset/element.phtml
@@ -15,12 +15,12 @@
getElement();
-$note = $element->getNote() ? '
' . $element->getNote() . '
' : '';
+$note = $element->getNote() ? '' . $element->getNote() . '
' : '';
$elementBeforeLabel = $element->getExtType() == 'checkbox' || $element->getExtType() == 'radio';
$addOn = $element->getBeforeElementHtml() || $element->getAfterElementHtml();
$fieldId = ($element->getHtmlId()) ? ' id="attribute-' . $element->getHtmlId() . '-container"' : '';
$entity = $element->getEntityAttribute();
-$fieldClass = "field field-{$element->getId()} {$element->getCssClass()}";
+$fieldClass = "admin__field field field-{$element->getId()} {$element->getCssClass()}";
$fieldClass .= ($elementBeforeLabel) ? ' choice' : '';
$fieldClass .= ($addOn) ? ' with-addon' : '';
$fieldClass .= ($element->getRequired()) ? ' required' : '';
@@ -51,7 +51,7 @@ $fieldAttributes = $fieldId . ' class="' . $fieldClass . '" '
getLabelHtml('', $block->getScopeLabel()) ?>
-
+
' . $block->getElementHtml() . '
' : $block->getElementHtml(); ?>
diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
index b6a68d413cab0..206b2d8b59d9d 100644
--- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -762,6 +762,8 @@ protected function getItemsPerPage()
$memoryUsagePercent = 0.8;
// Minimum Products limit
$minProductsLimit = 500;
+ // Maximal Products limit
+ $maxProductsLimit = 5000;
$this->_itemsPerPage = intval(
($memoryLimit * $memoryUsagePercent - memory_get_usage(true)) / $memoryPerProduct
@@ -769,6 +771,9 @@ protected function getItemsPerPage()
if ($this->_itemsPerPage < $minProductsLimit) {
$this->_itemsPerPage = $minProductsLimit;
}
+ if ($this->_itemsPerPage > $maxProductsLimit) {
+ $this->_itemsPerPage = $maxProductsLimit;
+ }
}
return $this->_itemsPerPage;
}
@@ -850,8 +855,10 @@ protected function getExportData()
if ($storeId == Store::DEFAULT_STORE_ID && isset($stockItemRows[$productId])) {
$dataRow = array_merge($dataRow, $stockItemRows[$productId]);
}
-
- $exportData = array_merge($exportData, $this->addMultirowData($dataRow, $multirawData));
+ $this->appendMultirowData($dataRow, $multirawData);
+ if ($dataRow) {
+ $exportData[] = $dataRow;
+ }
}
}
} catch (\Exception $e) {
@@ -1053,9 +1060,8 @@ protected function isValidAttributeValue($code, $value)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
- protected function addMultirowData($dataRow, $multiRawData)
+ private function appendMultirowData(&$dataRow, &$multiRawData)
{
- $result = [];
$productId = $dataRow['product_id'];
$productLinkId = $dataRow['product_link_id'];
$storeId = $dataRow['store_id'];
@@ -1121,7 +1127,6 @@ protected function addMultirowData($dataRow, $multiRawData)
}
}
$dataRow = $this->rowCustomizer->addData($dataRow, $productId);
-
}
if (!empty($this->collectedMultiselectsData[$storeId][$productId])) {
@@ -1144,7 +1149,7 @@ protected function addMultirowData($dataRow, $multiRawData)
}
if (empty($dataRow)) {
- return $result;
+ return null;
} elseif ($storeId != Store::DEFAULT_STORE_ID) {
$dataRow[self::COL_STORE] = $this->_storeIdToCode[$storeId];
if (isset($productData[Store::DEFAULT_STORE_ID][self::COL_VISIBILITY])) {
@@ -1152,9 +1157,19 @@ protected function addMultirowData($dataRow, $multiRawData)
}
}
$dataRow[self::COL_SKU] = $sku;
- $result[] = $dataRow;
+ return $dataRow;
+ }
- return $result;
+ /**
+ * @deprecated
+ * @param array $dataRow
+ * @param array $multiRawData
+ * @return array
+ */
+ protected function addMultirowData($dataRow, $multiRawData)
+ {
+ $data = $this->appendMultirowData($dataRow, $multiRawData);
+ return $data ? [$data] : [];
}
/**
diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php
index 585a1ed5336cf..579eb998e06af 100644
--- a/app/code/Magento/Checkout/Model/Cart.php
+++ b/app/code/Magento/Checkout/Model/Cart.php
@@ -321,9 +321,6 @@ protected function _getProductRequest($requestInfo)
$request = new \Magento\Framework\DataObject($requestInfo);
}
- if (!$request->hasQty()) {
- $request->setQty(1);
- }
!$request->hasFormKey() ?: $request->unsFormKey();
return $request;
@@ -350,7 +347,7 @@ public function addProduct($productInfo, $requestInfo = null)
//If product was not found in cart and there is set minimal qty for it
if ($minimumQty
&& $minimumQty > 0
- && $request->getQty() < $minimumQty
+ && !$request->getQty()
&& !$this->getQuote()->hasProductId($productId)
) {
$request->setQty($minimumQty);
@@ -690,7 +687,7 @@ public function updateItem($itemId, $requestInfo = null, $updatingParams = null)
// If product was not found in cart and there is set minimal qty for it
if ($minimumQty
&& $minimumQty > 0
- && $request->getQty() < $minimumQty
+ && !$request->getQty()
&& !$this->getQuote()->hasProductId($productId)
) {
$request->setQty($minimumQty);
diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php
index fb9a54be74457..3771d55535e06 100644
--- a/app/code/Magento/Cms/Model/Page/DataProvider.php
+++ b/app/code/Magento/Cms/Model/Page/DataProvider.php
@@ -49,6 +49,18 @@ public function __construct(
$this->collection = $pageCollectionFactory->create();
$this->dataPersistor = $dataPersistor;
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
+ $this->meta = $this->prepareMeta($this->meta);
+ }
+
+ /**
+ * Prepares Meta
+ *
+ * @param array $meta
+ * @return array
+ */
+ public function prepareMeta(array $meta)
+ {
+ return $meta;
}
/**
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
index 04b414a70a245..bbad307d28f90 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
@@ -138,18 +138,20 @@ public function getOptionText($value)
*/
public function addValueSortToCollection($collection, $dir = \Magento\Framework\DB\Select::SQL_ASC)
{
- $valueTable1 = $this->getAttribute()->getAttributeCode() . '_t1';
- $valueTable2 = $this->getAttribute()->getAttributeCode() . '_t2';
+ $attribute = $this->getAttribute();
+ $valueTable1 = $attribute->getAttributeCode() . '_t1';
+ $valueTable2 = $attribute->getAttributeCode() . '_t2';
+ $linkField = $attribute->getEntity()->getLinkField();
$collection->getSelect()->joinLeft(
- [$valueTable1 => $this->getAttribute()->getBackend()->getTable()],
- "e.entity_id={$valueTable1}.entity_id" .
- " AND {$valueTable1}.attribute_id='{$this->getAttribute()->getId()}'" .
+ [$valueTable1 => $attribute->getBackend()->getTable()],
+ "e.{$linkField}={$valueTable1}." . $linkField .
+ " AND {$valueTable1}.attribute_id='{$attribute->getId()}'" .
" AND {$valueTable1}.store_id=0",
[]
)->joinLeft(
- [$valueTable2 => $this->getAttribute()->getBackend()->getTable()],
- "e.entity_id={$valueTable2}.entity_id" .
- " AND {$valueTable2}.attribute_id='{$this->getAttribute()->getId()}'" .
+ [$valueTable2 => $attribute->getBackend()->getTable()],
+ "e.{$linkField}={$valueTable2}." . $linkField .
+ " AND {$valueTable2}.attribute_id='{$attribute->getId()}'" .
" AND {$valueTable2}.store_id='{$collection->getStoreId()}'",
[]
);
@@ -161,11 +163,11 @@ public function addValueSortToCollection($collection, $dir = \Magento\Framework\
$this->_attrOptionFactory->create()->addOptionValueToCollection(
$collection,
- $this->getAttribute(),
+ $attribute,
$valueExpr
);
- $collection->getSelect()->order("{$this->getAttribute()->getAttributeCode()} {$dir}");
+ $collection->getSelect()->order("{$attribute->getAttributeCode()} {$dir}");
return $this;
}
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
index de1a5e6cbae4d..3e7cdb9cc2500 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
@@ -5,7 +5,6 @@
*/
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Source;
-use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
class TableTest extends \PHPUnit_Framework_TestCase
@@ -13,12 +12,18 @@ class TableTest extends \PHPUnit_Framework_TestCase
/**
* @var \Magento\Eav\Model\Entity\Attribute\Source\Table
*/
- protected $_model;
+ private $model;
/**
- * @var CollectionFactory | \PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory
+ * | \PHPUnit_Framework_MockObject_MockObject
*/
- protected $collectionFactory;
+ private $collectionFactory;
+
+ /**
+ * @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $attrOptionFactory;
protected function setUp()
{
@@ -40,9 +45,19 @@ protected function setUp()
false
);
- $this->_model = $objectManager->getObject(
+ $this->attrOptionFactory = $this->getMockBuilder(
+ 'Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory'
+ )
+ ->setMethods(['create'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->model = $objectManager->getObject(
'Magento\Eav\Model\Entity\Attribute\Source\Table',
- ['attrOptionCollectionFactory' => $this->collectionFactory]
+ [
+ 'attrOptionCollectionFactory' => $this->collectionFactory,
+ 'attrOptionFactory' => $this->attrOptionFactory
+ ]
);
}
@@ -74,9 +89,9 @@ public function testGetFlatColumns()
$abstractAttributeMock->expects($this->any())->method('getAttributeCode')->will($this->returnValue('code'));
- $this->_model->setAttribute($abstractAttributeMock);
+ $this->model->setAttribute($abstractAttributeMock);
- $flatColumns = $this->_model->getFlatColumns();
+ $flatColumns = $this->model->getFlatColumns();
$this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
$this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
@@ -117,7 +132,7 @@ public function testGetSpecificOptions($optionIds, $withEmpty)
->method('getStoreId')
->willReturn($storeId);
- $this->_model->setAttribute($attribute);
+ $this->model->setAttribute($attribute);
$this->collectionFactory->expects($this->once())
->method('create')
@@ -148,7 +163,7 @@ public function testGetSpecificOptions($optionIds, $withEmpty)
array_unshift($options, ['label' => '', 'value' => '']);
}
- $this->assertEquals($options, $this->_model->getSpecificOptions($optionIds, $withEmpty));
+ $this->assertEquals($options, $this->model->getSpecificOptions($optionIds, $withEmpty));
}
public function specificOptionsProvider()
@@ -184,7 +199,7 @@ public function testGetOptionText($optionsIds, $value, $options, $expectedResult
->method('getStoreId')
->willReturn($storeId);
- $this->_model->setAttribute($attribute);
+ $this->model->setAttribute($attribute);
$this->collectionFactory->expects($this->once())
->method('create')
@@ -211,7 +226,7 @@ public function testGetOptionText($optionsIds, $value, $options, $expectedResult
->method('toOptionArray')
->willReturn($options);
- $this->assertEquals($expectedResult, $this->_model->getOptionText($value));
+ $this->assertEquals($expectedResult, $this->model->getOptionText($value));
}
public function getOptionTextProvider()
@@ -227,4 +242,57 @@ public function getOptionTextProvider()
['5', '5', [['label' => 'test label', 'value' => '5']], 'test label']
];
}
+
+ public function testAddValueSortToCollection()
+ {
+ $attributeCode = 'attribute_code';
+ $dir = \Magento\Framework\DB\Select::SQL_ASC;
+ $collection = $this->getMockBuilder('Magento\Eav\Model\Entity\Collection\AbstractCollection')
+ ->setMethods([ 'getSelect', 'getStoreId'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+ ->setMethods(['getAttributeCode', 'getEntity', 'getBackend', 'getId'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $attribute->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode);
+ $entity = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
+ ->setMethods(['getLinkField'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $attribute->expects($this->once())->method('getEntity')->willReturn($entity);
+ $entity->expects($this->once())->method('getLinkField')->willReturn('entity_id');
+ $select = $this->getMockBuilder('Magento\Framework\DB\Select')
+ ->setMethods(['joinLeft', 'getConnection', 'order'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $collection->expects($this->any())->method('getSelect')->willReturn($select);
+ $select->expects($this->any())->method('joinLeft')->willReturnSelf();
+ $backend = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend')
+ ->setMethods(['getTable'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ $attribute->expects($this->any())->method('getBackend')->willReturn($backend);
+ $backend->expects($this->any())->method('getTable')->willReturn('table_name');
+ $attribute->expects($this->any())->method('getId')->willReturn(1);
+ $collection->expects($this->once())->method('getStoreId')->willReturn(1);
+ $connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $expr = $this->getMockBuilder('Zend_Db_Expr')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $connection->expects($this->once())->method('getCheckSql')->willReturn($expr);
+ $select->expects($this->once())->method('getConnection')->willReturn($connection);
+ $attrOption = $this->getMockBuilder('Magento\Eav\Model\ResourceModel\Entity\Attribute\Option')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->attrOptionFactory->expects($this->once())->method('create')->willReturn($attrOption);
+ $attrOption->expects($this->once())->method('addOptionValueToCollection')->with($collection, $attribute, $expr)
+ ->willReturnSelf();
+ $select->expects($this->once())->method('order')->with("{$attributeCode} {$dir}");
+
+ $this->model->setAttribute($attribute);
+ $this->assertEquals($this->model, $this->model->addValueSortToCollection($collection, $dir));
+ }
}
diff --git a/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/Edit/Tab/Googleoptimizer.php b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/Edit/Tab/Googleoptimizer.php
index bf903745f9fb8..be1ead2238080 100644
--- a/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/Edit/Tab/Googleoptimizer.php
+++ b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/Edit/Tab/Googleoptimizer.php
@@ -7,6 +7,9 @@
*/
namespace Magento\GoogleOptimizer\Block\Adminhtml\Cms\Page\Edit\Tab;
+/**
+ * @deprecated
+ */
class Googleoptimizer extends \Magento\GoogleOptimizer\Block\Adminhtml\AbstractTab
{
/**
diff --git a/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/EntityCmsPage.php b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/EntityCmsPage.php
new file mode 100644
index 0000000000000..6d4c96172d164
--- /dev/null
+++ b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Cms/Page/EntityCmsPage.php
@@ -0,0 +1,81 @@
+coreRegistry = $registry;
+ $this->codeModel = $code;
+ parent::__construct($data);
+ }
+
+ /**
+ * Returns Code Model
+ *
+ * @return GoogleOptimizerCode|null
+ * @throws NoSuchEntityException
+ */
+ public function getCode()
+ {
+ $code = null;
+ $entity = $this->getEntity();
+ if ($entity->getId()) {
+ $this->codeModel->loadByEntityIdAndType($entity->getId(), GoogleOptimizerCode::ENTITY_TYPE_PAGE);
+ $code = $this->codeModel;
+ }
+ return $code;
+ }
+
+ /**
+ * Retrieves Google Optimizer binded entity
+ *
+ * @return \Magento\Cms\Model\Page|mixed
+ * @throws NoSuchEntityException
+ */
+ private function getEntity()
+ {
+ if (!$this->entity) {
+ $this->entity = $this->coreRegistry->registry('cms_page');
+ if (!$this->entity) {
+ throw new NoSuchEntityException();
+ }
+ }
+ return $this->entity;
+ }
+}
diff --git a/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php
new file mode 100644
index 0000000000000..40a50e3c87e69
--- /dev/null
+++ b/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php
@@ -0,0 +1,63 @@
+formHelper = $formHelper;
+ $this->setForm($formFactory->create());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function _prepareForm()
+ {
+ $entityClass = $this->getData('code-entity');
+ $formName = $this->getData('form-name');
+ if (!$entityClass) {
+ throw new ConfigurationMismatchException(__('Data key is missing: %1', ['code-entity']));
+ }
+ if (!$formName) {
+ throw new ConfigurationMismatchException(__('Data key is missing: %1', ['form-name']));
+ }
+
+ $entity = ObjectManager::getInstance()->create($entityClass);
+
+ $this->formHelper->addGoogleoptimizerFields($this->getForm(), $entity->getCode(), $formName);
+ $this->getForm()->getElement('googleoptimizer_fields')->setData(['legend' => null]);
+ return parent::_prepareForm();
+ }
+}
diff --git a/app/code/Magento/GoogleOptimizer/Model/Plugin/Cms/Page/DataProvider.php b/app/code/Magento/GoogleOptimizer/Model/Plugin/Cms/Page/DataProvider.php
new file mode 100644
index 0000000000000..26fd70e747417
--- /dev/null
+++ b/app/code/Magento/GoogleOptimizer/Model/Plugin/Cms/Page/DataProvider.php
@@ -0,0 +1,40 @@
+helper = $helper;
+ }
+
+ /**
+ * @param \Magento\Cms\Model\Page\DataProvider $subject
+ * @param array $result
+ * @return mixed
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterPrepareMeta(\Magento\Cms\Model\Page\DataProvider $subject, $result)
+ {
+ $result['page_view_optimization']['arguments']['data']['disabled'] = !$this->helper->isGoogleExperimentActive();
+ $result['page_view_optimization']['arguments']['data']['config']['componentType'] =
+ \Magento\Ui\Component\Form\Fieldset::NAME;
+ $result['page_view_optimization']['arguments']['data']['config']['label'] = __('Page View Optimization');
+ return $result;
+ }
+}
diff --git a/app/code/Magento/GoogleOptimizer/etc/adminhtml/di.xml b/app/code/Magento/GoogleOptimizer/etc/adminhtml/di.xml
index 1b7aa152f6ed6..af6326d312ff9 100644
--- a/app/code/Magento/GoogleOptimizer/etc/adminhtml/di.xml
+++ b/app/code/Magento/GoogleOptimizer/etc/adminhtml/di.xml
@@ -16,6 +16,17 @@
+
+
+
+ - Magento\GoogleOptimizer\Block\Adminhtml\Cms\Page\EntityCmsPage
+ - cms_page_form
+
+
+
+
+
+
diff --git a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml
new file mode 100644
index 0000000000000..c27ea723a0570
--- /dev/null
+++ b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml
@@ -0,0 +1,28 @@
+
+
+
diff --git a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php
index 35bda74df5237..262b773165b85 100644
--- a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php
+++ b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php
@@ -89,8 +89,9 @@ public function addError(
/** @var ProcessingError $newError */
$newError = $this->errorFactory->create();
$newError->init($errorCode, $errorLevel, $rowNumber, $columnName, $errorMessage, $errorDescription);
- $this->items[] = $newError;
-
+ $this->items['rows'][$rowNumber][] = $newError;
+ $this->items['codes'][$errorCode][] = $newError;
+ $this->items['messages'][$errorMessage][] = $newError;
return $this;
}
@@ -209,13 +210,21 @@ public function hasFatalExceptions()
return (bool)$this->getErrorsCount([ProcessingError::ERROR_LEVEL_CRITICAL]);
}
-
/**
* @return ProcessingError[]
*/
public function getAllErrors()
{
- return $this->items;
+ $result = [];
+ if (empty($this->items)) {
+ return $result;
+ }
+
+ foreach (array_values($this->items['rows']) as $errors) {
+ $result = array_merge($result, $errors);
+ }
+
+ return $result;
}
/**
@@ -225,9 +234,9 @@ public function getAllErrors()
public function getErrorsByCode(array $codes)
{
$result = [];
- foreach ($this->items as $error) {
- if (in_array($error->getErrorCode(), $codes)) {
- $result[] = $error;
+ foreach ($codes as $code) {
+ if (isset($this->items['codes'][$code])) {
+ $result = array_merge($result, $this->items['codes'][$code]);
}
}
@@ -241,10 +250,8 @@ public function getErrorsByCode(array $codes)
public function getErrorByRowNumber($rowNumber)
{
$result = [];
- foreach ($this->items as $error) {
- if ($error->getRowNumber() == (int)$rowNumber) {
- $result[] = $error;
- }
+ if (isset($this->items['rows'][$rowNumber])) {
+ $result = $this->items['rows'][$rowNumber];
}
return $result;
@@ -261,16 +268,26 @@ public function getRowsGroupedByErrorCode(
array $excludedCodes = [],
$replaceCodeWithMessage = true
) {
+ if (empty($this->items)) {
+ return [];
+ }
+ $allCodes = array_keys($this->items['codes']);
+ if (!empty($excludedCodes)) {
+ $allCodes = array_diff($allCodes, $excludedCodes);
+ }
+ if (!empty($errorCode)) {
+ $allCodes = array_intersect($errorCode, $allCodes);
+ }
+
$result = [];
- foreach ($this->items as $error) {
- if ((!empty($errorCode) && in_array($error->getErrorCode(), $errorCode))
- || in_array($error->getErrorCode(), $excludedCodes)
- ) {
- continue;
+ foreach ($allCodes as $code) {
+ $errors = $this->getErrorsByCode([$code]);
+ foreach ($errors as $error) {
+ $key = $replaceCodeWithMessage ? $error->getErrorMessage() : $code;
+ $result[$key][] = $error->getRowNumber() + 1;
}
- $message = $replaceCodeWithMessage ? $error->getErrorMessage() : $error->getErrorCode();
- $result[$message][] = $error->getRowNumber()+1;
}
+
return $result;
}
diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ErrorProcessing/ProcessingErrorAggregatorTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ErrorProcessing/ProcessingErrorAggregatorTest.php
index 3a534ce5adcf8..f8859da4f6f8a 100644
--- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ErrorProcessing/ProcessingErrorAggregatorTest.php
+++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ErrorProcessing/ProcessingErrorAggregatorTest.php
@@ -117,10 +117,7 @@ public function testAddErrorMessageTemplate()
$this->model->addError('columnNotFound', 'critical', 7, 'Some column name', null, 'Description');
$this->model->addError('columnEmptyHeader', 'not-critical', 4, 'Some column name', 'No header', 'Description');
$result = $this->model->getRowsGroupedByErrorCode(['systemException']);
- $expectedResult = [
- 'Template: No column' => [8],
- 'No header' => [5]
- ];
+ $expectedResult = ['systemException' => [0 => 1]];
$this->assertEquals($expectedResult, $result);
}
@@ -348,20 +345,73 @@ public function testGetErrorsByCodeNotInArray()
/**
* Test for method getRowsGroupedByErrorCode. Expects errors.
+ *
+ * @param array $params
+ * @param array $expectedResult
+ *
+ * @dataProvider getRowsGroupedByErrorCodeWithErrorsDataProvider
*/
- public function testGetRowsGroupedByErrorCodeWithErrors()
+ public function testGetRowsGroupedByErrorCodeWithErrors(array $params = [], array $expectedResult = [])
{
$this->model->addError('systemException');
$this->model->addError('columnNotFound', 'critical', 7, 'Some column name', 'No column', 'Description');
$this->model->addError('columnEmptyHeader', 'not-critical', 4, 'Some column name', 'No header', 'Description');
- $result = $this->model->getRowsGroupedByErrorCode(['systemException']);
- $expectedResult = [
- 'No column' => [8],
- 'No header' => [5]
- ];
+
+ $result = call_user_func_array([$this->model, 'getRowsGroupedByErrorCode'], $params);
+
$this->assertEquals($expectedResult, $result);
}
+ /**
+ * @return array
+ */
+ public function getRowsGroupedByErrorCodeWithErrorsDataProvider()
+ {
+ $errorCode1 = 'systemException';
+ $errorCode2 = 'columnNotFound';
+ $errorCode3 = 'columnEmptyHeader';
+
+ $message1 = 'systemException';
+ $message2 = 'No column';
+ $message3 = 'No header';
+
+ return [
+ [
+ [[$errorCode1]],
+ [$message1 => [1]]
+ ],
+ [
+ [[], [$errorCode2]],
+ [$message1 => [1], $message3 => [5]]
+ ],
+ [
+ [[$errorCode3, $errorCode2], [$errorCode2]],
+ [$message3 => [5]]
+ ],
+ [
+ [[], []],
+ [$message1 => [1], $message2 => [8], $message3 => [5]]
+ ],
+
+ [
+ [[$errorCode1], [], false],
+ [$errorCode1 => [1]]
+ ],
+ [
+ [[], [$errorCode2], false],
+ [$errorCode1 => [1], $errorCode3 => [5]]
+ ],
+ [
+ [[$errorCode3, $errorCode2], [$errorCode2], false],
+ [$errorCode3 => [5]]
+ ],
+ [
+ [[], [], false],
+ [$errorCode1 => [1], $errorCode2 => [8], $errorCode3 => [5]]
+ ],
+ ];
+ }
+
/**
* Test for method getRowsGroupedByErrorCode. Unexpects errors.
*/
diff --git a/app/code/Magento/Rss/view/frontend/templates/feeds.phtml b/app/code/Magento/Rss/view/frontend/templates/feeds.phtml
index 86211e9977d7b..81ac6fd803259 100644
--- a/app/code/Magento/Rss/view/frontend/templates/feeds.phtml
+++ b/app/code/Magento/Rss/view/frontend/templates/feeds.phtml
@@ -14,7 +14,7 @@
getFeeds() as $feed): ?>
- |
+ escapeHtml($feed['label']) ?> |
|
@@ -23,7 +23,7 @@
|
- |
+ escapeHtml($item['label']) ?> |
|
diff --git a/app/code/Magento/Swatches/Block/Product/Renderer/Configurable.php b/app/code/Magento/Swatches/Block/Product/Renderer/Configurable.php
index 0d06c0176980a..4546a01529d33 100644
--- a/app/code/Magento/Swatches/Block/Product/Renderer/Configurable.php
+++ b/app/code/Magento/Swatches/Block/Product/Renderer/Configurable.php
@@ -404,7 +404,7 @@ protected function getHtmlOutput()
*/
public function getMediaCallback()
{
- return $this->getBaseUrl() . self::MEDIA_CALLBACK_ACTION;
+ return $this->getUrl(self::MEDIA_CALLBACK_ACTION, ['_secure' => $this->getRequest()->isSecure()]);
}
/**
diff --git a/app/code/Magento/Swatches/Model/Plugin/Configurable.php b/app/code/Magento/Swatches/Model/Plugin/Configurable.php
new file mode 100644
index 0000000000000..05a575b820816
--- /dev/null
+++ b/app/code/Magento/Swatches/Model/Plugin/Configurable.php
@@ -0,0 +1,61 @@
+eavConfig = $eavConfig;
+ $this->swatchHelper = $swatchHelper;
+ }
+
+ /**
+ * Returns Configurable Products Collection with added swatch attributes
+ *
+ * @param ConfigurableProduct $subject
+ * @param Collection $result
+ * @return Collection
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterGetUsedProductCollection(
+ ConfigurableProductType $subject,
+ Collection $result
+ ) {
+ $attributeCodes = ['image'];
+ $entityType = $result->getEntity()->getType();
+
+ foreach ($this->eavConfig->getEntityAttributeCodes($entityType) as $code) {
+ $attribute = $this->eavConfig->getAttribute($entityType, $code);
+ if ($this->swatchHelper->isVisualSwatch($attribute) || $this->swatchHelper->isTextSwatch($attribute)) {
+ $attributeCodes[] = $code;
+ }
+ }
+ $result->addAttributeToSelect($attributeCodes);
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/ConfigurableTest.php
index e32e263391cb1..44ea9663bc86c 100644
--- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/ConfigurableTest.php
+++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/ConfigurableTest.php
@@ -323,7 +323,13 @@ public function testGetJsonSwatchConfigWithoutVisualImageType()
public function testGetMediaCallback()
{
- $this->urlBuilder->expects($this->once())->method('getBaseUrl')->willReturn('http://magento.com/');
- $this->assertContains(Configurable::MEDIA_CALLBACK_ACTION, $this->configurable->getMediaCallback());
+ $url = 'http://localhost/' . Configurable::MEDIA_CALLBACK_ACTION;
+
+ $this->urlBuilder->expects($this->once())
+ ->method('getUrl')
+ ->with(Configurable::MEDIA_CALLBACK_ACTION)
+ ->willReturn($url);
+
+ $this->assertEquals($url, $this->configurable->getMediaCallback());
}
}
diff --git a/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ConfigurableTest.php
new file mode 100644
index 0000000000000..f4a657b453c57
--- /dev/null
+++ b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ConfigurableTest.php
@@ -0,0 +1,86 @@
+eavConfig = $this->getMock(
+ '\Magento\Eav\Model\Config',
+ ['getEntityAttributeCodes', 'getAttribute'],
+ [],
+ '',
+ false
+ );
+ $this->swatchHelper = $this->getMock(
+ '\Magento\Swatches\Helper\Data',
+ ['isVisualSwatch', 'isTextSwatch'],
+ [],
+ '',
+ false
+ );
+
+ $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ $this->pluginModel = $objectManager->getObject(
+ '\Magento\Swatches\Model\Plugin\Configurable',
+ [
+ 'eavConfig' => $this->eavConfig,
+ 'swatchHelper' => $this->swatchHelper,
+ ]
+ );
+ }
+
+ public function testAfterGetUsedProductCollection()
+ {
+ $subject = $this->getMock('\Magento\ConfigurableProduct\Model\Product\Type\Configurable', [], [], '', false);
+ $result = $this->getMock(
+ '\Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection',
+ ['getEntity', 'addAttributeToSelect'],
+ [],
+ '',
+ false
+ );
+
+ $collectionEntity = $this->getMock(
+ '\Magento\Eav\Model\Entity\Collection\AbstractCollection',
+ ['getType'],
+ [],
+ '',
+ false
+ );
+ $collectionEntity->expects($this->once())->method('getType')->willReturn('catalog');
+ $result->expects($this->once())->method('getEntity')->willReturn($collectionEntity);
+
+ $attribute = $this->getMock('\Magento\Catalog\Model\ResourceModel\Eav\Attribute', [], [], '', false);
+
+ $this->eavConfig->expects($this->once())->method('getEntityAttributeCodes')->with('catalog')
+ ->willReturn(['size', 'color', 'swatch1']);
+
+ $this->eavConfig->expects($this->exactly(3))->method('getAttribute')->willReturn($attribute);
+
+ $this->swatchHelper->expects($this->exactly(3))->method('isVisualSwatch')->with($attribute)->willReturn(true);
+
+ $result->expects($this->once())->method('addAttributeToSelect')
+ ->with($this->identicalTo(['image', 'size', 'color', 'swatch1']))->willReturn($result);
+
+ $result = $this->pluginModel->afterGetUsedProductCollection($subject, $result);
+ $this->assertInstanceOf(
+ '\Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection',
+ $result
+ );
+ }
+}
diff --git a/app/code/Magento/Swatches/etc/di.xml b/app/code/Magento/Swatches/etc/di.xml
index f73753acfb714..f91a525777606 100644
--- a/app/code/Magento/Swatches/etc/di.xml
+++ b/app/code/Magento/Swatches/etc/di.xml
@@ -18,6 +18,9 @@
+
+
+
diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js
index e3e7ccb848782..17f52b5d5f68f 100644
--- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js
+++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js
@@ -106,14 +106,6 @@ define([
this.backendType.val('int');
}
- if (this.frontendInput.is(':visible') &&
- (this.frontendInput.val() === 'swatch_text' || this.frontendInput.val() === 'swatch_visual')
- ) {
- this.usedInProductListing.val(1);
- this.isVisibleOnFront.val(1);
- this.updateProductPreviewImage.val(1);
- }
-
if (this.frontendInput.val() === 'multiselect' ||
this.frontendInput.val() === 'gallery' ||
this.frontendInput.val() === 'textarea'
diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml
index 5f26d947a5d4f..2b3c9f148360f 100644
--- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml
+++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml
@@ -69,7 +69,7 @@