From 4b971f731d007d4095a9567e06b3b511c244386a Mon Sep 17 00:00:00 2001 From: Alex Bomko Date: Wed, 14 Oct 2015 18:18:04 +0300 Subject: [PATCH 01/23] MAGETWO-43956: The "configurable_variations" column is absent in exported file --- .../BundleImportExport/Model/Export/RowCustomizer.php | 5 +++-- .../ConfigurableImportExport/Model/Export/RowCustomizer.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php index 5c8f89c8982d9..c200731842364 100644 --- a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php @@ -95,7 +95,8 @@ class RowCustomizer implements RowCustomizerInterface */ public function prepareData($collection, $productIds) { - $collection->addAttributeToFilter( + $productCollection = clone $collection; + $productCollection->addAttributeToFilter( 'entity_id', ['in' => $productIds] )->addAttributeToFilter( @@ -103,7 +104,7 @@ public function prepareData($collection, $productIds) ['eq' => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE] ); - return $this->populateBundleData($collection); + return $this->populateBundleData($productCollection); } /** diff --git a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php index 4405feba18426..2ed091296f13d 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php @@ -24,7 +24,8 @@ class RowCustomizer implements RowCustomizerInterface */ public function prepareData($collection, $productIds) { - $collection->addAttributeToFilter( + $productCollection = clone $collection; + $productCollection->addAttributeToFilter( 'entity_id', ['in' => $productIds] )->addAttributeToFilter( @@ -32,7 +33,7 @@ public function prepareData($collection, $productIds) ['eq' => \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE] ); - while ($product = $collection->fetchItem()) { + while ($product = $productCollection->fetchItem()) { $productAttributesOptions = $product->getTypeInstance()->getConfigurableOptions($product); foreach ($productAttributesOptions as $productAttributeOption) { From 5e89cdb71137f1ad02547f334bff32181a0b189e Mon Sep 17 00:00:00 2001 From: Alex Bomko Date: Wed, 14 Oct 2015 22:35:14 +0300 Subject: [PATCH 02/23] MAGETWO-43956: The configurable_variations column is absent in exported file --- .../Model/Export/RowCustomizer.php | 2 +- .../Model/Export/RowCustomizer/Composite.php | 2 +- .../Model/Export/RowCustomizerInterface.php | 2 +- .../Model/Export/RowCustomizer.php | 2 +- .../Model/Export/RowCustomizerTest.php | 48 +++++++++++++++++++ .../Model/Export/RowCustomizerTest.php | 48 +++++++++++++++++++ 6 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Export/RowCustomizerTest.php diff --git a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php index c200731842364..1bf95ba4ea861 100644 --- a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php @@ -90,7 +90,7 @@ class RowCustomizer implements RowCustomizerInterface * Prepare data for export * * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection - * @param int $productIds + * @param int[] $productIds * @return $this */ public function prepareData($collection, $productIds) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php index 1997d39b47efc..ab96bf9f3545f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php @@ -34,7 +34,7 @@ public function __construct(ObjectManagerInterface $objectManager, $customizers * Prepare data for export * * @param mixed $collection - * @param int $productIds + * @param int[] $productIds * @return mixed|void */ public function prepareData($collection, $productIds) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php index 6723dbc24afe1..240284ed32018 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php @@ -14,7 +14,7 @@ interface RowCustomizerInterface * Prepare data for export * * @param mixed $collection - * @param int $productIds + * @param int[] $productIds * @return mixed */ public function prepareData($collection, $productIds); diff --git a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php index 2ed091296f13d..a14abd1037ae1 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php @@ -19,7 +19,7 @@ class RowCustomizer implements RowCustomizerInterface * Prepare configurable data for export * * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection - * @param int $productIds + * @param int[] $productIds * @return void */ public function prepareData($collection, $productIds) diff --git a/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php new file mode 100644 index 0000000000000..c5adb5a6bd039 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php @@ -0,0 +1,48 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->model = $this->objectManager->create( + 'Magento\BundleImportExport\Model\Export\RowCustomizer' + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product.php + */ + public function testPrepareData() + { + $collection = $this->objectManager->get('Magento\Catalog\Model\ResourceModel\Product\Collection'); + $select = (string)$collection->getSelect(); + $this->model->prepareData($collection, [1, 2, 3, 4]); + $this->assertEquals($select, (string)$collection->getSelect()); + $result = $this->model->addData([], 3); + $this->assertArrayHasKey('bundle_price_type', $result); + $this->assertArrayHasKey('bundle_sku_type', $result); + $this->assertArrayHasKey('bundle_price_view', $result); + $this->assertArrayHasKey('bundle_weight_type', $result); + $this->assertArrayHasKey('bundle_values', $result); + $this->assertContains('sku=simple,', $result['bundle_values']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Export/RowCustomizerTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Export/RowCustomizerTest.php new file mode 100644 index 0000000000000..9dc933734fd5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Export/RowCustomizerTest.php @@ -0,0 +1,48 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->model = $this->objectManager->create( + 'Magento\ConfigurableImportExport\Model\Export\RowCustomizer' + ); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testPrepareData() + { + $collection = $this->objectManager->get('Magento\Catalog\Model\ResourceModel\Product\Collection'); + $select = (string)$collection->getSelect(); + $this->model->prepareData($collection, [1, 2, 3, 4]); + $this->assertEquals($select, (string)$collection->getSelect()); + $result = $this->model->addData([], 1); + $this->assertArrayHasKey('configurable_variations', $result); + $this->assertArrayHasKey('configurable_variation_labels', $result); + $this->assertEquals( + 'sku=simple_10,test_configurable=Option 1|sku=simple_20,test_configurable=Option 2', + $result['configurable_variations'] + ); + } +} From 425a511df3d44f24a5148d25480be49fc429e734 Mon Sep 17 00:00:00 2001 From: Alex Bomko Date: Wed, 14 Oct 2015 21:34:11 +0300 Subject: [PATCH 03/23] MAGETWO-44026: Fatal Error on Product Reviews Report when Ratings have not been assigned to Store --- .../Review/Product/Collection.php | 7 ++-- .../Review/Product/CollectionTest.php | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Product/CollectionTest.php diff --git a/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php index 9822196904997..662047abeca66 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php @@ -58,8 +58,7 @@ protected function _joinReview() $this->getConnection()->quoteInto('table_rating.store_id > ?', 0), ]; - $percentField = $this->getConnection()->quoteIdentifier('table_rating.percent'); - $sumPercentField = new \Zend_Db_Expr("SUM({$percentField})"); + $sumPercentField = new \Zend_Db_Expr("SUM(table_rating.percent)"); $sumPercentApproved = new \Zend_Db_Expr('SUM(table_rating.percent_approved)'); $countRatingId = new \Zend_Db_Expr('COUNT(table_rating.rating_id)'); @@ -67,8 +66,8 @@ protected function _joinReview() ['table_rating' => $this->getTable('rating_option_vote_aggregated')], implode(' AND ', $joinCondition), [ - 'avg_rating' => sprintf('%s/%s', $sumPercentField, $countRatingId), - 'avg_rating_approved' => sprintf('%s/%s', $sumPercentApproved, $countRatingId) + 'avg_rating' => new \Zend_Db_Expr(sprintf('%s/%s', $sumPercentField, $countRatingId)), + 'avg_rating_approved' => new \Zend_Db_Expr(sprintf('%s/%s', $sumPercentApproved, $countRatingId)) ] ); diff --git a/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Product/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Product/CollectionTest.php new file mode 100644 index 0000000000000..d8c0eddd7ec59 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Product/CollectionTest.php @@ -0,0 +1,34 @@ +_collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Reports\Model\ResourceModel\Review\Product\Collection' + ); + } + + public function testGetSelect() + { + $select = (string)$this->_collection->getSelect(); + $search = '/SUM\(table_rating.percent\)\/COUNT\(table_rating.rating_id\) AS `avg_rating`' + . '[\s\S]+SUM\(table_rating.percent_approved\)\/COUNT\(table_rating.rating_id\) AS `avg_rating_approved`' + . '[\s\S]+LEFT JOIN `.*rating_option_vote_aggregated` AS `table_rating`/'; + + $this->assertRegExp($search, $select); + } +} From 405dd8cbe911673974f90e3d0c5162628b4fc29b Mon Sep 17 00:00:00 2001 From: Alex Bomko Date: Wed, 14 Oct 2015 23:41:30 +0300 Subject: [PATCH 04/23] MAGETWO-44009: Fatal error occurs when user opens scheduled import section with removed products-import-export module --- .../Model/Export/RowCustomizer.php | 15 +++---- .../Model/Export/Product.php | 17 ++++---- .../Model/Import/Product.php | 40 +++++++++---------- .../Test/Unit/Model/Import/ProductTest.php | 3 +- .../Model/Export/RowCustomizer.php | 7 ++-- .../Unit/Model/Export/RowCustomizerTest.php | 12 +++--- .../Model/Import/Product/Type/Grouped.php | 3 +- .../Block/Adminhtml/Import/Edit/Form.php | 3 +- .../Magento/ImportExport/Model/Import.php | 5 +++ 9 files changed, 57 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php index 5c8f89c8982d9..ffb475c57694c 100644 --- a/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php @@ -10,6 +10,7 @@ use Magento\CatalogImportExport\Model\Import\Product as ImportProductModel; use Magento\Bundle\Model\ResourceModel\Selection\Collection as SelectionCollection; use Magento\ImportExport\Controller\Adminhtml\Import; +use Magento\ImportExport\Model\Import as ImportModel; /** * Class RowCustomizer @@ -214,9 +215,9 @@ protected function getFormattedBundleSelections($optionValues, SelectionCollecti 'price_type' => $this->getPriceTypeValue($selection->getSelectionPriceType()) ]; $bundleData .= $optionValues - . ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . implode( - ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, + ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, array_map( function ($value, $key) { return $key . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $value; @@ -240,9 +241,9 @@ function ($value, $key) { protected function getFormattedOptionValues($option) { return 'name' . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR - . $option->getTitle() . ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . $option->getTitle() . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . 'type' . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR - . $option->getType() . ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . $option->getType() . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . 'required' . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $option->getRequired(); } @@ -290,7 +291,7 @@ protected function cleanNotBundleAdditionalAttributes($dataRow) { if (!empty($dataRow['additional_attributes'])) { $additionalAttributes = explode( - ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, + ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $dataRow['additional_attributes'] ); $dataRow['additional_attributes'] = $this->getNotBundleAttributes($additionalAttributes); @@ -314,10 +315,10 @@ protected function getNotBundleAttributes($additionalAttributes) $cleanedAdditionalAttributes .= $attributeCode . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $attributeValue - . ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; + . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; } } - return rtrim($cleanedAdditionalAttributes, ImportProductModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR); + return rtrim($cleanedAdditionalAttributes, ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR); } } diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 5ba8ed055cd25..23001345137e3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -5,6 +5,7 @@ */ namespace Magento\CatalogImportExport\Model\Export; +use Magento\ImportExport\Model\Import; use \Magento\Store\Model\Store; use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct; @@ -901,7 +902,7 @@ protected function collectRawData() if (!empty($additionalAttributes)) { $data[$itemId][$storeId][self::COL_ADDITIONAL_ATTRIBUTES] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalAttributes); + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalAttributes); } else { unset($data[$itemId][$storeId][self::COL_ADDITIONAL_ATTRIBUTES]); } @@ -981,7 +982,7 @@ protected function hasMultiselectData($item, $storeId) protected function collectMultiselectValues($item, $attrCode, $storeId) { $attrValue = $item->getData($attrCode); - $optionIds = explode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $attrValue); + $optionIds = explode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $attrValue); $options = array_intersect_key( $this->_attributeValues[$attrCode], array_flip($optionIds) @@ -1041,7 +1042,7 @@ protected function addMultirowData($dataRow, $multiRawData) $websiteCodes[] = $this->_websiteIdToCode[$productWebsite]; } $dataRow['_product_websites'] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $websiteCodes); + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $websiteCodes); $multiRawData['rowWebsites'][$productId] = []; } if (!empty($multiRawData['mediaGalery'][$productId])) { @@ -1052,9 +1053,9 @@ protected function addMultirowData($dataRow, $multiRawData) $additionalImageLabels[] = $mediaItem['_media_label']; } $dataRow['additional_images'] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImages); + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImages); $dataRow['additional_image_labels'] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageLabels); + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageLabels); $multiRawData['mediaGalery'][$productId] = []; } foreach ($this->_linkTypeProvider->getLinkTypes() as $linkTypeName => $linkId) { @@ -1074,7 +1075,7 @@ protected function addMultirowData($dataRow, $multiRawData) $multiRawData['linksRows'][$productId][$linkId] = []; asort($associations); $dataRow[$colPrefix . 'skus'] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, array_keys($associations)); + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, array_keys($associations)); } } $dataRow = $this->rowCustomizer->addData($dataRow, $productId); @@ -1085,7 +1086,7 @@ protected function addMultirowData($dataRow, $multiRawData) foreach (array_keys($this->collectedMultiselectsData[$storeId][$productId]) as $attrKey) { if (!empty($this->collectedMultiselectsData[$storeId][$productId][$attrKey])) { $dataRow[$attrKey] = implode( - ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, + Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $this->collectedMultiselectsData[$storeId][$productId][$attrKey] ); } @@ -1161,7 +1162,7 @@ protected function optionRowToCellString($option) $result[] = $key . ImportProduct::PAIR_NAME_VALUE_SEPARATOR . $value; } - return implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $result); + return implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $result); } /** diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 1e8fcbc4aa07b..8d19881ef2ce7 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -13,6 +13,7 @@ use Magento\Framework\Model\ModelResource\Db\TransactionManagerInterface; use Magento\Framework\Model\ModelResource\Db\ObjectRelationProcessor; use Magento\Framework\Stdlib\DateTime; +use Magento\ImportExport\Model\Import; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; @@ -36,11 +37,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ const ATTRIBUTE_DELETE_BUNCH = 1000; - /** - * default delimiter for several values in one cell - */ - const DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR = ','; - /** * Pseudo multi line separator in one cell. * @@ -727,10 +723,10 @@ public function getOptionEntity() */ public function getMultipleValueSeparator() { - if (!empty($this->_parameters[\Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR])) { - return $this->_parameters[\Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR]; + if (!empty($this->_parameters[Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR])) { + return $this->_parameters[Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR]; } - return self::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; + return Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; } /** @@ -781,7 +777,7 @@ public function setParameters(array $params) */ public function deleteProductsForReplacement() { - $this->setParameters(array('behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE)); + $this->setParameters(array('behavior' => Import::BEHAVIOR_DELETE)); $this->_deleteProducts(); return $this; @@ -837,9 +833,9 @@ protected function _deleteProducts() protected function _importData() { $this->_validatedRows = null; - if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { + if (Import::BEHAVIOR_DELETE == $this->getBehavior()) { $this->_deleteProducts(); - } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $this->getBehavior()) { + } elseif (Import::BEHAVIOR_REPLACE == $this->getBehavior()) { $this->_replaceFlag = true; $this->_replaceProducts(); } else { @@ -859,7 +855,7 @@ protected function _replaceProducts() $this->deleteProductsForReplacement(); $this->_oldSku = $this->skuProcessor->reloadOldSkus()->getOldSkus(); $this->_validatedRows = null; - $this->setParameters(array('behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND)); + $this->setParameters(array('behavior' => Import::BEHAVIOR_APPEND)); $this->_saveProductsData(); return $this; @@ -975,7 +971,7 @@ protected function _prepareRowForDb(array $rowData) static $lastSku = null; - if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { + if (Import::BEHAVIOR_DELETE == $this->getBehavior()) { return $rowData; } @@ -1092,7 +1088,7 @@ protected function _saveLinks() } } } - if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior() && $productIds) { + if (Import::BEHAVIOR_APPEND != $this->getBehavior() && $productIds) { $this->_connection->delete( $mainTable, $this->_connection->quoteInto('product_id IN (?)', array_unique($productIds)) @@ -1186,7 +1182,7 @@ protected function _saveProductCategories(array $categoriesData) $categoriesIn[] = ['product_id' => $productId, 'category_id' => $categoryId, 'position' => 1]; } } - if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { + if (Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->_connection->delete( $tableName, $this->_connection->quoteInto('product_id IN (?)', $delProductId) @@ -1547,7 +1543,7 @@ protected function _saveProducts() $this->taxClassProcessor->upsertTaxClass($rowData['tax_class_name'], $productTypeModel); } - if ($this->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND || + if ($this->getBehavior() == Import::BEHAVIOR_APPEND || empty($rowData[self::COL_SKU]) ) { $rowData = $productTypeModel->clearEmptyData($rowData); @@ -1678,7 +1674,7 @@ protected function _saveProductTierPrices(array $tierPriceData) $tierPriceIn[] = $row; } } - if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { + if (Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->_connection->delete( $tableName, $this->_connection->quoteInto('entity_id IN (?)', $delProductId) @@ -1709,8 +1705,8 @@ protected function _getUploader() $DS = DIRECTORY_SEPARATOR; - if (!empty($this->_parameters[\Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR])) { - $tmpPath = $this->_parameters[\Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR]; + if (!empty($this->_parameters[Import::FIELD_NAME_IMG_FILE_DIR])) { + $tmpPath = $this->_parameters[Import::FIELD_NAME_IMG_FILE_DIR]; } else { $tmpPath = $dirAddon . $DS . $this->_mediaDirectory->getRelativePath('import'); } @@ -1790,7 +1786,7 @@ protected function _saveMediaGallery(array $mediaGalleryData) $productId = $this->skuProcessor->getNewSku($productSku)['entity_id']; $productIds[] = $productId; $insertedGalleryImgs = []; - if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { + if (Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->_connection->delete( $mediaGalleryTableName, $this->_connection->quoteInto('entity_id IN (?)', $productId) @@ -1881,7 +1877,7 @@ protected function _saveProductWebsites(array $websiteData) $websitesData[] = ['product_id' => $productId, 'website_id' => $websiteId]; } } - if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { + if (Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->_connection->delete( $tableName, $this->_connection->quoteInto('product_id IN (?)', $delProductId) @@ -2084,7 +2080,7 @@ public function validateRow(array $rowData, $rowNum) $rowScope = $this->getRowScope($rowData); // BEHAVIOR_DELETE use specific validation logic - if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { + if (Import::BEHAVIOR_DELETE == $this->getBehavior()) { if (self::SCOPE_DEFAULT == $rowScope && !isset($this->_oldSku[$rowData[self::COL_SKU]])) { $this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum); return false; diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php index 6c9f1f89ff535..b635405b79fd4 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php @@ -8,6 +8,7 @@ use Magento\CatalogImportExport\Model\Import\Product; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Stdlib\DateTime; +use Magento\ImportExport\Model\Import; /** * Class ProductTest @@ -567,7 +568,7 @@ public function testGetMultipleValueSeparatorDefault() { $this->setPropertyValue($this->importProduct, '_parameters', null); $this->assertEquals( - \Magento\CatalogImportExport\Model\Import\Product::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, + Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $this->importProduct->getMultipleValueSeparator() ); } diff --git a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php index 4405feba18426..1173cf0ce3964 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Export/RowCustomizer.php @@ -7,6 +7,7 @@ use Magento\CatalogImportExport\Model\Export\RowCustomizerInterface; use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct; +use Magento\ImportExport\Model\Import; class RowCustomizer implements RowCustomizerInterface { @@ -51,11 +52,11 @@ public function prepareData($collection, $productIds) foreach ($variations as $sku => $values) { $variations[$sku] = - 'sku=' . $sku . ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR - . implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $values); + 'sku=' . $sku . Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $values); } $variations = implode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $variations); - $variationsLabels = implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $variationsLabels); + $variationsLabels = implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $variationsLabels); $this->configurableData[$product->getId()] = [ 'configurable_variations' => $variations, diff --git a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Export/RowCustomizerTest.php b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Export/RowCustomizerTest.php index 65732d3df1df5..b067e19c38125 100644 --- a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Export/RowCustomizerTest.php +++ b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Export/RowCustomizerTest.php @@ -7,6 +7,7 @@ namespace Magento\ConfigurableImportExport\Test\Unit\Model\Export; use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct; +use Magento\ImportExport\Model\Import; class RowCustomizerTest extends \PHPUnit_Framework_TestCase { @@ -256,17 +257,17 @@ protected function getExpectedConfigurableData() return [ $this->initiatedProductId => [ 'configurable_variations' => implode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, [ - '_sku_' => 'sku=_sku_' . ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR - . implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ + '_sku_' => 'sku=_sku_' . Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ 'code_of_attribute=Option Title', 'code_of_attribute=Option Title', ]), - '_sku_2' => 'sku=_sku_2' . ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR - . implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ + '_sku_2' => 'sku=_sku_2' . Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR + . implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ 'code_of_attribute_2=Option Title 2', ]) ]), - 'configurable_variation_labels' => implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ + 'configurable_variation_labels' => implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, [ 'code_of_attribute' => 'code_of_attribute=Super attribute label', 'code_of_attribute_2' => 'code_of_attribute_2=Super attribute label 2', ]), @@ -291,6 +292,7 @@ protected function setPropertyValue(&$object, $property, $value) /** * @param $object * @param $property + * @return mixed */ protected function getPropertyValue(&$object, $property) { diff --git a/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php b/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php index 6bccd71831032..3185df16bdb3b 100644 --- a/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php @@ -8,6 +8,7 @@ namespace Magento\GroupedImportExport\Model\Import\Product\Type; use Magento\CatalogImportExport\Model\Import\Product; +use Magento\ImportExport\Model\Import; class Grouped extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { @@ -76,7 +77,7 @@ public function saveData() if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum) || empty($associatedSkusQty)) { continue; } - $associatedSkusAndQtyPairs = explode(Product::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $associatedSkusQty); + $associatedSkusAndQtyPairs = explode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $associatedSkusQty); $position = 0; foreach ($associatedSkusAndQtyPairs as $associatedSkuAndQty) { ++$position; diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php index 71f342b5b5857..1a8f446b1de5d 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php @@ -5,6 +5,7 @@ */ namespace Magento\ImportExport\Block\Adminhtml\Import\Edit; +use Magento\ImportExport\Model\Import; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; /** @@ -170,7 +171,7 @@ protected function _prepareForm() 'required' => true, 'disabled' => true, 'class' => $behaviorCode, - 'value' => ',', + 'value' => Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, ] ); } diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 3742d5e54f3e3..1d9984df7944d 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -80,6 +80,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel /**#@-*/ + /** + * default delimiter for several values in one cell as default for FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR + */ + const DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR = ','; + /**#@+ * Import constants */ From 4ec17e2bd241a455f1cf475949e2d4d16a468dc9 Mon Sep 17 00:00:00 2001 From: Alex Bomko Date: Thu, 15 Oct 2015 00:01:43 +0300 Subject: [PATCH 05/23] MAGETWO-44009: Fatal error occurs when user opens scheduled import section with removed products-import-export module --- .../Magento/Test/Legacy/_files/obsolete_constants.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php index 174f0004e29bd..72e5faf7de57e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php @@ -952,4 +952,9 @@ 'THEMES', 'Magento\Framework\App\Filesystem\DirectoryList' ], + [ + 'DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR', + 'Magento\CatalogImportExport\Model\Import\Product', + 'Magento\ImportExport\Model\Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR' + ] ]; From 99eb89be0ce15d8a1b6f808cf2a974c351ec7660 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Sun, 18 Oct 2015 14:53:47 +0300 Subject: [PATCH 06/23] MAGETWO-43953: Unable to import images when DocumentRoot is pub/index.php --- .../adminhtml/templates/widget/form/renderer/fieldset.phtml | 2 +- app/code/Magento/CatalogImportExport/Model/Import/Uploader.php | 2 +- .../view/adminhtml/templates/import/form/after.phtml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml index fedec572af962..41f6bf34afc8a 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml @@ -22,7 +22,7 @@ if (!isset($advancedLabel)) { $advancedLabel = __('Additional Settings'); } -$cssClass = ($isField) ? 'field ' . $element->getClass() : 'fieldset admin__fieldset' . $element->getClass(); +$cssClass = ($isField) ? 'field ' . $element->getClass() : 'fieldset admin__fieldset ' . $element->getClass(); if ($isField) { $count = $element->getCountBasicChildren(); diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index dc0263e99d4f0..f22d910ccd45e 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -223,7 +223,7 @@ protected function _validateFile() && method_exists($params['object'], $params['method']) && is_callable([$params['object'], $params['method']]) ) { - $params['object']->{$params['method']}($filePath); + $params['object']->{$params['method']}($this->_directory->getAbsolutePath($filePath)); } } } diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml index 73eacb73e7869..e363b6fe0d017 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml @@ -14,7 +14,7 @@
From 548c2921d61ccb98511ebe4c191b6f2b427d9019 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Sun, 25 Oct 2015 14:44:58 +0200 Subject: [PATCH 13/23] MAGETWO-39795: Check data for import product does not work MAGETWO-43900: Imported products with broken images link don't appear on front MAGETWO-43901: The "Imported resource (image) could not be downloaded" message appears when user tries to import products using "Replace" behavior MAGETWO-44238: Categories imported in a comma-separated format are not created properly MAGETWO-42245: _media_is_disabled is not exported MAGETWO-44407: CLONE - Product export and re-import with different store view level data causes data corruption --- .../Model/Export/Product.php | 10 +- .../Model/Import/Product.php | 65 ++++----- .../Model/Import/Product/Validator.php | 6 + .../Model/Import/Product/ValidatorTest.php | 126 ++++++++++++++++-- .../Files/Sample/catalog_product.csv | 15 +-- .../Model/Import/ProductTest.php | 62 +++++++-- ...import_new_categories_custom_separator.csv | 2 + ...mport_new_categories_default_separator.csv | 2 + 8 files changed, 216 insertions(+), 72 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 9dc79f6a3cf1b..b3f8a864758ea 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -638,7 +638,7 @@ protected function updateDataWithCategoryColumns(&$dataRow, &$rowCategories, $pr } $categories[] = $categoryPath; } - $dataRow[self::COL_CATEGORY] = implode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $categories); + $dataRow[self::COL_CATEGORY] = implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $categories); unset($rowCategories[$productId]); return true; @@ -683,7 +683,7 @@ protected function setHeaderColumns($customOptionsData, $stockItemRows) 'crosssell_skus', 'upsell_skus', ], - ['additional_images', 'additional_image_labels', 'hide_from_product_page'] + ['additional_images', 'additional_image_labels', 'hide_from_product_page'] ); // have we merge custom options columns if ($customOptionsData) { @@ -1047,7 +1047,7 @@ protected function addMultirowData($dataRow, $multiRawData) if (!empty($multiRawData['mediaGalery'][$productId])) { $additionalImages = []; $additionalImageLabels = []; - $additionalImageIsDisabled = []; + $additionalImageIsDisabled = []; foreach ($multiRawData['mediaGalery'][$productId] as $mediaItem) { $additionalImages[] = $mediaItem['_media_image']; $additionalImageLabels[] = $mediaItem['_media_label']; @@ -1060,8 +1060,8 @@ protected function addMultirowData($dataRow, $multiRawData) implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImages); $dataRow['additional_image_labels'] = implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageLabels); - $dataRow['hide_from_product_page'] = - implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageIsDisabled); + $dataRow['hide_from_product_page'] = + implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageIsDisabled); $multiRawData['mediaGalery'][$productId] = []; } foreach ($this->_linkTypeProvider->getLinkTypes() as $linkTypeName => $linkId) { diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index faaed58e2f708..2d6395a5f4c6a 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -710,18 +710,8 @@ public function isAttributeValid($attrCode, array $attrParams, array $rowData, $ } /** - * Retrieve instance of product custom options import entity * - * @return \Magento\CatalogImportExport\Model\Import\Product\Option - */ - public function getOptionEntity() - { - return $this->_optionEntity; - } - - /** * Multiple value separator getter. - * * @return string */ public function getMultipleValueSeparator() @@ -732,6 +722,16 @@ public function getMultipleValueSeparator() return self::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; } + /** + * Retrieve instance of product custom options import entity + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Option + */ + public function getOptionEntity() + { + return $this->_optionEntity; + } + /** * Retrieve id of media gallery attribute. * @@ -1246,7 +1246,7 @@ protected function _saveProductEntity(array $entityRowsIn, array $entityRowsUp) /** * Retrieving images from all columns and rows * - * @param $bunch + * @param array $bunch * @return array */ protected function getBunchImages($bunch) @@ -1279,7 +1279,7 @@ protected function getBunchImages($bunch) /** * Prepare all media files * - * @param $images + * @param array $images * @return array */ protected function getExistingImages($images) @@ -1318,11 +1318,11 @@ protected function getExistingImages($images) return $result; } - /* + /** * @param array $rowData * @return array */ - public function getImagesFromRow($rowData) + public function getImagesFromRow(array $rowData) { $images = []; $labels = []; @@ -1440,7 +1440,7 @@ protected function _saveProducts() $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY]; $separatorName = \Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR; $multipleSeparatorValue = empty($this->_parameters[$separatorName]) - ? static::PSEUDO_MULTI_LINE_SEPARATOR + ? static::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR : $this->_parameters[$separatorName]; $this->categoriesCache[$rowSku] = []; if (!empty($categoriesString)) { @@ -1629,7 +1629,7 @@ protected function _saveProducts() } /** - * @param $productSku + * @param string $productSku * @return array */ public function getProductWebsites($productSku) @@ -1638,7 +1638,7 @@ public function getProductWebsites($productSku) } /** - * @param $productSku + * @param string $productSku * @return array */ public function getProductCategories($productSku) @@ -1647,7 +1647,7 @@ public function getProductCategories($productSku) } /** - * @param $storeCode + * @param string $storeCode * @return array|int|null|string */ public function getStoreIdByCode($storeCode) @@ -1781,22 +1781,16 @@ protected function _saveMediaGallery(array $mediaGalleryData) static $mediaGalleryTableName = null; static $mediaValueTableName = null; static $mediaEntityToValueTableName = null; - static $productId = null; - if (!$mediaGalleryTableName) { - $mediaGalleryTableName = $this->_resourceFactory->create()->getTable( - 'catalog_product_entity_media_gallery' - ); - } - if (!$mediaValueTableName) { - $mediaValueTableName = $this->_resourceFactory->create()->getTable( - 'catalog_product_entity_media_gallery_value' - ); - } - if (!$mediaEntityToValueTableName) { - $mediaEntityToValueTableName = $this->_resourceFactory->create()->getTable( - 'catalog_product_entity_media_gallery_value_to_entity' - ); - } + $mediaGalleryTableName = $mediaGalleryTableName ?: $this->_resourceFactory->create()->getTable( + 'catalog_product_entity_media_gallery' + ); + $mediaValueTableName = $mediaValueTableName ?: $this->_resourceFactory->create()->getTable( + 'catalog_product_entity_media_gallery_value' + ); + $mediaEntityToValueTableName = $mediaEntityToValueTableName ?: $this->_resourceFactory->create()->getTable( + 'catalog_product_entity_media_gallery_value_to_entity' + ); + $productIds = []; $imageNames = []; $multiInsertData = []; @@ -1830,8 +1824,7 @@ protected function _saveMediaGallery(array $mediaGalleryData) ); $this->_connection->insertOnDuplicate($mediaGalleryTableName, $multiInsertData, []); $multiInsertData = []; - $newMediaSelect = $this->_connection->select() - ->from($mediaGalleryTableName, ['value_id', 'value']) + $newMediaSelect = $this->_connection->select()->from($mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); if (array_keys($oldMediaValues)) { $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php index 26d5493409bc6..cee5e53e97978 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php @@ -93,6 +93,12 @@ protected function numericValidation($attrCode, $type) return $valid; } + /** + * @param string $attrCode + * @param array $attributeParams + * @param array $rowData + * @return bool + */ public function isRequiredAttributeValid($attrCode, array $attributeParams, array $rowData) { $doCheck = false; diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php index 3541ccbb99338..b7fd1e3604b67 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php @@ -5,8 +5,10 @@ */ namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product; +use Magento\CatalogImportExport\Model\Import\Product; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\CatalogImportExport\Model\Import\Product\Validator; +use Magento\ImportExport\Model\Import; class ValidatorTest extends \PHPUnit_Framework_TestCase { @@ -46,7 +48,7 @@ protected function setUp() false ); $this->context->expects($this->any())->method('retrieveProductTypeByName')->willReturn($entityTypeModel); - $this->context->expects($this->any())->method('retrieveMessageTemplate')->willReturn(''); + $this->context->expects($this->any())->method('retrieveMessageTemplate')->willReturn('error message'); $this->validatorOne = $this->getMock( 'Magento\CatalogImportExport\Model\Import\Product\Validator\Media', @@ -72,23 +74,123 @@ protected function setUp() $this->validator->init($this->context); } - public function testIsBooleanAttributeValid() + /** + * @param string $behavior + * @param array $attrParams + * @param array $rowData + * @param bool $isValid + * @param string $attrCode + * @dataProvider attributeValidationProvider + */ + public function testAttributeValidation($behavior, $attrParams, $rowData, $isValid, $attrCode = 'attribute_code') { - $this->context->expects($this->any())->method('getBehavior') - ->willReturn(\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE); + $this->context->expects($this->any())->method('getBehavior')->willReturn($behavior); $result = $this->validator->isAttributeValid( - 'boolean_attribute', + $attrCode, + $attrParams, + $rowData + ); + $this->assertEquals($isValid, $result); + if (!$isValid) { + $this->assertTrue($this->validator->hasMessages()); + } + } + + /** + * @return array + */ + public function attributeValidationProvider() + { + return [ + [ + 'any_behavior', + ['apply_to' => ['expected_product_type']], + ['product_type' => 'not_expected_product_type'], + true, //validation skipped in such case, so it means attribute is valid + 'any_attibute_code', + ], + [ + 'any_behavior', + [], + ['product_type' => 'any'], + false, + Product::COL_SKU + ], + [ + 'any_behavior', + ['type' => 'varchar'], + ['product_type' => 'any', 'sku' => 'sku_value'], + true, + Product::COL_SKU + ], + [ + 'any_behavior', + ['is_required' => true, 'type' => 'varchar'], + ['product_type' => 'any', 'attribute_code' => 'value'], + true + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'varchar'], + ['product_type' => 'any', 'attribute_code' => ''], + false + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'int'], + ['product_type' => 'any', 'attribute_code' => 'not-int'], + false + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'int'], + ['product_type' => 'any', 'attribute_code' => '1'], + true + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'boolean', 'options' => ['yes' => 0, 'no' => 1]], + ['product_type' => 'any', 'attribute_code' => 'some-value'], + false + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'boolean', 'options' => ['yes' => 0, 'no' => 1]], + ['product_type' => 'any', 'attribute_code' => 'Yes'], + true + ], [ - 'type' => 'boolean', - 'apply_to' => ['simple'], - 'is_required' => false + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'multiselect', 'options' => ['option 1' => 0, 'option 2' => 1]], + ['product_type' => 'any', 'attribute_code' => 'Option 1|Option 2|Option 3'], + false ], [ - 'product_type' => 'simple', - 'boolean_attribute' => 'Yes' + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'multiselect', 'options' => ['option 1' => 0, 'option 2' => 1]], + ['product_type' => 'any', 'attribute_code' => 'Option 1|Option 2'], + true + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'datetime'], + ['product_type' => 'any', 'attribute_code' => '1/1/15 12am'], + true + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'datetime'], + ['product_type' => 'any', 'attribute_code' => '1/1/15 13am'], + false + ], + [ + Import::BEHAVIOR_APPEND, + ['is_required' => true, 'type' => 'varchar', 'is_unique' => true], + ['product_type' => 'any', 'unique_attribute' => 'unique-value', Product::COL_SKU => 'sku-0'], + true, + 'unique_attribute' ] - ); - $this->assertTrue($result); + ]; } public function testIsValidCorrect() diff --git a/app/code/Magento/ImportExport/Files/Sample/catalog_product.csv b/app/code/Magento/ImportExport/Files/Sample/catalog_product.csv index e71a80c871155..8d9eaaa5e9a41 100644 --- a/app/code/Magento/ImportExport/Files/Sample/catalog_product.csv +++ b/app/code/Magento/ImportExport/Files/Sample/catalog_product.csv @@ -1,8 +1,7 @@ -sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,custom_options,configurable_variations,configurable_variation_prices,configurable_variation_labels,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values -24-WG085,,"Sprite Yoga Strap",simple,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 6 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and urable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,"1",1,"Taxable Goods","Catalog, Search",14,,,,sprite-yoga-strap-6-foot,"Meta Title","meta1, meta2, meta3","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 15:38","01.07.2015 15:38",,,"Block after Info Column",,,,,,,,,,,,,"has_options=0,required_options=0,size=6 foot",100,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087","/l/u/luma-yoga-strap.jpg,/l/u/luma-yoga-strap.jpg","Image,Image","name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=,option_title=Gold|name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=,option_title=Silver|name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=yoga3sku,option_title=Platinum",,,,,,,, -24-WG086,,"Sprite Yoga Strap",simple,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 8 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 8' long x 1.0"" wide.
  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,"1",1,"Taxable Goods","Catalog, Search",17,,,,sprite-yoga-strap-8-foot,"Meta Title","meta1, meta2, meta4","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 15:38","01.07.2015 15:38",,,"Block after Info Column",,,,,,,,,,,,,"has_options=0,required_options=0,size=8 foot",100,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087","/l/u/luma-yoga-strap.jpg,/l/u/luma-yoga-strap.jpg","Image,Image",,,,,,,,, -24-WG087,,"Sprite Yoga Strap",simple,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 10 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 10' long x 1.0"" wide.
  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,"1",1,"Taxable Goods","Catalog, Search",21,,,,sprite-yoga-strap-10-foot,"Meta Title","meta1, meta2, meta5","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 15:39","01.07.2015 15:39",,,"Block after Info Column",,,,,,,,,,,,,"has_options=0,required_options=0,size=10 foot",100,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087","/l/u/luma-yoga-strap.jpg,/l/u/luma-yoga-strap.jpg","Image,Image",,,,,,,,, -24-WG085_Group,,Gear,grouped,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Set of Sprite Yoga Straps","

Great set of Sprite Yoga Straps for every stretch and hold you need. There are three straps in this set: 6', 8' and 10'.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Choice of three natural colors made from phthalate and heavy metal free dyes.
",,"1",1,,"Catalog, Search",,,,,set-of-sprite-yoga-straps,"Meta Title","meta1, meta2, meta6","meta description",/l/u/luma-yoga-strap-set.jpg,"Image Label",/l/u/luma-yoga-strap-set.jpg,"Image Label",/l/u/luma-yoga-strap-set.jpg,"Image Label","01.07.2015 15:39","01.07.2015 15:39",,,"Block after Info Column",,,,,,,,,,,,,"has_options=0,required_options=0",0,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087",/l/u/luma-yoga-strap-set.jpg,"Image,Image",,,,,,,,, -24-WG085-configurable,,"Sprite Yoga Strap",configurable,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap Configurable","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1,1,"Taxable Goods","Catalog, Search",14,,,,sprite-yoga-strap1,"Meta Title","meta1, meta2, meta7","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 16:15","01.07.2015 16:15",,,"Block after Info Column",,,,,,,,,,,,,"has_options=1,required_options=1",0,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087",/l/u/luma-yoga-strap.jpg,"Image,Image",,"sku=24-WG086,size=8 foot|sku=24-WG087,size=10 foot|sku=24-WG085,size=6 foot","name=size,value=8 foot,price=3.0000,price_type=fixed|name=size,value=10 foot,price=7.0000,price_type=fixed|name=size,value=6 foot,price=,price_type=fixed",size=Size,,,,, -24-WG085-bundle-dynamic,,"Sprite Yoga Strap",bundle,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap Dynamic Bundle","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1,1,"Taxable Goods","Catalog, Search",14,,,,sprite-yoga-strap2,"Meta Title","meta1, meta2, meta8","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 16:15","01.07.2015 16:15",,,"Block after Info Column",,,,,,,,,,,,,"has_options=1,required_options=1",0,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087",/l/u/luma-yoga-strap.jpg,"Image,Image",,,,,dynamic,dynamic,"Price Range",fixed,"name=Bundle Option One1,type=dropdown,required=1,sku=24-WG085,price=15; price_type=fixed, default_qty=1, default=0 | name=Bundle Option One1,type=dropdown; required=1, sku=24-WG086,price=10, price_type=fixed, default_qty=1, default=1" -24-WG085-bundle-fixed,,"Sprite Yoga Strap",bundle,"Default Category/Gear|Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap Fixed Bundle","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1,1,"Taxable Goods","Catalog, Search",14,,,,sprite-yoga-strap3,"Meta Title","meta1, meta2, meta9","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","01.07.2015 16:15","01.07.2015 16:15",,,"Block after Info Column",,,,,,,,,,,,,"has_options=1,required_options=1",0,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,1,"24-WG086,24-WG087","24-WG086,24-WG087","24-WG086,24-WG087",/l/u/luma-yoga-strap.jpg,"Image,Image",,,,,fixed,fixed,"Price Range",fixed,"name=Yoga Strap,type=radiobutton,required=1,sku=24-WG086,default_qty=3,default=1 | name=Yoga Strap,type=radiobutton,required=1,sku=24-WG085,default_qty=3,default=0" +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus +24-WG085,,Default,simple,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 6 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and urable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1.0000,1,"Taxable Goods","Catalog, Search",14.0000,,,,sprite-yoga-strap-6-foot,"Meta Title","meta1, meta2, meta3","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","2015-10-25 03:34:19","2015-10-25 03:34:20",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=1,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",100.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,1,0,1,"24-WG087,24-WG086","24-WG087,24-WG086","24-WG087,24-WG086",/l/u/luma-yoga-strap.jpg,Image,,"name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=,option_title=Gold|name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=,option_title=Silver|name=Custom Yoga Option,type=drop_down,required=0,price=10.0000,price_type=fixed,sku=yoga3sku,option_title=Platinum",,,,,, +24-WG086,,Default,simple,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 8 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 8' long x 1.0"" wide.
  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1.0000,1,"Taxable Goods","Catalog, Search",17.0000,,,,sprite-yoga-strap-8-foot,"Meta Title","meta1, meta2, meta4","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","2015-10-25 03:34:20","2015-10-25 03:34:20",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=0,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",100.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,1,0,1,24-WG087,24-WG087,24-WG087,/l/u/luma-yoga-strap.jpg,Image,,,,,,,, +24-WG087,,Default,simple,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap 10 foot","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 10' long x 1.0"" wide.
  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1.0000,1,"Taxable Goods","Catalog, Search",21.0000,,,,sprite-yoga-strap-10-foot,"Meta Title","meta1, meta2, meta5","meta description",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label",/l/u/luma-yoga-strap.jpg,"Image Label","2015-10-25 03:34:20","2015-10-25 03:34:20",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=0,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",100.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,1,0,1,24-WG086,24-WG086,24-WG086,/l/u/luma-yoga-strap.jpg,Image,,,,,,,, +24-WG085_Group,,Default,grouped,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Set of Sprite Yoga Straps","

Great set of Sprite Yoga Straps for every stretch and hold you need. There are three straps in this set: 6', 8' and 10'.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Choice of three natural colors made from phthalate and heavy metal free dyes.
",,,1,,"Catalog, Search",,,,,set-of-sprite-yoga-straps,"Meta Title","meta1, meta2, meta6","meta description",/l/u/luma-yoga-strap-set.jpg,Image,/l/u/luma-yoga-strap-set.jpg,Image,/l/u/luma-yoga-strap-set.jpg,Image,"2015-10-25 03:34:20","2015-10-25 03:36:31",,,"Block after Info Column",,,,,,,,,,,,,"has_options=0,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",0.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,1,1,1,0.0000,1,0,0,1,0,1,"24-WG087,24-WG086","24-WG087,24-WG086","24-WG087,24-WG086",/l/u/luma-yoga-strap-set.jpg,Image,,,,,,,,"24-WG085=5.0000,24-WG086=5.0000" +24-WG085-bundle-dynamic,,Default,bundle,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap Dynamic Bundle","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1.0000,1,"Taxable Goods","Catalog, Search",14.0000,,,,sprite-yoga-strap2,"Meta Title","meta1, meta2, meta8","meta description",/l/u/luma-yoga-strap.jpg,,/l/u/luma-yoga-strap.jpg,,/l/u/luma-yoga-strap.jpg,,"2015-10-25 03:34:20","2015-10-25 03:34:20",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=1,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",0.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,1,0,1,"24-WG087,24-WG086","24-WG087,24-WG086","24-WG087,24-WG086",/l/u/luma-yoga-strap.jpg,Image,,,dynamic,dynamic,"Price range",fixed,"name=Bundle Option One1,type=select,required=1,sku=24-WG085,price=15.0000,default=0,default_qty=1.0000,price_type=fixed|name=Bundle Option One1,type=select,required=1,sku=24-WG086,price=10.0000,default=1,default_qty=1.0000,price_type=fixed", +24-WG085-bundle-fixed,,Default,bundle,"Default Category/Gear,Default Category/Gear/Fitness Equipment",base,"Sprite Yoga Strap Fixed Bundle","

The Sprite Yoga Strap is your untiring partner in demanding stretches, holds and alignment routines. The strap's 100% organic cotton fabric is woven tightly to form a soft, textured yet non-slip surface. The plastic clasp buckle is easily adjustable, lightweight and durable under strain.

  • 100% soft and durable cotton.
  • Plastic cinch buckle is easy to use.
  • Three natural colors made from phthalate and heavy metal free dyes.
",,1.0000,1,"Taxable Goods","Catalog, Search",14.0000,,,,sprite-yoga-strap3,"Meta Title","meta1, meta2, meta9","meta description",/l/u/luma-yoga-strap.jpg,,/l/u/luma-yoga-strap.jpg,,/l/u/luma-yoga-strap.jpg,,"2015-10-25 03:34:20","2015-10-25 03:34:20",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=1,is_returnable=Use config,quantity_and_stock_status=In Stock,required_options=0",0.0000,0.0000,1,0,0,1,1.0000,0,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,1,0,1,"24-WG087,24-WG086","24-WG087,24-WG086","24-WG087,24-WG086",/l/u/luma-yoga-strap.jpg,Image,,,fixed,fixed,"Price range",fixed,"name=Yoga Strap,type=radio,required=1,sku=24-WG086,price=0.0000,default=1,default_qty=3.0000,price_type=percent|name=Yoga Strap,type=radio,required=1,sku=24-WG085,price=0.0000,default=0,default_qty=3.0000,price_type=percent", diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index a140d2aefcfaa..329127b7bd9ad 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -21,7 +21,6 @@ * Class ProductTest * * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductTest extends \PHPUnit_Framework_TestCase { @@ -77,7 +76,7 @@ protected function setUp() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function testSaveProductsVisibility() + public function _testSaveProductsVisibility() { $existingProductIds = [10, 11, 12]; $productsBeforeImport = []; @@ -128,7 +127,7 @@ public function testSaveProductsVisibility() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function testSaveStockItemQty() + public function _testSaveStockItemQty() { $existingProductIds = [10, 11, 12]; $stockItems = []; @@ -182,7 +181,7 @@ public function testSaveStockItemQty() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function testStockState() + public function _testStockState() { $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Framework\Filesystem'); @@ -211,7 +210,7 @@ public function testStockState() * @param string $sku * @magentoAppIsolation enabled */ - public function testSaveCustomOptions($importFile, $sku) + public function _testSaveCustomOptions($importFile, $sku) { $pathToFile = __DIR__ . '/_files/' . $importFile; $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() @@ -296,7 +295,7 @@ public function getBehaviorDataProvider() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function testSaveDatetimeAttribute() + public function _testSaveDatetimeAttribute() { $existingProductIds = [10, 11, 12]; $productsBeforeImport = []; @@ -511,7 +510,7 @@ protected function getOptionValues(\Magento\Catalog\Model\Product\Option $option * * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testSaveMediaImage() + public function _testSaveMediaImage() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() @@ -627,7 +626,7 @@ protected function csvToArray($content, $entityId = null) * * @magentoDbIsolation enabled */ - public function testInvalidSkuLink() + public function _testInvalidSkuLink() { // import data from CSV file $pathToFile = __DIR__ . '/_files/products_to_import_invalid_attribute_set.csv'; @@ -670,7 +669,7 @@ public function testInvalidSkuLink() * @magentoDataFixture Magento/Catalog/_files/products_with_multiselect_attribute.php * @magentoAppIsolation enabled */ - public function testValidateInvalidMultiselectValues() + public function _testValidateInvalidMultiselectValues() { $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Framework\Filesystem' @@ -701,7 +700,7 @@ public function testValidateInvalidMultiselectValues() * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php * @magentoAppIsolation enabled */ - public function testProductsWithMultipleStores() + public function _testProductsWithMultipleStores() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -740,7 +739,7 @@ public function testProductsWithMultipleStores() /** * @magentoDbIsolation enabled */ - public function testProductWithInvalidWeight() + public function _testProductWithInvalidWeight() { // import data from CSV file $pathToFile = __DIR__ . '/_files/product_to_import_invalid_weight.csv'; @@ -762,4 +761,45 @@ public function testProductWithInvalidWeight() $errors->getErrorByRowNumber(1)[0]->getErrorMessage() ); } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testProductCategoriesDefaultSeparator() + { + // import data from CSV file + $pathToFile = __DIR__ . '/_files/import_new_categories_default_separator.csv'; + $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Framework\Filesystem' + ); + + $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $source = new \Magento\ImportExport\Model\Import\Source\Csv($pathToFile, $directory); + $errors = $this->_model->setSource( + $source + )->setParameters( + ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] + )->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 0); + $this->_model->importData(); + + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $resource = $objectManager->get('Magento\Catalog\Model\ResourceModel\Product'); + $productId = $resource->getIdBySku('simple1'); + $this->assertTrue(is_numeric($productId)); + /** @var \Magento\Catalog\Model\Product $product */ + $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Catalog\Model\Product' + ); + $product->load($productId); + $this->assertFalse($product->isObjectNew()); + $categories = $product->getCategoryCollection(); + $this->assertTrue($categories->count() > 0); + /** @var \Magento\Catalog\Model\Category $category */ + foreach ($categories as $category) { + $this->assertTrue(in_array($category->getName(), ['Category 1', 'Category 2'])); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv new file mode 100644 index 0000000000000..96281b790b1db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv @@ -0,0 +1,2 @@ +sku,product_type,store_view_code,name,price,attribute_set_code,categories,product_websites +simple2,simple,,"simple 2",25,Default,"Default Category/Category 1|Default Category/Category 2",base diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv new file mode 100644 index 0000000000000..9bf687dec4632 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv @@ -0,0 +1,2 @@ +sku,product_type,store_view_code,name,price,attribute_set_code,categories,product_websites,url_key +simple1,simple,,"simple 1",25,Default,"Default Category/Category 1,Default Category/Category 2",base,simple1-ds From c36df073d35169ee3fa2a5dc996057059c3088a1 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Sun, 25 Oct 2015 18:49:48 +0200 Subject: [PATCH 14/23] MAGETWO-39795: Check data for import product does not work MAGETWO-43900: Imported products with broken images link don't appear on front MAGETWO-43901: The "Imported resource (image) could not be downloaded" message appears when user tries to import products using "Replace" behavior MAGETWO-44238: Categories imported in a comma-separated format are not created properly MAGETWO-42245: _media_is_disabled is not exported MAGETWO-44407: CLONE - Product export and re-import with different store view level data causes data corruption --- .../Model/Export/Product.php | 4 +- .../Model/Import/Product.php | 35 +++++++----- .../Model/Import/ProductTest.php | 54 ++++++++++++------- ...import_new_categories_custom_separator.csv | 2 +- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index b3f8a864758ea..58e22946ffcfd 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -672,7 +672,7 @@ protected function setHeaderColumns($customOptionsData, $stockItemRows) self::COL_ATTR_SET, self::COL_TYPE, self::COL_CATEGORY, - '_product_websites', + self::COL_PRODUCT_WEBSITES, ], $this->_getExportMainAttrCodes(), [self::COL_ADDITIONAL_ATTRIBUTES], @@ -1040,7 +1040,7 @@ protected function addMultirowData($dataRow, $multiRawData) foreach ($multiRawData['rowWebsites'][$productId] as $productWebsite) { $websiteCodes[] = $this->_websiteIdToCode[$productWebsite]; } - $dataRow['_product_websites'] = + $dataRow[self::COL_PRODUCT_WEBSITES] = implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $websiteCodes); $multiRawData['rowWebsites'][$productId] = []; } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 863ea0d9fb84c..54ce88b1b0e4b 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1437,20 +1437,10 @@ protected function _saveProducts() } // 3. Categories phase - $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY]; - $separatorName = \Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR; - $multipleSeparatorValue = empty($this->_parameters[$separatorName]) - ? static::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR - : $this->_parameters[$separatorName]; - $this->categoriesCache[$rowSku] = []; - if (!empty($categoriesString)) { - $categoryIds = $this->categoryProcessor->upsertCategories( - $categoriesString, - $multipleSeparatorValue - ); - foreach ($categoryIds as $id) { - $this->categoriesCache[$rowSku][$id] = true; - } + $categoryIds = $this->processRowCategories($rowData); + $this->categoriesCache[$rowData[Product::COL_SKU]] = []; + foreach ($categoryIds as $id) { + $this->categoriesCache[$rowData[Product::COL_SKU]][$id] = true; } // 4.1. Tier prices phase @@ -1628,6 +1618,23 @@ protected function _saveProducts() return $this; } + /** + * @param array $rowData + * @return array + */ + protected function processRowCategories($rowData) + { + $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY]; + $categoryIds = []; + if (!empty($categoriesString)) { + $categoryIds = $this->categoryProcessor->upsertCategories( + $categoriesString, + $this->getMultipleValueSeparator() + ); + } + return $categoryIds; + } + /** * @param string $productSku * @return array diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index 329127b7bd9ad..fd948348e4d64 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -16,6 +16,7 @@ use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\ImportExport\Model\Import; /** * Class ProductTest @@ -76,7 +77,7 @@ protected function setUp() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function _testSaveProductsVisibility() + public function testSaveProductsVisibility() { $existingProductIds = [10, 11, 12]; $productsBeforeImport = []; @@ -127,7 +128,7 @@ public function _testSaveProductsVisibility() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function _testSaveStockItemQty() + public function testSaveStockItemQty() { $existingProductIds = [10, 11, 12]; $stockItems = []; @@ -181,7 +182,7 @@ public function _testSaveStockItemQty() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function _testStockState() + public function testStockState() { $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Framework\Filesystem'); @@ -210,7 +211,7 @@ public function _testStockState() * @param string $sku * @magentoAppIsolation enabled */ - public function _testSaveCustomOptions($importFile, $sku) + public function testSaveCustomOptions($importFile, $sku) { $pathToFile = __DIR__ . '/_files/' . $importFile; $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() @@ -295,7 +296,7 @@ public function getBehaviorDataProvider() * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoAppIsolation enabled */ - public function _testSaveDatetimeAttribute() + public function testSaveDatetimeAttribute() { $existingProductIds = [10, 11, 12]; $productsBeforeImport = []; @@ -510,7 +511,7 @@ protected function getOptionValues(\Magento\Catalog\Model\Product\Option $option * * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function _testSaveMediaImage() + public function testSaveMediaImage() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() @@ -626,7 +627,7 @@ protected function csvToArray($content, $entityId = null) * * @magentoDbIsolation enabled */ - public function _testInvalidSkuLink() + public function testInvalidSkuLink() { // import data from CSV file $pathToFile = __DIR__ . '/_files/products_to_import_invalid_attribute_set.csv'; @@ -646,7 +647,7 @@ public function _testInvalidSkuLink() $this->assertTrue($errors->getErrorsCount() == 1); $this->assertEquals( - 'Invalid value for Product Template column (set doesn\'t exist?)', + 'Invalid value for Attribute Set column (set doesn\'t exist?)', $errors->getErrorByRowNumber(1)[0]->getErrorMessage() ); $this->_model->importData(); @@ -669,7 +670,7 @@ public function _testInvalidSkuLink() * @magentoDataFixture Magento/Catalog/_files/products_with_multiselect_attribute.php * @magentoAppIsolation enabled */ - public function _testValidateInvalidMultiselectValues() + public function testValidateInvalidMultiselectValues() { $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Framework\Filesystem' @@ -700,7 +701,7 @@ public function _testValidateInvalidMultiselectValues() * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php * @magentoAppIsolation enabled */ - public function _testProductsWithMultipleStores() + public function testProductsWithMultipleStores() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -739,7 +740,7 @@ public function _testProductsWithMultipleStores() /** * @magentoDbIsolation enabled */ - public function _testProductWithInvalidWeight() + public function testProductWithInvalidWeight() { // import data from CSV file $pathToFile = __DIR__ . '/_files/product_to_import_invalid_weight.csv'; @@ -763,13 +764,15 @@ public function _testProductWithInvalidWeight() } /** + * @magentoAppArea adminhtml + * @dataProvider categoryTestDataProvider * @magentoDbIsolation enabled * @magentoAppIsolation enabled */ - public function testProductCategoriesDefaultSeparator() + public function testProductCategories($fixture, $separator) { // import data from CSV file - $pathToFile = __DIR__ . '/_files/import_new_categories_default_separator.csv'; + $pathToFile = __DIR__ . '/_files/' . $fixture; $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Framework\Filesystem' ); @@ -779,7 +782,11 @@ public function testProductCategoriesDefaultSeparator() $errors = $this->_model->setSource( $source )->setParameters( - ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR => $separator + ] )->validateData(); $this->assertTrue($errors->getErrorsCount() == 0); @@ -795,11 +802,18 @@ public function testProductCategoriesDefaultSeparator() ); $product->load($productId); $this->assertFalse($product->isObjectNew()); - $categories = $product->getCategoryCollection(); - $this->assertTrue($categories->count() > 0); - /** @var \Magento\Catalog\Model\Category $category */ - foreach ($categories as $category) { - $this->assertTrue(in_array($category->getName(), ['Category 1', 'Category 2'])); - } + $categories = $product->getCategoryIds(); + $this->assertTrue(count($categories) == 2); + } + + /** + * @return array + */ + public function categoryTestDataProvider() + { + return [ + ['import_new_categories_default_separator.csv', ','], + ['import_new_categories_custom_separator.csv', '|'] + ]; } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv index 96281b790b1db..c0deb9b289fd3 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv @@ -1,2 +1,2 @@ sku,product_type,store_view_code,name,price,attribute_set_code,categories,product_websites -simple2,simple,,"simple 2",25,Default,"Default Category/Category 1|Default Category/Category 2",base +simple1,simple,,"simple 2",25,Default,"Default Category/Category 1|Default Category/Category 2",base From 3a9a6a6a19bdc109b812cb5e53a68f7aa60a453e Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 26 Oct 2015 13:18:37 +0200 Subject: [PATCH 15/23] MAGETWO-39795: Check data for import product does not work MAGETWO-43900: Imported products with broken images link don't appear on front MAGETWO-43901: The "Imported resource (image) could not be downloaded" message appears when user tries to import products using "Replace" behavior MAGETWO-44238: Categories imported in a comma-separated format are not created properly MAGETWO-42245: _media_is_disabled is not exported MAGETWO-44407: CLONE - Product export and re-import with different store view level data causes data corruption --- .../Magento/CatalogImportExport/Model/Import/Product.php | 4 +++- .../CatalogImportExport/Model/Import/ProductTest.php | 2 ++ .../Model/Import/_files/products_multiple_stores.csv | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 54ce88b1b0e4b..4a145dcdb35db 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1426,7 +1426,9 @@ protected function _saveProducts() } } - $this->websitesCache[$rowSku] = []; + if (!array_key_exists($rowSku, $this->websitesCache)) { + $this->websitesCache[$rowSku] = []; + } // 2. Product-to-Website phase if (!empty($rowData[self::COL_PRODUCT_WEBSITES])) { $websiteCodes = explode($this->getMultipleValueSeparator(), $rowData[self::COL_PRODUCT_WEBSITES]); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index fd948348e4d64..e8205523ec8d5 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -696,6 +696,7 @@ public function testValidateInvalidMultiselectValues() /** * @magentoDataFixture Magento/Catalog/_files/categories.php + * @magentoDataFixture Magento/Store/_files/website.php * @magentoDataFixture Magento/Store/_files/core_fixturestore.php * @magentoDataFixture Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option.php * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php @@ -734,6 +735,7 @@ public function testProductsWithMultipleStores() $simpleProduct = $objectManager->create('Magento\Catalog\Model\Product'); $id = $simpleProduct->getIdBySku('Configurable 03-Option 1'); $simpleProduct->load($id); + $this->assertTrue(count($simpleProduct->getWebsiteIds()) == 2); $this->assertEquals('Option Label', $simpleProduct->getAttributeText('attribute_with_option')); } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv index d3e6af92cba7a..d7876f612233c 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv @@ -1,5 +1,5 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,configurable_variations,configurable_variation_labels,associated_skus -"Configurable 03-Option 1",,Default,simple,"Default Category/Category 1/Category 1.1",base,"Configurable 03-Option 1",,,,1,"Taxable Goods","Not Visible Individually",10.0000,,,,configurable-03-option-1,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 01:00:25",,,"Block after Info Column",,,,,,,,,,,"Use config",,"attribute_with_option=Option Label,has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 1",99999.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,1,0,0,1.0000,0,0,0,1,,,,,,,,,,,,,, -"Configurable 03-Option 1",fixturestore,Default,"simple",,base,"Configurable 03-Option 1 fixturestore",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -"Configurable 03-Option 2",,Default,simple,"Default Category/Category 1/Category 1.1",base,"Configurable 03-Option 2",,,,1,"Taxable Goods","Not Visible Individually",10.0000,,,,configurable-03-option-2,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 00:35:03",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 2",99999.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,1,0,0,1.0000,0,0,0,1,,,,,,,,,,,,,, -"Configurable 03",,Default,configurable,"Default Category/Category 1/Category 1.1",base,"Configurable 03",,,,1,"Taxable Goods","Catalog, Search",10.0000,,,,configurable-03,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 00:35:03",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,0,0,0,1.0000,0,0,0,1,,,,,,,,,,,,"sku=Configurable 03-Option 1,test_configurable=Option 1|sku=Configurable 03-Option 2,test_configurable=Option 2",test_configurable=test_configurable, +"Configurable 03-Option 1",,Default,simple,"Default Category/Category 1/Category 1.1","base,test","Configurable 03-Option 1",,,,1,"Taxable Goods","Not Visible Individually",10.0000,,,,configurable-03-option-1,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 01:00:25",,,"Block after Info Column",,,,,,,,,,,"Use config",,"attribute_with_option=Option Label,has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 1",99999.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,1,0,0,1.0000,0,0,0,1,,,,,,,,,,,,,, +"Configurable 03-Option 1",fixturestore,Default,"simple",,,"Configurable 03-Option 1 fixturestore",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"Configurable 03-Option 2",,Default,simple,"Default Category/Category 1/Category 1.1","base,test","Configurable 03-Option 2",,,,1,"Taxable Goods","Not Visible Individually",10.0000,,,,configurable-03-option-2,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 00:35:03",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 2",99999.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,1,0,0,1.0000,0,0,0,1,,,,,,,,,,,,,, +"Configurable 03",,Default,configurable,"Default Category/Category 1/Category 1.1","base,test","Configurable 03",,,,1,"Taxable Goods","Catalog, Search",10.0000,,,,configurable-03,"Configurable 03","Configurable 03","Configurable 03 ",,,,,,,"2015-10-23 00:35:03","2015-10-23 00:35:03",,,"Block after Info Column",,,,,,,,,,,"Use config",,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0.0000,0.0000,0,0,0,1,1.0000,0,0.0000,0,1,,1,0,0,0,1.0000,0,0,0,1,,,,,,,,,,,,"sku=Configurable 03-Option 1,test_configurable=Option 1|sku=Configurable 03-Option 2,test_configurable=Option 2",test_configurable=test_configurable, From f4d3451108f601a750287afc62916194b6010411 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 26 Oct 2015 15:21:58 +0200 Subject: [PATCH 16/23] MAGETWO-39795: Check data for import product does not work MAGETWO-43900: Imported products with broken images link don't appear on front MAGETWO-43901: The "Imported resource (image) could not be downloaded" message appears when user tries to import products using "Replace" behavior MAGETWO-44238: Categories imported in a comma-separated format are not created properly MAGETWO-42245: _media_is_disabled is not exported MAGETWO-44407: CLONE - Product export and re-import with different store view level data causes data corruption --- .../Magento/CatalogImportExport/Model/Export/Product.php | 6 +++--- .../Magento/CatalogImportExport/Model/Import/Product.php | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 58e22946ffcfd..299084686e0c3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -1052,9 +1052,9 @@ protected function addMultirowData($dataRow, $multiRawData) $additionalImages[] = $mediaItem['_media_image']; $additionalImageLabels[] = $mediaItem['_media_label']; - if ($mediaItem['_media_is_disabled'] == true) { - $additionalImageIsDisabled[] = $mediaItem['_media_image']; - } + if ($mediaItem['_media_is_disabled'] == true) { + $additionalImageIsDisabled[] = $mediaItem['_media_image']; + } } $dataRow['additional_images'] = implode(ImportProduct::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImages); diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 4a145dcdb35db..a7f04b26938e1 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1799,7 +1799,6 @@ protected function _saveMediaGallery(array $mediaGalleryData) $mediaEntityToValueTableName = $mediaEntityToValueTableName ?: $this->_resourceFactory->create()->getTable( 'catalog_product_entity_media_gallery_value_to_entity' ); - $productIds = []; $imageNames = []; $multiInsertData = []; @@ -1880,7 +1879,6 @@ protected function _saveMediaGallery(array $mediaGalleryData) $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) ); } - return $this; } From ea18e7d973e980d28414a3f5413a8f7aa5a80fde Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 26 Oct 2015 15:58:27 +0200 Subject: [PATCH 17/23] MAGETWO-39795: Check data for import product does not work MAGETWO-43900: Imported products with broken images link don't appear on front MAGETWO-43901: The "Imported resource (image) could not be downloaded" message appears when user tries to import products using "Replace" behavior MAGETWO-44238: Categories imported in a comma-separated format are not created properly MAGETWO-42245: _media_is_disabled is not exported MAGETWO-44407: CLONE - Product export and re-import with different store view level data causes data corruption --- .../Observer/AfterImportDataObserver.php | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php index a1d7000e8ce24..55fd02dce9220 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php @@ -190,6 +190,7 @@ protected function _populateForUrlGeneration($rowData) $product->setData($field, $rowData[$field]); } } + $this->categoryCache[$rowData['entity_id']] = $this->import->getProductCategories($rowData['sku']); $this->websiteCache[$rowData['entity_id']] = $this->import->getProductWebsites($rowData['sku']); foreach ($this->websiteCache[$rowData['entity_id']] as $websiteId) { @@ -197,6 +198,23 @@ protected function _populateForUrlGeneration($rowData) $this->websitesToStoreIds[$websiteId] = $this->storeManager->getWebsite($websiteId)->getStoreIds(); } } + + $this->setStoreToProduct($product, $rowData); + + if ($this->isGlobalScope($product->getStoreId())) { + $this->populateGlobalProduct($product); + } else { + $this->addProductToImport($product, $product->getStoreId()); + } + return $this; + } + + /** + * @param \Magento\Catalog\Model\Product $product + * @param array $rowData + */ + protected function setStoreToProduct(\Magento\Catalog\Model\Product $product, array $rowData) + { if (!empty($rowData[ImportProduct::COL_STORE]) && ($storeId = $this->import->getStoreIdByCode($rowData[ImportProduct::COL_STORE])) ) { @@ -204,12 +222,6 @@ protected function _populateForUrlGeneration($rowData) } elseif (!$product->hasData(\Magento\Catalog\Api\Data\ProductInterface::STORE_ID)) { $product->setStoreId(Store::DEFAULT_STORE_ID); } - if ($this->isGlobalScope($product->getStoreId())) { - $this->populateGlobalProduct($product); - } else { - $this->addProductToImport($product, $product->getStoreId()); - } - return $this; } /** From 16cdc4cce3af9a3066d6504ee2f1c9c881efbfe7 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 26 Oct 2015 16:50:43 +0200 Subject: [PATCH 18/23] MAGETWO-44226: Multi-store: Import product to two different websites --- .../CatalogUrlRewrite/Observer/AfterImportDataObserver.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php index 55fd02dce9220..855d800fcfdcb 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php @@ -212,6 +212,7 @@ protected function _populateForUrlGeneration($rowData) /** * @param \Magento\Catalog\Model\Product $product * @param array $rowData + * @return void */ protected function setStoreToProduct(\Magento\Catalog\Model\Product $product, array $rowData) { From 6e12c3367b0db5b84122e7e813b5d1f9b59b9d83 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 26 Oct 2015 19:15:03 +0200 Subject: [PATCH 19/23] MAGETWO-44238: Categories imported in a comma-separated format are not created properly --- .../Magento/CatalogImportExport/Model/Import/Product.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index e272baec71b01..066e0cf166ee1 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1435,10 +1435,12 @@ protected function _saveProducts() } // 3. Categories phase + if (!array_key_exists($rowSku, $this->categoriesCache)) { + $this->categoriesCache[$rowSku] = []; + } $categoryIds = $this->processRowCategories($rowData); - $this->categoriesCache[$rowData[Product::COL_SKU]] = []; foreach ($categoryIds as $id) { - $this->categoriesCache[$rowData[Product::COL_SKU]][$id] = true; + $this->categoriesCache[$rowSku][$id] = true; } // 4.1. Tier prices phase From 3d6e1ccaa113a3591a57907be9ba08276ea41b48 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Tue, 27 Oct 2015 11:31:23 +0200 Subject: [PATCH 20/23] MAGETWO-43900: Imported products with broken images link don't appear on front --- .../ProcessingErrorAggregator.php | 4 +++- .../ProcessingErrorAggregatorTest.php | 24 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php index acb19a9847212..e6df28446fbf0 100644 --- a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php +++ b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php @@ -81,7 +81,9 @@ public function addError( return $this; } $this->processErrorStatistics($errorLevel); - $this->processInvalidRow($rowNumber); + if ($errorLevel == ProcessingError::ERROR_LEVEL_CRITICAL) { + $this->processInvalidRow($rowNumber); + } $errorMessage = $this->getErrorMessage($errorCode, $errorMessage, $columnName); /** @var ProcessingError $newError */ 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 63b82e3693d2d..7877a5c3a2609 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 @@ -5,6 +5,8 @@ */ namespace Magento\ImportExport\Test\Unit\Model\Import\ErrorProcessing; +use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError; + class ProcessingErrorAggregatorTest extends \PHPUnit_Framework_TestCase { /** @@ -124,22 +126,26 @@ public function testAddErrorMessageTemplate() /** * Test for method isRowInvalid. Expected true result. + * @dataProvider isRowInvalidDataProvider */ - public function testIsRowInvalidTrue() + public function testIsRowInvalid($errorLevel, $rowNumber, $isValid) { - $this->model->addError('systemException', 'critical', 7, 'Some column name', 'Message', 'Description'); - $result = $this->model->isRowInvalid(7); - $this->assertTrue($result); + $this->model->addError('systemException', $errorLevel, $rowNumber, 'Some column name', 'Message', 'Description'); + $result = $this->model->isRowInvalid($rowNumber); + $this->assertEquals($isValid, $result); } /** - * Test for method isRowInvalid. Expected false result. + * @return array */ - public function testIsRowInvalidFalse() + public function isRowInvalidDataProvider() { - $this->model->addError('systemException'); - $result = $this->model->isRowInvalid(8); - $this->assertFalse($result); + return [ + [ProcessingError::ERROR_LEVEL_CRITICAL, 7, true], + [ProcessingError::ERROR_LEVEL_NOT_CRITICAL, 8, false], + [ProcessingError::ERROR_LEVEL_NOTICE, 9, false], + [ProcessingError::ERROR_LEVEL_WARNING, 10, false] + ]; } /** From 6d2516f99b7d1d838838021f8fe24468bf44a5f2 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Tue, 27 Oct 2015 18:24:58 +0200 Subject: [PATCH 21/23] MAGETWO-44250: [Import/Export] Product doesn't exist on backend but still visible on frontend --- .../Model/Controller/Result/BuiltinPlugin.php | 15 +- .../Controller/Result/BuiltinPluginTest.php | 172 +++++++++++------- 2 files changed, 124 insertions(+), 63 deletions(-) diff --git a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php index 667da81dd04e1..022824faafbd4 100644 --- a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php +++ b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php @@ -66,8 +66,9 @@ public function aroundRenderResult( ) { $result = $proceed($response); $usePlugin = $this->registry->registry('use_page_cache_plugin'); - if (!$this->config->isEnabled() || $this->config->getType() != \Magento\PageCache\Model\Config::BUILT_IN - || !$usePlugin) { + if (!$usePlugin || !$this->config->isEnabled() + || $this->config->getType() != \Magento\PageCache\Model\Config::BUILT_IN + ) { return $result; } @@ -76,6 +77,16 @@ public function aroundRenderResult( $response->setHeader('X-Magento-Cache-Control', $cacheControl); $response->setHeader('X-Magento-Cache-Debug', 'MISS', true); } + + $tagsHeader = $response->getHeader('X-Magento-Tags'); + $tags = []; + if ($tagsHeader) { + $tags = explode(',', $tagsHeader->getFieldValue()); + $response->clearHeader('X-Magento-Tags'); + } + $tags = array_unique(array_merge($tags, [\Magento\PageCache\Model\Cache\Type::CACHE_TAG])); + $response->setHeader('X-Magento-Tags', implode(',', $tags)); + $this->kernel->process($response); return $result; } diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php index a3542bdc708cf..2ae5fa1f9f1e5 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php @@ -11,83 +11,133 @@ class BuiltinPluginTest extends \PHPUnit_Framework_TestCase { /** - * @param bool $usePlugin - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $getHeaderCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $setCacheControlHeaderCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $setCacheDebugHeaderCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $getModeCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $processCount - * @dataProvider dataProvider + * @var \Magento\PageCache\Model\Controller\Result\BuiltinPlugin */ - public function testAroundResult( - $usePlugin, $getHeaderCount, $setCacheControlHeaderCount, $setCacheDebugHeaderCount, $getModeCount, - $processCount - ) { - $cacheControl = 'test'; - - $header = $this->getMockBuilder('Zend\Http\Header\HeaderInterface') - ->getMockForAbstractClass(); - $header->expects($this->any())->method('getFieldValue') - ->willReturn($cacheControl); - - $response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); - $response->expects($getHeaderCount) - ->method('getHeader') - ->with('Cache-Control') - ->willReturn($header); - $response->expects($setCacheControlHeaderCount)->method('setHeader') - ->with('X-Magento-Cache-Control', $cacheControl); - $response->expects($setCacheDebugHeaderCount)->method('setHeader') - ->with('X-Magento-Cache-Debug', 'MISS', true); - - /** @var \Magento\Framework\Controller\ResultInterface $result */ + protected $plugin; + + /** + * @var \Magento\Framework\Controller\ResultInterface + */ + protected $subject; + + /** + * @var \Closure + */ + protected $closure; + + /** + * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + */ + protected $response; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $registry; + + /** + * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + */ + protected $state; + + /** + * @var \Zend\Http\Header\HeaderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $header; + + /** + * @var \Magento\Framework\App\PageCache\Kernel|\PHPUnit_Framework_MockObject_MockObject + */ + protected $kernel; + + protected function setUp() + { $result = $this->getMock('Magento\Framework\Controller\ResultInterface', [], [], '', false); - $closure = function () use ($result) { + $this->closure = function() use ($result) { return $result; }; - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject $registry */ - $registry = $this->getMock('Magento\Framework\Registry', [], [], '', false); - $registry->expects($this->once())->method('registry')->with('use_page_cache_plugin') - ->will($this->returnValue($usePlugin)); - - /** @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); - $config->expects($this->once())->method('isEnabled')->will($this->returnValue(true)); - $config->expects($this->once())->method('getType') - ->will($this->returnValue(\Magento\PageCache\Model\Config::BUILT_IN)); + $this->header = $this->getMock('Zend\Http\Header\HeaderInterface', [], [], '', false); + $this->subject = $this->getMock('Magento\Framework\Controller\ResultInterface', [], [], '', false); + $this->response = $this->getMock( + 'Magento\Framework\App\Response\Http', + ['getHeader', 'clearHeader', 'setHeader'], + [], + '', + false + ); + $this->response->expects($this->any())->method('getHeader')->willReturnMap( + [ + ['X-Magento-Tags', $this->header], + ['Cache-Control', $this->header] + ] + ); - /** @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject $state */ - $state = $this->getMock('Magento\Framework\App\State', [], [], '', false); - $state->expects($getModeCount)->method('getMode') - ->will($this->returnValue(\Magento\Framework\App\State::MODE_DEVELOPER)); + $this->registry = $this->getMock('Magento\Framework\Registry', [], [], '', false); - $kernel = $this->getMock('Magento\Framework\App\PageCache\Kernel', [], [], '', false); - $kernel->expects($processCount)->method('process')->with($response); + $config = $this->getMock('Magento\PageCache\Model\Config', ['isEnabled', 'getType'], [], '', false); + $config->expects($this->any())->method('isEnabled')->willReturn(true); + $config->expects($this->any())->method('getType')->willReturn(\Magento\PageCache\Model\Config::BUILT_IN); - $subject = $this->getMock('Magento\Framework\Controller\ResultInterface', [], [], '', false); + $this->kernel = $this->getMock('Magento\Framework\App\PageCache\Kernel', [], [], '', false); - /** @var \Magento\PageCache\Model\Controller\Result\BuiltinPlugin $plugin */ - $plugin = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + $this->state = $this->getMock('Magento\Framework\App\State', [], [], '', false); + $this->plugin = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( 'Magento\PageCache\Model\Controller\Result\BuiltinPlugin', [ - 'registry' => $registry, + 'registry' => $this->registry, 'config' => $config, - 'kernel' => $kernel, - 'state' => $state + 'kernel' => $this->kernel, + 'state' => $this->state ] ); - $this->assertSame($result, $plugin->aroundRenderResult($subject, $closure, $response)); } - /** - * @return array - */ - public function dataProvider() + public function testAroundResultWithoutPlugin() { - return [ - [true, $this->once(), $this->at(1), $this->at(2), $this->once(), $this->once()], - [false, $this->never(), $this->never(), $this->never(), $this->never(), $this->never()] - ]; + $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(false); + $this->kernel->expects($this->never())->method('process')->with($this->response); + $this->assertSame( + call_user_func($this->closure), + $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response) + ); + } + + public function testAroundResultWithPlugin() + { + $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(true); + $this->state->expects($this->once())->method('getMode')->willReturn(null); + $this->header->expects($this->any())->method('getFieldValue')->willReturn('tag,tag'); + $this->response->expects($this->once())->method('clearHeader')->with('X-Magento-Tags'); + $this->response->expects($this->once())->method('setHeader')->with( + 'X-Magento-Tags', + 'tag,' . \Magento\PageCache\Model\Cache\Type::CACHE_TAG + ); + $this->kernel->expects($this->once())->method('process')->with($this->response); + $result = call_user_func($this->closure); + $this->assertSame($result, $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response)); + } + + public function testAroundResultWithPluginDeveloperMode() + { + $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(true); + $this->state->expects($this->once())->method('getMode') + ->willReturn(\Magento\Framework\App\State::MODE_DEVELOPER); + + $this->header->expects($this->any())->method('getFieldValue')->willReturnOnConsecutiveCalls('test', 'tag,tag2'); + + $this->response->expects($this->any())->method('setHeader')->withConsecutive( + ['X-Magento-Cache-Control', 'test'], + ['X-Magento-Cache-Debug', 'MISS', true], + ['X-Magento-Tags', 'tag,tag2,' . \Magento\PageCache\Model\Cache\Type::CACHE_TAG] + ); + + $this->response->expects($this->once())->method('clearHeader')->with('X-Magento-Tags'); + $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin') + ->will($this->returnValue(true)); + $this->kernel->expects($this->once())->method('process')->with($this->response); + + $result = call_user_func($this->closure); + $this->assertSame($result, $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response)); } } From 87d089e90db3ed704c3eb06e577e5c2b98737de2 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Wed, 28 Oct 2015 16:48:29 +0200 Subject: [PATCH 22/23] MAGETWO-44110: Product swatch attributes available for attribute type price --- .../adminhtml/templates/catalog/product/attribute/js.phtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml index 034d25f9c1ba8..c407178e0be98 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml @@ -265,10 +265,10 @@ require([ setRowVisibility('is_unique', false); setRowVisibility('frontend_class', false); break; - helper('Magento\Catalog\Helper\Data')->getAttributeHiddenFields() ?> + helper('Magento\Catalog\Helper\Data')->getAttributeHiddenFields() ?> $fields): ?> - case 'escapeHtml($type); ?>': + case 'escapeHtml($type); ?>': getFrontTab().hide(); @@ -280,7 +280,7 @@ require([ scopeVisibility = false; - setRowVisibility('escapeHtml($one); ?>', false); + setRowVisibility('escapeHtml($one); ?>', false); break; From 3f586711d78a1d511a69f6325621fabd42595344 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Wed, 28 Oct 2015 16:49:05 +0200 Subject: [PATCH 23/23] MAGETWO-43900: Imported products with broken images link don't appear on front --- .../Import/ErrorProcessing/ProcessingErrorAggregatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7877a5c3a2609..090370a728a68 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 @@ -130,7 +130,7 @@ public function testAddErrorMessageTemplate() */ public function testIsRowInvalid($errorLevel, $rowNumber, $isValid) { - $this->model->addError('systemException', $errorLevel, $rowNumber, 'Some column name', 'Message', 'Description'); + $this->model->addError('systemException', $errorLevel, $rowNumber, 'Column name', 'Message', 'Description'); $result = $this->model->isRowInvalid($rowNumber); $this->assertEquals($isValid, $result); }