From 0e3aa6e5203663762d1c93e1d0a3b637b3ad9478 Mon Sep 17 00:00:00 2001 From: Kateryna Muntianu Date: Fri, 8 Apr 2016 16:02:00 +0300 Subject: [PATCH 01/17] MAGETWO-51714: Improve error messages for functional tests --- .../Product/ProductList/PromotedSection.php | 4 ++++ .../Block/Product/ProductList/Related.php | 4 ++++ .../Constraint/AssertCategoryBreadcrumbs.php | 4 ++++ .../AssertCategoryForAssignedProducts.php | 2 +- .../Constraint/AssertProductCrossSells.php | 3 ++- .../AssertProductRelatedProducts.php | 3 ++- .../Test/Constraint/AssertProductUpSells.php | 3 ++- .../Test/Repository/CatalogProductSimple.xml | 20 +++++++++---------- .../Test/Repository/CatalogProductVirtual.xml | 4 ++-- 9 files changed, 31 insertions(+), 16 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/PromotedSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/PromotedSection.php index db0cab463a417..0f7c04da94bdf 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/PromotedSection.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/PromotedSection.php @@ -62,6 +62,10 @@ public function getProductItem(FixtureInterface $product) */ public function getProducts() { + if (!$this->_rootElement->isVisible($this->productItem)) { + return []; + } + $elements = $this->_rootElement->getElements($this->productItem, Locator::SELECTOR_CSS); $result = []; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/Related.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/Related.php index f1b1e029f62d4..c81cab9de5297 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/Related.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ProductList/Related.php @@ -38,6 +38,10 @@ public function getProductItem(FixtureInterface $product) */ public function getProducts() { + if (!$this->_rootElement->isVisible($this->productItem)) { + return []; + } + $elements = $this->_rootElement->getElements($this->productItem, Locator::SELECTOR_CSS); $result = []; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryBreadcrumbs.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryBreadcrumbs.php index b5102db734e42..c1ed4c8bbd182 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryBreadcrumbs.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryBreadcrumbs.php @@ -45,6 +45,10 @@ public function processAssert( $this->openCategory($category); $breadcrumbs = $this->getBreadcrumbs($category); + \PHPUnit_Framework_Assert::assertNotEmpty( + $breadcrumbs, + 'No breadcrumbs on category \''. $category->getName() . '\' page.' + ); $pageBreadcrumbs = $catalogCategoryView->getBreadcrumbs()->getText(); \PHPUnit_Framework_Assert::assertEquals( $breadcrumbs, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryForAssignedProducts.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryForAssignedProducts.php index 936d00040de48..25166e66073f4 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryForAssignedProducts.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryForAssignedProducts.php @@ -40,7 +40,7 @@ public function processAssert( foreach ($products as $productFixture) { \PHPUnit_Framework_Assert::assertTrue( $categoryView->getListProductBlock()->getProductItem($productFixture)->isVisible(), - "Products '{$productFixture->getName()}' not found." + "Products '{$productFixture->getName()}' not found in category '{$category->getName()}'." ); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCrossSells.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCrossSells.php index 7cad535e5e02c..b053218966634 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCrossSells.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCrossSells.php @@ -51,7 +51,8 @@ public function processAssert( $checkoutCart->open(); foreach ($promotedProducts as $promotedProduct) { if (!$checkoutCart->getCrosssellBlock()->getProductItem($promotedProduct)->isVisible()) { - $errors[] = 'Product \'' . $promotedProduct->getName() . '\' is absent in cross-sell section.'; + $errors[] = 'Product \'' . $promotedProduct->getName() + . '\' is absent in cross-sell section of a product \'' . $product->getName() . '\'.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductRelatedProducts.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductRelatedProducts.php index bc1a6cfbc35f4..cb3db6bd63488 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductRelatedProducts.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductRelatedProducts.php @@ -46,7 +46,8 @@ public function processAssert( foreach ($promotedProducts as $promotedProduct) { \PHPUnit_Framework_Assert::assertTrue( $catalogProductView->getRelatedProductBlock()->getProductItem($promotedProduct)->isVisible(), - 'Product \'' . $promotedProduct->getName() . '\' is absent in related products.' + 'Product \'' . $promotedProduct->getName() + . '\' is absent in related products \'' . $product->getName() . '\'.' ); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductUpSells.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductUpSells.php index e85edcdbd081b..f35a3004fda6d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductUpSells.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductUpSells.php @@ -46,7 +46,8 @@ public function processAssert( foreach ($promotedProducts as $promotedProduct) { \PHPUnit_Framework_Assert::assertTrue( $catalogProductView->getUpsellBlock()->getProductItem($promotedProduct)->isVisible(), - 'Product \'' . $promotedProduct->getName() . '\' is absent in up-sells products.' + 'Product \'' . $promotedProduct->getName() + . '\' is absent in up-sells products of a product \'' . $product->getName() . '\'.' ); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml index 6ca96f063ea9b..b79d1b61709dd 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml @@ -227,7 +227,7 @@ product_100_dollar%isolation% product_100_dollar%isolation% - 666.0000 + 777.0000 In Stock This item has weight @@ -252,7 +252,7 @@ product_40_dollar%isolation% simple - 666 + 777 In Stock This item has weight @@ -277,7 +277,7 @@ default - 666 + 777 In Stock This item has weight @@ -300,7 +300,7 @@ simple_product_with_category_%isolation% Simple product with category %isolation% - 666 + 777 In Stock This item has weight @@ -349,7 +349,7 @@ default - 666 + 777 In Stock Simple Product %isolation% @@ -487,7 +487,7 @@ None - 666 + 777 In Stock This item has weight @@ -511,7 +511,7 @@ None - 666 + 777 In Stock This item has weight @@ -535,7 +535,7 @@ None - 666 + 777 In Stock This item has weight @@ -559,7 +559,7 @@ taxable_goods - 666 + 777 In Stock This item has weight @@ -973,7 +973,7 @@ simple_product_with_category_%isolation% Simple product with category %isolation% - 666 + 777 In Stock This item has weight diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml index 910d475e83a20..dacbc77bb4e5a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml @@ -23,7 +23,7 @@ Virtual product %isolation% sku_virtual_product_%isolation% - 666 + 777 In Stock @@ -110,7 +110,7 @@ Virtual product %isolation% sku_virtual_product_%isolation% - 666 + 777 In Stock From 8ce01894d07d5c8bbb4922303f2a2be1873c7224 Mon Sep 17 00:00:00 2001 From: Kateryna Muntianu Date: Mon, 11 Apr 2016 17:26:08 +0300 Subject: [PATCH 02/17] MAGETWO-51775: [FT] CreateCategoryEntityTest fails because date/time format has changed --- .../Category/CreateCategoryEntityTest.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index e69adac6123d9..7e6f913dda6e7 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -36,11 +36,11 @@ custom meta keywords %isolation% Custom meta description %isolation% 2 columns with right bar - LAYOUT UPDATE XML - Yes - 01/10/2014 - 12/31/2024 + <referenceContainer name="catalog.leftnav" remove="true"/> Magento Luma + Yes + Jan 10, 2014 + Dec 31, 2024 @@ -79,11 +79,11 @@ Custom meta description %isolation% catalogProductSimple::default,catalogProductSimple::default 2 columns with right bar - LAYOUT UPDATE XML - Yes - 01/10/2014 - 12/31/2024 + <referenceContainer name="content.aside" remove="true"/> Magento Luma + Yes + Jan 1, 2014 + Dec 31, 2024 From f7bb0ef953dcb7f60a31508347ac41735daa8af3 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 11 Apr 2016 17:28:51 +0300 Subject: [PATCH 03/17] MAGETWO-51540: Linked indexers catalog_category_product and catalog_product_cateogry do not set valid status after shell run --- .../Console/Command/IndexerReindexCommand.php | 78 ++++++++++++++++--- .../Command/IndexerReindexCommandTest.php | 34 ++++++-- 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php index 0be86320e6ca7..6668b37bf8e20 100644 --- a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php +++ b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php @@ -16,6 +16,16 @@ */ class IndexerReindexCommand extends AbstractIndexerManageCommand { + /** + * @var array + */ + private $sharedIndexesComplete = []; + + /** + * @var \Magento\Framework\Indexer\ConfigInterface + */ + private $config; + /** * {@inheritdoc} */ @@ -34,21 +44,18 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $indexers = $this->getIndexers($input); - $config = $this->getConfig(); - $sharedIndexesComplete = []; foreach ($indexers as $indexer) { try { $startTime = microtime(true); - $indexerConfig = $config->getIndexer($indexer->getId()); + $indexerConfig = $this->getConfig()->getIndexer($indexer->getId()); + $sharedIndex = $indexerConfig['shared_index']; // Skip indexers having shared index that was already complete - if (!in_array($indexerConfig['shared_index'], $sharedIndexesComplete)) { + if (!in_array($sharedIndex, $this->sharedIndexesComplete)) { $indexer->reindexAll(); - } else { - $indexer->getState()->setStatus(StateInterface::STATUS_VALID)->save(); - } - if ($indexerConfig['shared_index']) { - $sharedIndexesComplete[] = $indexerConfig['shared_index']; + if ($sharedIndex) { + $this->validateSharedIndex($sharedIndex); + } } $resultTime = microtime(true) - $startTime; $output->writeln( @@ -63,6 +70,54 @@ protected function execute(InputInterface $input, OutputInterface $output) } } + /** + * Get indexer ids that have common shared index + * + * @param $sharedIndex + * @return array + */ + private function getIndexerIdsBySharedIndex($sharedIndex) + { + $indexers = $this->getConfig()->getIndexers(); + $result = []; + foreach ($indexers as $indexerCode => $indexerConfig) { + if ($indexerConfig['shared_index'] == $sharedIndex) { + $result[] = $indexerConfig['indexer_id']; + } + } + return $result; + } + + /** + * Validate indexers by shared index ID + * + * @param $sharedIndex + * @return $this + */ + private function validateSharedIndex($sharedIndex) + { + if (empty($sharedIndex)) { + throw new \InvalidArgumentException('sharedIndex must be a valid indexer ID'); + } + $indexerIds = $this->getIndexerIdsBySharedIndex($sharedIndex); + if (empty($indexerIds)) { + return $this; + } + $indexerFactory = $this->getObjectManager()->create('Magento\Indexer\Model\IndexerFactory'); + foreach ($indexerIds as $indexerId) { + /** @var \Magento\Indexer\Model\Indexer $indexer */ + $indexer = $indexerFactory->create(); + $indexer->load($indexerId); + /** @var \Magento\Indexer\Model\Indexer\State $state */ + $state = $indexer->getState(); + $state->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_VALID); + $state->save(); + } + $this->sharedIndexesComplete[] = $sharedIndex; + return $this; + } + + /** * Get config * @@ -71,6 +126,9 @@ protected function execute(InputInterface $input, OutputInterface $output) */ private function getConfig() { - return $this->getObjectManager()->get(ConfigInterface::class); + if (!$this->config) { + $this->config = $this->getObjectManager()->get(ConfigInterface::class); + } + return $this->config; } } diff --git a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerReindexCommandTest.php b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerReindexCommandTest.php index f6e8b6622e4a9..40923b6418ce4 100644 --- a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerReindexCommandTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerReindexCommandTest.php @@ -86,36 +86,60 @@ public function testExecuteWithIndex() ['id_indexer3', ['title' => 'Title_indexer3', 'shared_index' => 'with_indexer_3']] ] )); + $this->configMock->expects($this->any()) + ->method('getIndexers') + ->will($this->returnValue( + [ + 'id_indexerOne' => [ + 'indexer_id' => 'id_indexerOne', + 'title' => 'Title_indexerOne', + 'shared_index' => null + ], + 'id_indexerTwo' => [ + 'indexer_id' => 'id_indexerTwo', + 'title' => 'Title_indexerTwo', + 'shared_index' => 'with_indexer_3' + ], + 'id_indexer3' => [ + 'indexer_id' => 'id_indexer3', + 'title' => 'Title_indexer3', + 'shared_index' => 'with_indexer_3' + ] + ] + )); $this->configureAdminArea(); $indexerOne = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false); $indexerOne->expects($this->once())->method('reindexAll'); $indexerOne->expects($this->once())->method('getTitle')->willReturn('Title_indexerOne'); $indexerOne->expects($this->any())->method('getId')->willReturn('id_indexerOne'); - $indexerOne->expects($this->once())->method('load')->with('id_indexerOne')->willReturn($indexerOne); + $indexerOne->expects($this->any())->method('load')->with('id_indexerOne')->willReturn($indexerOne); $indexerTwo = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false); $indexerTwo->expects($this->once())->method('reindexAll'); $indexerTwo->expects($this->once())->method('getTitle')->willReturn('Title_indexerTwo'); $indexerTwo->expects($this->any())->method('getId')->willReturn('id_indexerTwo'); - $indexerTwo->expects($this->once())->method('load')->with('id_indexerTwo')->willReturn($indexerTwo); + $indexerTwo->expects($this->any())->method('load')->with('id_indexerTwo')->willReturn($indexerTwo); $indexer3 = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false); $indexer3->expects($this->never())->method('reindexAll'); $indexer3->expects($this->once())->method('getTitle')->willReturn('Title_indexer3'); $indexer3->expects($this->any())->method('getId')->willReturn('id_indexer3'); - $indexer3->expects($this->once())->method('load')->with('id_indexer3')->willReturn($indexer3); + $indexer3->expects($this->any())->method('load')->with('id_indexer3')->willReturn($indexer3); $stateMock = $this->getMock(\Magento\Indexer\Model\Indexer\State::class, [], [], '', false); - $stateMock->expects($this->once())->method('setStatus')->will($this->returnSelf()); - $stateMock->expects($this->once())->method('save'); + $stateMock->expects($this->exactly(2))->method('setStatus')->will($this->returnSelf()); + $stateMock->expects($this->exactly(2))->method('save'); $indexer3->expects($this->once())->method('getState')->willReturn($stateMock); + $indexerTwo->expects($this->once())->method('getState')->willReturn($stateMock); $this->collectionFactory->expects($this->never())->method('create'); $this->indexerFactory->expects($this->at(0))->method('create')->willReturn($indexerOne); $this->indexerFactory->expects($this->at(1))->method('create')->willReturn($indexerTwo); $this->indexerFactory->expects($this->at(2))->method('create')->willReturn($indexer3); + $this->indexerFactory->expects($this->at(3))->method('create')->willReturn($indexerTwo); + $this->indexerFactory->expects($this->at(4))->method('create')->willReturn($indexer3); $this->command = new IndexerReindexCommand($this->objectManagerFactory); $commandTester = new CommandTester($this->command); From 0bea0768b152525a08bf4478d8c3c863ce1c9210 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 11 Apr 2016 17:33:21 +0300 Subject: [PATCH 04/17] MAGETWO-51540: Linked indexers catalog_category_product and catalog_product_cateogry do not set valid status after shell run --- .../Magento/Indexer/Console/Command/IndexerReindexCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php index 6668b37bf8e20..59bc26b97633f 100644 --- a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php +++ b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php @@ -97,7 +97,7 @@ private function getIndexerIdsBySharedIndex($sharedIndex) private function validateSharedIndex($sharedIndex) { if (empty($sharedIndex)) { - throw new \InvalidArgumentException('sharedIndex must be a valid indexer ID'); + throw new \InvalidArgumentException('sharedIndex must be a valid shared index identifier'); } $indexerIds = $this->getIndexerIdsBySharedIndex($sharedIndex); if (empty($indexerIds)) { From 69aa839e9d2a765beb0966ffec7cb859c45e1641 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov Date: Mon, 11 Apr 2016 17:36:20 +0300 Subject: [PATCH 05/17] MAGETWO-51731: Catalog Price Rule applied despite time frames --- app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php b/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php index d2aac2a8369e9..87340140ada3f 100644 --- a/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php +++ b/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php @@ -724,7 +724,7 @@ protected function critical($e) private function roundTime($timeStamp) { if (is_numeric($timeStamp) && $timeStamp != 0) { - $timeStamp = $this->dateTime->timestamp($this->dateTime->date('Y-m-d 00:00:00')); + $timeStamp = $this->dateTime->timestamp($this->dateTime->date('Y-m-d 00:00:00', $timeStamp)); } return $timeStamp; From 1fcc0c7f100f2b10dce95ddaa9349801b7efb5ed Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 11 Apr 2016 18:16:09 +0300 Subject: [PATCH 06/17] MAGETWO-51039: Indexer is no longer updated after reindex was interrupted --- .../Console/Command/IndexerReindexCommand.php | 19 ++++++ .../Command/IndexerResetStateCommand.php | 51 +++++++++++++++ app/code/Magento/Indexer/README.md | 12 +++- .../Command/IndexerResetStateCommandTest.php | 64 +++++++++++++++++++ app/code/Magento/Indexer/etc/di.xml | 1 + 5 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Indexer/Console/Command/IndexerResetStateCommand.php create mode 100644 app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerResetStateCommandTest.php diff --git a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php index 59bc26b97633f..1832dbc044284 100644 --- a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php +++ b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php @@ -46,6 +46,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $indexers = $this->getIndexers($input); foreach ($indexers as $indexer) { try { + $this->validateIndexerStatus($indexer); $startTime = microtime(true); $indexerConfig = $this->getConfig()->getIndexer($indexer->getId()); $sharedIndex = $indexerConfig['shared_index']; @@ -70,6 +71,24 @@ protected function execute(InputInterface $input, OutputInterface $output) } } + /** + * Validate that indexer is not locked + * + * @param \Magento\Framework\Indexer\IndexerInterface $indexer + * @throws LocalizedException + */ + private function validateIndexerStatus(\Magento\Framework\Indexer\IndexerInterface $indexer) + { + if ($indexer->getStatus() == \Magento\Framework\Indexer\StateInterface::STATUS_WORKING) { + throw new LocalizedException( + __( + '%1 index is locked by another reindex process. Skipping.', + $indexer->getTitle() + ) + ); + } + } + /** * Get indexer ids that have common shared index * diff --git a/app/code/Magento/Indexer/Console/Command/IndexerResetStateCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerResetStateCommand.php new file mode 100644 index 0000000000000..3b1e952d1e619 --- /dev/null +++ b/app/code/Magento/Indexer/Console/Command/IndexerResetStateCommand.php @@ -0,0 +1,51 @@ +setName('indexer:reset') + ->setDescription('Resets indexer status to invalid') + ->setDefinition($this->getInputList()); + + parent::configure(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $indexers = $this->getIndexers($input); + foreach ($indexers as $indexer) { + try { + $indexer->getState() + ->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID) + ->save(); + $output->writeln($indexer->getTitle() . ' indexer has been invalidated.'); + } catch (LocalizedException $e) { + $output->writeln($e->getMessage()); + } catch (\Exception $e) { + $output->writeln($indexer->getTitle() . ' indexer process unknown error:'); + $output->writeln($e->getMessage()); + } + } + } +} diff --git a/app/code/Magento/Indexer/README.md b/app/code/Magento/Indexer/README.md index fe6d85ba0fcab..b0a88d12ad0ed 100644 --- a/app/code/Magento/Indexer/README.md +++ b/app/code/Magento/Indexer/README.md @@ -1,4 +1,12 @@ +## Overview Magento_Indexer module is a base of Magento Indexing functionality. -It allows to read indexers configuration, represent indexers in admin, control their mode, regenerate indexers by schedule. +It allows: + - read indexers configuration, + - represent indexers in admin, + - regenerate indexes by cron schedule, + - regenerate indexes from console, + - view and reset indexer state from console, + - view and set indexer mode from console + There are 2 modes of the Indexers: "Update on save" and "Update by schedule". -Manual re-index can be performed via console by running index.php script. +Manual full reindex can be performed via console by running `php -f bin/magento indexer:reindex` console command. \ No newline at end of file diff --git a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerResetStateCommandTest.php b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerResetStateCommandTest.php new file mode 100644 index 0000000000000..5dac864ab277b --- /dev/null +++ b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerResetStateCommandTest.php @@ -0,0 +1,64 @@ +stateMock->expects($this->once())->method('setAreaCode')->with(FrontNameResolver::AREA_CODE); + } + + public function testExecute() + { + $this->configureAdminArea(); + $collection = $this->getMock('Magento\Indexer\Model\Indexer\Collection', [], [], '', false); + $indexerOne = $this->getMock('Magento\Indexer\Model\Indexer', [], [], '', false); + + $indexerOne->expects($this->once()) + ->method('getTitle') + ->willReturn('Title_indexerOne'); + + $collection->expects($this->once()) + ->method('getItems') + ->willReturn([$indexerOne]); + + $stateMock = $this->getMock(\Magento\Indexer\Model\Indexer\State::class, [], [], '', false); + $stateMock->expects($this->exactly(1)) + ->method('setStatus') + ->with(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID) + ->will($this->returnSelf()); + + $stateMock->expects($this->exactly(1)) + ->method('save'); + + $indexerOne->expects($this->once()) + ->method('getState') + ->willReturn($stateMock); + + $this->collectionFactory->expects($this->once()) + ->method('create') + ->will($this->returnValue($collection)); + + $this->command = new IndexerResetStateCommand($this->objectManagerFactory); + $commandTester = new CommandTester($this->command); + $commandTester->execute([]); + $actualValue = $commandTester->getDisplay(); + $this->assertSame(sprintf('Title_indexerOne indexer has been invalidated.') . PHP_EOL, $actualValue); + } +} diff --git a/app/code/Magento/Indexer/etc/di.xml b/app/code/Magento/Indexer/etc/di.xml index 019dad475a553..b29cc6ca71d1a 100644 --- a/app/code/Magento/Indexer/etc/di.xml +++ b/app/code/Magento/Indexer/etc/di.xml @@ -51,6 +51,7 @@ Magento\Indexer\Console\Command\IndexerSetModeCommand Magento\Indexer\Console\Command\IndexerShowModeCommand Magento\Indexer\Console\Command\IndexerStatusCommand + Magento\Indexer\Console\Command\IndexerResetStateCommand From eed3c86ae05105db504b3f5245d65a55f516e6d2 Mon Sep 17 00:00:00 2001 From: Kateryna Muntianu Date: Tue, 12 Apr 2016 11:19:48 +0300 Subject: [PATCH 07/17] MAGETWO-51775: [FT] CreateCategoryEntityTest fails because date/time format has changed --- .../Test/Block/Adminhtml/Category/Edit/CategoryForm.xml | 8 ++++---- .../tests/app/Magento/Catalog/Test/Fixture/Category.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml index 03c5cd3c02995..593ab70e100ff 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml @@ -110,6 +110,10 @@ checkbox input[name='custom_use_parent_settings'] + + select + select[name='custom_design'] + select select[name='page_layout'] @@ -137,10 +141,6 @@ text input[name='custom_design_to'] - - select - select[name='custom_design'] - diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml index eb4967eec2616..b9ba495535e82 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml @@ -46,11 +46,11 @@ + - From 795fac1ac4d0311f6709f3af2befae7103dffec4 Mon Sep 17 00:00:00 2001 From: Volodymyr Klymenko Date: Tue, 12 Apr 2016 14:37:31 +0300 Subject: [PATCH 08/17] MAGETWO-51490: Does not work regular price change in the simple product with custom options --- .../Magento/Catalog/Model/Product/Option.php | 22 +++++++++++++++- .../Test/Unit/Model/Product/OptionTest.php | 25 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php index 86ed6714529d8..0c47ac11b2282 100644 --- a/app/code/Magento/Catalog/Model/Product/Option.php +++ b/app/code/Magento/Catalog/Model/Product/Option.php @@ -30,6 +30,11 @@ */ class Option extends AbstractExtensibleModel implements ProductCustomOptionInterface { + /** + * Option type percent + */ + const TYPE_PERCENT = 'percent'; + const OPTION_GROUP_TEXT = 'text'; const OPTION_GROUP_FILE = 'file'; @@ -424,7 +429,7 @@ public function afterSave() */ public function getPrice($flag = false) { - if ($flag && $this->getPriceType() == 'percent') { + if ($flag && $this->getPriceType() == self::TYPE_PERCENT) { $basePrice = $this->getProduct()->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getValue(); $price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100); return $price; @@ -827,6 +832,21 @@ public function getExtensionAttributes() return $this->_getExtensionAttributes(); } + /** + * Return regular price. + * + * @return float|int + */ + public function getRegularPrice() + { + if ($this->getPriceType() == self::TYPE_PERCENT) { + $basePrice = $this->getProduct()->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue(); + $price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100); + return $price; + } + return $this->_getData(self::KEY_PRICE); + } + /** * @param Product $product * @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php index 8b938938c20e1..9d71f05b9fb70 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Test\Unit\Model\Product; +use \Magento\Catalog\Model\Product\Option; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class OptionTest extends \PHPUnit_Framework_TestCase @@ -33,4 +34,28 @@ public function testGetProductSku() $this->productMock->expects($this->once())->method('getSku')->willReturn($productSku); $this->assertEquals($productSku, $this->model->getProductSku()); } + + public function testGetRegularPrice() + { + $priceInfoMock = $this->getMockForAbstractClass('Magento\Framework\Pricing\PriceInfoInterface', + [], + '', + false, + false, + true, + ['getAmount', 'getPrice'] + ); + $priceInfoMock->expects($this->once())->method('getPrice')->willReturnSelf(); + $amountMock = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); + $priceInfoMock->expects($this->once())->method('getAmount')->willReturn($amountMock); + + $this->productMock->expects($this->once())->method('getPriceInfo')->willReturn($priceInfoMock); + + $amountMock->expects($this->once())->method('getValue')->willReturn(50); + $this->model->setPrice(50); + $this->model->setPriceType(Option::TYPE_PERCENT); + $this->assertEquals(25, $this->model->getRegularPrice()); + $this->model->setPriceType(null); + $this->assertEquals(50, $this->model->getRegularPrice()); + } } From 41dad766b80d2b600855c074cde803d6cc313f02 Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Tue, 12 Apr 2016 15:01:58 +0300 Subject: [PATCH 09/17] MAGETWO-51039: Indexer is no longer updated after reindex was interrupted - CR fixes --- .../Indexer/Console/Command/IndexerReindexCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php index 1832dbc044284..6dc61d9110a5f 100644 --- a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php +++ b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php @@ -75,6 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output) * Validate that indexer is not locked * * @param \Magento\Framework\Indexer\IndexerInterface $indexer + * @return void * @throws LocalizedException */ private function validateIndexerStatus(\Magento\Framework\Indexer\IndexerInterface $indexer) @@ -92,14 +93,14 @@ private function validateIndexerStatus(\Magento\Framework\Indexer\IndexerInterfa /** * Get indexer ids that have common shared index * - * @param $sharedIndex + * @param string $sharedIndex * @return array */ private function getIndexerIdsBySharedIndex($sharedIndex) { $indexers = $this->getConfig()->getIndexers(); $result = []; - foreach ($indexers as $indexerCode => $indexerConfig) { + foreach ($indexers as $indexerConfig) { if ($indexerConfig['shared_index'] == $sharedIndex) { $result[] = $indexerConfig['indexer_id']; } @@ -110,7 +111,7 @@ private function getIndexerIdsBySharedIndex($sharedIndex) /** * Validate indexers by shared index ID * - * @param $sharedIndex + * @param string $sharedIndex * @return $this */ private function validateSharedIndex($sharedIndex) @@ -136,7 +137,6 @@ private function validateSharedIndex($sharedIndex) return $this; } - /** * Get config * From 69ef10f47a8d008e1bca65fa8a38912e5524125c Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Mon, 11 Apr 2016 13:19:07 +0300 Subject: [PATCH 10/17] MAGETWO-51751: Unable to filter by date Product Reviews report --- .../Model/ResourceModel/Review/Product/Collection.php | 4 ++-- .../adminhtml/layout/reports_report_review_product_grid.xml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) 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 ccfbc983aab67..dae41f6d59a4f 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php @@ -47,7 +47,7 @@ protected function _joinReview() 'e.entity_id = r.entity_pk_value', [ 'review_cnt' => new \Zend_Db_Expr(sprintf('(%s)', $subSelect)), - 'last_created' => 'MAX(r.created_at)' + 'created_at' => 'MAX(r.created_at)' ] )->group( 'e.entity_id' @@ -83,7 +83,7 @@ protected function _joinReview() */ public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC) { - if (in_array($attribute, ['review_cnt', 'last_created', 'avg_rating', 'avg_rating_approved'])) { + if (in_array($attribute, ['review_cnt', 'created_at', 'avg_rating', 'avg_rating_approved'])) { $this->getSelect()->order($attribute . ' ' . $dir); return $this; } diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml index 094740686678f..c795a9e29223c 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml @@ -86,12 +86,12 @@ col-avg-rating - + Last Review datetime - last_created - last_created + created_at + created_at col-date col-date From 8808a68489dbe82bfca270ce107e03ca4ce24cdc Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Tue, 12 Apr 2016 18:36:33 +0300 Subject: [PATCH 11/17] MAGETWO-51490: Does not work regular price change in the simple product with custom options --- .../Magento/Catalog/Test/Unit/Model/Product/OptionTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php index 9d71f05b9fb70..4bddb357d1614 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php @@ -37,7 +37,8 @@ public function testGetProductSku() public function testGetRegularPrice() { - $priceInfoMock = $this->getMockForAbstractClass('Magento\Framework\Pricing\PriceInfoInterface', + $priceInfoMock = $this->getMockForAbstractClass( + 'Magento\Framework\Pricing\PriceInfoInterface', [], '', false, From dbaf56a4c3aec15a8869cae263a79224606bc43d Mon Sep 17 00:00:00 2001 From: Volodymyr Klymenko Date: Wed, 13 Apr 2016 12:17:35 +0300 Subject: [PATCH 12/17] MAGETWO-51490: Does not work regular price change in the simple product with custom options --- app/code/Magento/Catalog/Model/Product/Option.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php index 0c47ac11b2282..2c9e09f8aff30 100644 --- a/app/code/Magento/Catalog/Model/Product/Option.php +++ b/app/code/Magento/Catalog/Model/Product/Option.php @@ -30,11 +30,6 @@ */ class Option extends AbstractExtensibleModel implements ProductCustomOptionInterface { - /** - * Option type percent - */ - const TYPE_PERCENT = 'percent'; - const OPTION_GROUP_TEXT = 'text'; const OPTION_GROUP_FILE = 'file'; @@ -68,6 +63,11 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter */ protected $optionRepository; + /** + * Option type percent + */ + protected static $typePercent = 'percent'; + /**#@+ * Constants */ @@ -429,7 +429,7 @@ public function afterSave() */ public function getPrice($flag = false) { - if ($flag && $this->getPriceType() == self::TYPE_PERCENT) { + if ($flag && $this->getPriceType() == self::$typePercent) { $basePrice = $this->getProduct()->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getValue(); $price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100); return $price; @@ -839,7 +839,7 @@ public function getExtensionAttributes() */ public function getRegularPrice() { - if ($this->getPriceType() == self::TYPE_PERCENT) { + if ($this->getPriceType() == self::$typePercent) { $basePrice = $this->getProduct()->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue(); $price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100); return $price; From a7c9360ba2673d7bdd62afc14441112bbf76c834 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov Date: Wed, 13 Apr 2016 14:59:31 +0300 Subject: [PATCH 13/17] MAGETWO-47025: [GITHUB] Meta Description For Products is Up to 255 #2749 --- app/code/Magento/Catalog/Setup/UpgradeData.php | 13 +++++++++++++ app/code/Magento/Catalog/etc/module.xml | 2 +- app/code/Magento/Eav/Setup/EavSetup.php | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Setup/UpgradeData.php b/app/code/Magento/Catalog/Setup/UpgradeData.php index 542fea6770fab..ab32e8c5a6c7d 100644 --- a/app/code/Magento/Catalog/Setup/UpgradeData.php +++ b/app/code/Magento/Catalog/Setup/UpgradeData.php @@ -338,7 +338,20 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } + + if (version_compare($context->getVersion(), '2.0.7') < 0) { + /** @var EavSetup $eavSetupF */ + $eavSetup= $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'meta_description', + [ + 'note' => 'Maximum 255 chars. Meta Description should optimally be between 150-160 characters' + ] + ); + } + $setup->endSetup(); } } diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index ac6a681cd5ebd..87e82543fc65b 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Eav/Setup/EavSetup.php b/app/code/Magento/Eav/Setup/EavSetup.php index b585435dee2c5..a53ed60774749 100644 --- a/app/code/Magento/Eav/Setup/EavSetup.php +++ b/app/code/Magento/Eav/Setup/EavSetup.php @@ -909,7 +909,7 @@ public function addAttributeOption($option) * * @param int|string $entityTypeId * @param int|string $id - * @param string $field + * @param string|array $field * @param mixed $value * @param int $sortOrder * @return $this From de48ec28ab4e3ee8e203a948b25d512a1d4c0510 Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Wed, 13 Apr 2016 18:02:02 +0300 Subject: [PATCH 14/17] MAGETWO-48688: New category with invalid data loses entered data after validation --- .../Controller/Adminhtml/Category/Add.php | 9 ++++ .../Controller/Adminhtml/Category/Save.php | 44 +++++++++++++++++++ .../Catalog/Model/Category/DataProvider.php | 4 +- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php index 17ed8b762c1e4..26bdc8082ca76 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php @@ -50,6 +50,15 @@ public function execute() return $resultRedirect->setPath('catalog/*/', ['_current' => true, 'id' => null]); } + /** + * Check if we have data in session (if during category save was exception) + */ + $data = $this->_getSession()->getCategoryData(true); + if (isset($data['general'])) { + unset($data['general']['image']); + $category->addData($data['general']); + } + $resultPageFactory = $this->_objectManager->get('Magento\Framework\View\Result\PageFactory'); /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $resultPageFactory->create(); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php index 852c465b1482a..f1138749daa40 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php @@ -50,6 +50,11 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category */ private $storeManager; + /** + * @var \Magento\Framework\Stdlib\DateTime\Filter\DateTime + */ + private $dateTimeFilter; + /** * Constructor * @@ -113,6 +118,7 @@ public function execute() $isNewCategory = !isset($data['general']['entity_id']); $data = $this->stringToBoolConverting($data); $data = $this->imagePreprocessing($data); + $data = $this->dateTimePreprocessing($data, $category); $storeId = isset($data['general']['store_id']) ? $data['general']['store_id'] : null; $store = $this->storeManager->getStore($storeId); $this->storeManager->setCurrentStore($store->getCode()); @@ -338,4 +344,42 @@ protected function getRedirectParams($isNewCategory, $hasError, $categoryId, $pa } return ['path' => $path, 'params' => $params]; } + + /** + * Datetime data preprocessing + * + * @param array $postData + * @param \Magento\Catalog\Model\Category $category + * + * @return array + */ + private function dateTimePreprocessing($postData, $category) + { + $dateFieldFilters = []; + $attributes = $category->getAttributes(); + foreach ($attributes as $attrKey => $attribute) { + if ($attribute->getBackend()->getType() == 'datetime') { + if (array_key_exists($attrKey, $postData['general']) && $postData['general'][$attrKey] != '') { + $dateFieldFilters[$attrKey] = $this->getDateTimeFilter(); + } + } + } + $inputFilter = new \Zend_Filter_Input($dateFieldFilters, [], $postData['general']); + $postData['general'] = $inputFilter->getUnescaped(); + return $postData; + } + + /** + * @return \Magento\Framework\Stdlib\DateTime\Filter\DateTime + * + * @deprecated + */ + private function getDateTimeFilter() + { + if ($this->dateTimeFilter === null) { + $this->dateTimeFilter = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class); + } + return $this->dateTimeFilter; + } } diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index e1d1ee848f288..8626d183e2fac 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -201,9 +201,7 @@ public function getData() return $this->loadedData; } $category = $this->getCurrentCategory(); - if (!$category->getId()) { - return []; - } else { + if ($category) { $categoryData = $category->getData(); $categoryData = $this->addUseDefaultSettings($category, $categoryData); $categoryData = $this->addUseConfigSettings($categoryData); From da6a01b1492705036e3769a3e4718dc63f61965b Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Wed, 13 Apr 2016 18:27:43 +0300 Subject: [PATCH 15/17] MAGETWO-51490: Does not work regular price change in the simple product with custom options --- app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php index 4bddb357d1614..ea01f87a1ad6c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/OptionTest.php @@ -54,7 +54,7 @@ public function testGetRegularPrice() $amountMock->expects($this->once())->method('getValue')->willReturn(50); $this->model->setPrice(50); - $this->model->setPriceType(Option::TYPE_PERCENT); + $this->model->setPriceType(\Magento\Catalog\Model\Product\Option\Value::TYPE_PERCENT); $this->assertEquals(25, $this->model->getRegularPrice()); $this->model->setPriceType(null); $this->assertEquals(50, $this->model->getRegularPrice()); From fa165433995f0a6869bfcedd828f04ebb133c6af Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Thu, 14 Apr 2016 15:15:17 +0300 Subject: [PATCH 16/17] MAGETWO-48688: New category with invalid data loses entered data after validation --- .../Catalog/Controller/Adminhtml/Category.php | 42 +++++++ .../Controller/Adminhtml/Category/Add.php | 8 +- .../Controller/Adminhtml/Category/Edit.php | 12 +- .../Controller/Adminhtml/Category/Save.php | 107 ++++++------------ .../Category/Attribute/Backend/Image.php | 3 + 5 files changed, 87 insertions(+), 85 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php index 63a9842808a71..366202df27ee7 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php @@ -17,6 +17,11 @@ abstract class Category extends \Magento\Backend\App\Action */ const ADMIN_RESOURCE = 'Magento_Catalog::categories'; + /** + * @var \Magento\Framework\Stdlib\DateTime\Filter\DateTime + */ + private $dateTimeFilter; + /** * Initialize requested category and put it into registry. * Root category can be returned, if inappropriate store/category is specified @@ -107,4 +112,41 @@ protected function ajaxRequestResponse($category, $resultPage) $resultJson->setData($eventResponse->getData()); return $resultJson; } + + /** + * @return \Magento\Framework\Stdlib\DateTime\Filter\DateTime + * + * @deprecated + */ + private function getDateTimeFilter() + { + if ($this->dateTimeFilter === null) { + $this->dateTimeFilter = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class); + } + return $this->dateTimeFilter; + } + + /** + * Datetime data preprocessing + * + * @param \Magento\Catalog\Model\Category $category + * @param array $postData + * + * @return array + */ + protected function dateTimePreprocessing($category, $postData) + { + $dateFieldFilters = []; + $attributes = $category->getAttributes(); + foreach ($attributes as $attrKey => $attribute) { + if ($attribute->getBackend()->getType() == 'datetime') { + if (array_key_exists($attrKey, $postData) && $postData[$attrKey] != '') { + $dateFieldFilters[$attrKey] = $this->getDateTimeFilter(); + } + } + } + $inputFilter = new \Zend_Filter_Input($dateFieldFilters, [], $postData); + return $inputFilter->getUnescaped(); + } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php index 26bdc8082ca76..3a28c62b5e76e 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php @@ -53,10 +53,10 @@ public function execute() /** * Check if we have data in session (if during category save was exception) */ - $data = $this->_getSession()->getCategoryData(true); - if (isset($data['general'])) { - unset($data['general']['image']); - $category->addData($data['general']); + $categoryData = $this->_getSession()->getCategoryData(true); + if (is_array($categoryData)) { + unset($categoryData['image']); + $category->addData($categoryData); } $resultPageFactory = $this->_objectManager->get('Magento\Framework\View\Result\PageFactory'); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php index 3f81b2bbd0ea1..cf1061934fec6 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php @@ -82,14 +82,14 @@ public function execute() /** * Check if we have data in session (if during category save was exception) */ - $data = $this->_getSession()->getCategoryData(true); - if (isset($data['general'])) { - if (isset($data['general']['image']['delete'])) { - $data['general']['image'] = null; + $categoryData = $this->_getSession()->getCategoryData(true); + if (is_array($categoryData)) { + if (isset($categoryData['image']['delete'])) { + $categoryData['image'] = null; } else { - unset($data['general']['image']); + unset($categoryData['image']); } - $category->addData($data['general']); + $category->addData($categoryData); } /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php index f1138749daa40..d3878e6eba120 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php @@ -9,7 +9,7 @@ /** * Class Save - * + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Save extends \Magento\Catalog\Controller\Adminhtml\Category @@ -34,15 +34,13 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category * @var array */ protected $stringToBoolInputs = [ - 'general' => [ - 'custom_use_parent_settings', - 'custom_apply_to_products', - 'is_active', - 'include_in_menu', - 'is_anchor', - 'use_default' => ['url_key'], - 'use_config' => ['available_sort_by', 'filter_price_range', 'default_sort_by'] - ] + 'custom_use_parent_settings', + 'custom_apply_to_products', + 'is_active', + 'include_in_menu', + 'is_anchor', + 'use_default' => ['url_key'], + 'use_config' => ['available_sort_by', 'filter_price_range', 'default_sort_by'] ]; /** @@ -50,11 +48,6 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category */ private $storeManager; - /** - * @var \Magento\Framework\Stdlib\DateTime\Filter\DateTime - */ - private $dateTimeFilter; - /** * Constructor * @@ -115,16 +108,18 @@ public function execute() } $data['general'] = $this->getRequest()->getPostValue(); - $isNewCategory = !isset($data['general']['entity_id']); - $data = $this->stringToBoolConverting($data); - $data = $this->imagePreprocessing($data); - $data = $this->dateTimePreprocessing($data, $category); - $storeId = isset($data['general']['store_id']) ? $data['general']['store_id'] : null; + $categoryPostData = $data['general']; + + $isNewCategory = !isset($categoryPostData['entity_id']); + $categoryPostData = $this->stringToBoolConverting($categoryPostData); + $categoryPostData = $this->imagePreprocessing($categoryPostData); + $categoryPostData = $this->dateTimePreprocessing($category, $categoryPostData); + $storeId = isset($categoryPostData['store_id']) ? $categoryPostData['store_id'] : null; $store = $this->storeManager->getStore($storeId); $this->storeManager->setCurrentStore($store->getCode()); - $parentId = isset($data['general']['parent']) ? $data['general']['parent'] : null; - if ($data['general']) { - $category->addData($this->_filterCategoryPostData($data['general'])); + $parentId = isset($categoryPostData['parent']) ? $categoryPostData['parent'] : null; + if ($categoryPostData) { + $category->addData($this->_filterCategoryPostData($categoryPostData)); if ($isNewCategory) { $parentCategory = $this->getParentCategory($parentId, $storeId); $category->setPath($parentCategory->getPath()); @@ -134,10 +129,10 @@ public function execute() /** * Process "Use Config Settings" checkboxes */ - $generalPost = $data['general']; + $useConfig = []; - if (isset($generalPost['use_config']) && !empty($generalPost['use_config'])) { - foreach ($generalPost['use_config'] as $attributeCode => $attributeValue) { + if (isset($categoryPostData['use_config']) && !empty($categoryPostData['use_config'])) { + foreach ($categoryPostData['use_config'] as $attributeCode => $attributeValue) { if ($attributeValue) { $useConfig[] = $attributeCode; $category->setData($attributeCode, null); @@ -147,11 +142,11 @@ public function execute() $category->setAttributeSetId($category->getDefaultAttributeSetId()); - if (isset($data['general']['category_products']) - && is_string($data['general']['category_products']) + if (isset($categoryPostData['category_products']) + && is_string($categoryPostData['category_products']) && !$category->getProductsReadonly() ) { - $products = json_decode($data['general']['category_products'], true); + $products = json_decode($categoryPostData['category_products'], true); $category->setPostedProducts($products); } $this->_eventManager->dispatch( @@ -162,8 +157,8 @@ public function execute() /** * Check "Use Default Value" checkboxes values */ - if (isset($generalPost['use_default']) && !empty($generalPost['use_default'])) { - foreach ($generalPost['use_default'] as $attributeCode => $attributeValue) { + if (isset($categoryPostData['use_default']) && !empty($categoryPostData['use_default'])) { + foreach ($categoryPostData['use_default'] as $attributeCode => $attributeValue) { if ($attributeValue) { $category->setData($attributeCode, null); } @@ -203,15 +198,15 @@ public function execute() } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { $this->messageManager->addError($e->getMessage()); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->_getSession()->setCategoryData($data); + $this->_getSession()->setCategoryData($categoryPostData); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->_getSession()->setCategoryData($data); + $this->_getSession()->setCategoryData($categoryPostData); } catch (\Exception $e) { $this->messageManager->addError(__('Something went wrong while saving the category.')); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->_getSession()->setCategoryData($data); + $this->_getSession()->setCategoryData($categoryPostData); } } @@ -254,9 +249,9 @@ public function execute() */ public function imagePreprocessing($data) { - if (empty($data['general']['image'])) { - unset($data['general']['image']); - $data['general']['image']['delete'] = true; + if (empty($data['image'])) { + unset($data['image']); + $data['image']['delete'] = true; } return $data; } @@ -344,42 +339,4 @@ protected function getRedirectParams($isNewCategory, $hasError, $categoryId, $pa } return ['path' => $path, 'params' => $params]; } - - /** - * Datetime data preprocessing - * - * @param array $postData - * @param \Magento\Catalog\Model\Category $category - * - * @return array - */ - private function dateTimePreprocessing($postData, $category) - { - $dateFieldFilters = []; - $attributes = $category->getAttributes(); - foreach ($attributes as $attrKey => $attribute) { - if ($attribute->getBackend()->getType() == 'datetime') { - if (array_key_exists($attrKey, $postData['general']) && $postData['general'][$attrKey] != '') { - $dateFieldFilters[$attrKey] = $this->getDateTimeFilter(); - } - } - } - $inputFilter = new \Zend_Filter_Input($dateFieldFilters, [], $postData['general']); - $postData['general'] = $inputFilter->getUnescaped(); - return $postData; - } - - /** - * @return \Magento\Framework\Stdlib\DateTime\Filter\DateTime - * - * @deprecated - */ - private function getDateTimeFilter() - { - if ($this->dateTimeFilter === null) { - $this->dateTimeFilter = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class); - } - return $this->dateTimeFilter; - } } diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php index f2e2ea6c78816..6c114089789c6 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php @@ -111,6 +111,9 @@ public function afterSave($object) } catch (\Exception $e) { $this->_logger->critical($e); } + } elseif (isset($value[0]['name'])) { + $object->setData($this->getAttribute()->getName(), $value[0]['name']); + $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName()); } return $this; } From 7d42851e4c052c00eca22b72faf5293bc41f5009 Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov Date: Thu, 14 Apr 2016 15:51:54 +0300 Subject: [PATCH 17/17] MAGETWO-48688: New category with invalid data loses entered data after validation --- app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php | 2 +- app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php index 3a28c62b5e76e..c66fe32bcce2d 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Add.php @@ -51,7 +51,7 @@ public function execute() } /** - * Check if we have data in session (if during category save was exception) + * Check if there are data in session (if there was an exception on saving category) */ $categoryData = $this->_getSession()->getCategoryData(true); if (is_array($categoryData)) { diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php index cf1061934fec6..1f5a68969037a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Edit.php @@ -80,7 +80,7 @@ public function execute() } /** - * Check if we have data in session (if during category save was exception) + * Check if there are data in session (if there was an exception on saving category) */ $categoryData = $this->_getSession()->getCategoryData(true); if (is_array($categoryData)) {