From cb8a09f023ebc9280c0e8bc6c1a934a67cd755f2 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Thu, 13 Oct 2022 12:36:32 -0500 Subject: [PATCH 1/6] ACP2E-1214: [Magento Cloud] - Mass Delete Product Review doesnt work when logged in as limited user role --- .../Magento/Review/Controller/Adminhtml/Product/MassDelete.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php b/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php index 44b267dc5aa7c..18462742c4d86 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php @@ -123,6 +123,7 @@ private function getCollection(): Collection ->getIdFieldName(), $this->getRequest()->getParam('reviews') ); + $collection->addStoreData(); $this->collection = $collection; } From 32c698caf5adecab1045d4ad8e41123dc1959202 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Fri, 14 Oct 2022 10:07:03 -0500 Subject: [PATCH 2/6] ACP2E-1214: [Magento Cloud] - Mass Delete Product Review doesnt work when logged in as limited user role --- .../Adminhtml/Product/MassDelete.php | 5 +- .../Adminhtml/Product/MassDeleteTest.php | 105 ++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php b/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php index 18462742c4d86..64e2421df2a33 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/MassDelete.php @@ -71,7 +71,10 @@ public function execute() } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addExceptionMessage($e, __('Something went wrong while deleting these records.')); + $this->messageManager->addExceptionMessage( + $e, + __('Something went wrong while deleting these records.') + ); } } /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ diff --git a/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php new file mode 100644 index 0000000000000..c798a4dca975e --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php @@ -0,0 +1,105 @@ +createMock(Context::class); + $this->requestMock = $this->createMock(RequestInterface::class); + $contextMock->method('getRequest') + ->willReturn($this->requestMock); + $messageManagerMock = $this->createMock(ManagerInterface::class); + $contextMock->method('getMessageManager') + ->willReturn($messageManagerMock); + $resultFactoryMock = $this->createMock(ResultFactory::class); + $contextMock->method('getResultFactory') + ->willReturn($resultFactoryMock); + $resultMock = $this->createMock(Redirect::class); + $resultFactoryMock->method('create') + ->willReturn($resultMock); + + $coreRegistryMock = $this->createMock(Registry::class); + $reviewFactoryMock = $this->createMock(ReviewFactory::class); + $ratingFactoryMock = $this->createMock(RatingFactory::class); + $this->collectionFactoryMock = $this->createMock(ReviewCollectionFactory::class); + + $this->massDelete = new MassDelete( + $contextMock, + $coreRegistryMock, + $reviewFactoryMock, + $ratingFactoryMock, + $this->collectionFactoryMock + ); + } + + public function testExecute(): void + { + $this->requestMock->expects(self::atLeastOnce()) + ->method('getParam') + ->willReturnMap( + [ + ['reviews', null, [10, 20]], + ['ret', 'index', 'index'], + ] + ); + + $collectionMock = $this->createMock(ReviewCollection::class); + $this->collectionFactoryMock->expects(self::once()) + ->method('create') + ->willReturn($collectionMock); + $resource = $this->createMock(ReviewResourceModel::class); + $collectionMock->method('getResource') + ->willReturn($resource); + $resource->method('getIdFieldName') + ->willReturn('id'); + $collectionMock->expects(self::once()) + ->method('addFieldToFilter') + ->with('main_table.id', [10, 20]) + ->willReturnSelf(); + $collectionMock->expects(self::once()) + ->method('addStoreData') + ->willReturnSelf(); + + $this->massDelete->execute(); + } +} From a4368e66cfb3ef29a28aa88b57007c1ac8d77d5e Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Mon, 17 Oct 2022 12:29:39 -0500 Subject: [PATCH 3/6] ACP2E-1214: [Magento Cloud] - Mass Delete Product Review doesnt work when logged in as limited user role --- .../Unit/Controller/Adminhtml/Product/MassDeleteTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php index c798a4dca975e..b13b000403c6a 100644 --- a/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php +++ b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php @@ -74,7 +74,7 @@ protected function setUp(): void public function testExecute(): void { - $this->requestMock->expects(self::atLeastOnce()) + $this->requestMock->expects($this->atLeastOnce()) ->method('getParam') ->willReturnMap( [ @@ -84,7 +84,7 @@ public function testExecute(): void ); $collectionMock = $this->createMock(ReviewCollection::class); - $this->collectionFactoryMock->expects(self::once()) + $this->collectionFactoryMock->expects($this->once()) ->method('create') ->willReturn($collectionMock); $resource = $this->createMock(ReviewResourceModel::class); @@ -92,11 +92,11 @@ public function testExecute(): void ->willReturn($resource); $resource->method('getIdFieldName') ->willReturn('id'); - $collectionMock->expects(self::once()) + $collectionMock->expects($this->once()) ->method('addFieldToFilter') ->with('main_table.id', [10, 20]) ->willReturnSelf(); - $collectionMock->expects(self::once()) + $collectionMock->expects($this->once()) ->method('addStoreData') ->willReturnSelf(); From e5df77c329d93f5207ed989109016a4a21cb8d6d Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Mon, 17 Oct 2022 15:15:21 -0500 Subject: [PATCH 4/6] ACP2E-1214: [Magento Cloud] - Mass Delete Product Review doesnt work when logged in as limited user role --- .../Unit/Controller/Adminhtml/Product/MassDeleteTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php index b13b000403c6a..c798a4dca975e 100644 --- a/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php +++ b/app/code/Magento/Review/Test/Unit/Controller/Adminhtml/Product/MassDeleteTest.php @@ -74,7 +74,7 @@ protected function setUp(): void public function testExecute(): void { - $this->requestMock->expects($this->atLeastOnce()) + $this->requestMock->expects(self::atLeastOnce()) ->method('getParam') ->willReturnMap( [ @@ -84,7 +84,7 @@ public function testExecute(): void ); $collectionMock = $this->createMock(ReviewCollection::class); - $this->collectionFactoryMock->expects($this->once()) + $this->collectionFactoryMock->expects(self::once()) ->method('create') ->willReturn($collectionMock); $resource = $this->createMock(ReviewResourceModel::class); @@ -92,11 +92,11 @@ public function testExecute(): void ->willReturn($resource); $resource->method('getIdFieldName') ->willReturn('id'); - $collectionMock->expects($this->once()) + $collectionMock->expects(self::once()) ->method('addFieldToFilter') ->with('main_table.id', [10, 20]) ->willReturnSelf(); - $collectionMock->expects($this->once()) + $collectionMock->expects(self::once()) ->method('addStoreData') ->willReturnSelf(); From 74e68576c01a5f9c1c758c240d30394d4c7f7355 Mon Sep 17 00:00:00 2001 From: soumah Date: Wed, 19 Oct 2022 14:02:26 -0500 Subject: [PATCH 5/6] ACP2E-1223: When trying to use certain multi-selects within the Magento admin for coupon report, they don't always work as intended. --- .../Reports/Block/Adminhtml/Filter/Form.php | 4 +- .../Block/Adminhtml/Sales/Coupons/Grid.php | 8 +- .../Unit/Block/Adminhtml/Filter/FormTest.php | 93 +++++++++++++++++++ .../Adminhtml/Sales/Coupons/GridTest.php | 38 +++++--- 4 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Filter/FormTest.php diff --git a/app/code/Magento/Reports/Block/Adminhtml/Filter/Form.php b/app/code/Magento/Reports/Block/Adminhtml/Filter/Form.php index b9e31829d9436..b7b669163e93c 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Filter/Form.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Filter/Form.php @@ -201,8 +201,8 @@ protected function _initFormValues() { $data = $this->getFilterData()->getData(); foreach ($data as $key => $value) { - if (is_array($value) && isset($value[0])) { - $data[$key] = explode(',', $value[0]); + if (is_array($value) && count($value) === 1) { + $data[$key] = explode(',', reset($value)); } } $this->getForm()->addValues($data); diff --git a/app/code/Magento/Reports/Block/Adminhtml/Sales/Coupons/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Sales/Coupons/Grid.php index 358a0e85281a6..e6e8bdbec964a 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Sales/Coupons/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Sales/Coupons/Grid.php @@ -211,9 +211,11 @@ protected function _addCustomFilter($collection, $filterData) { if ($filterData->getPriceRuleType()) { $rulesList = $filterData->getData('rules_list'); - if (isset($rulesList[0])) { - $rulesIds = explode(',', $rulesList[0]); - $collection->addRuleFilter($rulesIds); + if (is_array($rulesList) && count($rulesList) > 0) { + if (count($rulesList) === 1) { + $rulesList = explode(',', reset($rulesList)); + } + $collection->addRuleFilter($rulesList); } } diff --git a/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Filter/FormTest.php b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Filter/FormTest.php new file mode 100644 index 0000000000000..a5c5bc0efb5d8 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Filter/FormTest.php @@ -0,0 +1,93 @@ +context = $this->createMock(Context::class); + $this->registry = $this->createMock(Registry::class); + $this->formFactory = $this->createMock(FormFactory::class); + $this->context->method('getUrlBuilder') + ->willReturn($this->getMockForAbstractClass(UrlInterface::class)); + $this->model = new \Magento\Reports\Block\Adminhtml\Filter\Form( + $this->context, + $this->registry, + $this->formFactory + ); + } + + /** + * @return void + * @throws \ReflectionException + */ + public function testMultiselectInitialValues(): void + { + $this->context->method('getUrlBuilder') + ->willReturn($this->getMockForAbstractClass(UrlInterface::class)); + $this->model->setData('filter_data', new DataObject(['multiselect' => ['5', '6']])); + $form = $this->getMockBuilder(Form::class) + ->disableOriginalConstructor() + ->onlyMethods(['getElements']) + ->getMockForAbstractClass(); + $element = $this->getMockBuilder(AbstractElement::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $element->setId('multiselect'); + $form->method('getElements')->willReturn(new Collection($form)); + $reflection = new ReflectionClass($form); + $reflectionProp = $reflection->getProperty('_allElements'); + $reflectionProp->setAccessible(true); + $reflectionProp->setValue($form, new Collection($form)); + $form->addElement($element); + $this->model->setForm($form); + $reflection = new ReflectionClass($this->model); + $reflectionMethod = $reflection->getMethod('_initFormValues'); + $reflectionMethod->setAccessible(true); + $reflectionMethod->invoke($this->model); + $this->assertEquals(['5', '6'], $this->model->getForm()->getElement('multiselect')->getValue()); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Coupons/GridTest.php b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Coupons/GridTest.php index 1c671ca11744f..91ad4babe42bd 100644 --- a/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Coupons/GridTest.php +++ b/app/code/Magento/Reports/Test/Unit/Block/Adminhtml/Sales/Coupons/GridTest.php @@ -67,16 +67,18 @@ protected function setUp(): void * @dataProvider getCountTotalsDataProvider * * @param string $reportType - * @param int $priceRuleType + * @param array|null $rulesList * @param int $collectionSize * @param bool $expectedCountTotals + * @param array|null $expectedRuleFilter * @return void */ public function testGetCountTotals( string $reportType, - int $priceRuleType, + ?array $rulesList, int $collectionSize, - bool $expectedCountTotals + bool $expectedCountTotals, + ?array $expectedRuleFilter = null ): void { $filterData = new DataObject(); $filterData->setData('report_type', $reportType); @@ -84,15 +86,18 @@ public function testGetCountTotals( $filterData->setData('from', '2000-01-01'); $filterData->setData('to', '2000-01-30'); $filterData->setData('store_ids', '1'); - $filterData->setData('price_rule_type', $priceRuleType); - if ($priceRuleType) { - $filterData->setData('rules_list', ['0,1']); - } + $filterData->setData('price_rule_type', $rulesList !== null); + $filterData->setData('rules_list', $rulesList); $filterData->setData('order_statuses', 'statuses'); $this->model->setFilterData($filterData); $resourceCollectionName = $this->model->getResourceCollectionName(); - $collectionMock = $this->buildBaseCollectionMock($filterData, $resourceCollectionName, $collectionSize); + $collectionMock = $this->buildBaseCollectionMock( + $filterData, + $resourceCollectionName, + $collectionSize, + $expectedRuleFilter + ); $store = $this->getMockBuilder(StoreInterface::class) ->getMock(); @@ -111,23 +116,26 @@ public function testGetCountTotals( public function getCountTotalsDataProvider(): array { return [ - ['created_at_shipment', 0, 0, false], - ['created_at_shipment', 0, 1, true], - ['updated_at_order', 0, 1, true], - ['updated_at_order', 1, 1, true], + ['created_at_shipment', null, 0, false], + ['created_at_shipment', null, 1, true], + ['updated_at_order', null, 1, true], + ['updated_at_order', ['1,2'], 1, true, ['1', '2']], + ['updated_at_order', ['1', '2'], 1, true, ['1', '2']], ]; } /** - * @param \Magento\Framework\DataObject $filterData + * @param DataObject $filterData * @param string $resourceCollectionName * @param int $collectionSize + * @param array|null $ruleFilter * @return MockObject */ private function buildBaseCollectionMock( DataObject $filterData, string $resourceCollectionName, - int $collectionSize + int $collectionSize, + ?array $ruleFilter ): MockObject { $collectionMock = $this->getMockBuilder($resourceCollectionName) ->disableOriginalConstructor() @@ -159,7 +167,7 @@ private function buildBaseCollectionMock( if ($filterData->getData('price_rule_type')) { $collectionMock->expects($this->once()) ->method('addRuleFilter') - ->with(\explode(',', $filterData->getData('rules_list')[0])) + ->with($ruleFilter) ->willReturnSelf(); } From 0d90748aa1dd76581b8a3dbf34b5ce82961d9902 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Thu, 20 Oct 2022 16:21:40 -0500 Subject: [PATCH 6/6] ACP2E-1296: product price index (catalog_product_price) not working if bundle product not assigned to any website --- .../Price/DisabledProductOptionPriceModifier.php | 8 ++++---- .../Model/ResourceModel/Indexer/PriceTest.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price/DisabledProductOptionPriceModifier.php b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price/DisabledProductOptionPriceModifier.php index 0da07eaff4aaf..b3c3e74e1fa60 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price/DisabledProductOptionPriceModifier.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price/DisabledProductOptionPriceModifier.php @@ -85,8 +85,9 @@ public function modifyPrice(IndexTableStructure $priceTable, array $entityIds = foreach ($this->getBundleIds($entityIds) as $entityId) { $entityId = (int) $entityId; foreach ($this->getWebsiteIdsOfProduct($entityId) as $websiteId) { + $websiteId = (int) $websiteId; $productIdsDisabledRequired = $this->selectionProductsDisabledRequired - ->getChildProductIds($entityId, (int)$websiteId); + ->getChildProductIds($entityId, $websiteId); if ($productIdsDisabledRequired) { $connection = $this->resourceConnection->getConnection('indexer'); $select = $connection->select(); @@ -118,9 +119,8 @@ private function getWebsiteIdsOfProduct(int $entityId): array ['product_in_websites' => $this->resourceConnection->getTableName('catalog_product_website')], ['website_id'] )->where('product_in_websites.product_id = ?', $entityId); - foreach ($connection->fetchCol($select) as $websiteId) { - $this->websiteIdsOfProduct[$entityId][] = (int)$websiteId; - } + $this->websiteIdsOfProduct[$entityId] = $connection->fetchCol($select); + return $this->websiteIdsOfProduct[$entityId]; } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/ResourceModel/Indexer/PriceTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/ResourceModel/Indexer/PriceTest.php index afb0e66558aaa..2125b5f3247e7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/ResourceModel/Indexer/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/ResourceModel/Indexer/PriceTest.php @@ -6,6 +6,7 @@ namespace Magento\Bundle\Model\ResourceModel\Indexer; +use Magento\Bundle\Test\Fixture\Product as BundleProductFixture; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Indexer\Product\Price; use Magento\Customer\Model\Group; @@ -14,6 +15,7 @@ use Magento\Store\Api\WebsiteRepositoryInterface; use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId; use Magento\CatalogInventory\Model\Indexer\Stock; +use Magento\TestFramework\Fixture\DataFixture; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -91,6 +93,18 @@ public function testExecuteRowWithShowOutOfStock(): void $this->assertIndexTableData($bundleProduct->getId(), $expectedPrices); } + #[ + DataFixture( + BundleProductFixture::class, + ['sku' => 'bundle1', 'extension_attributes' => ['website_ids' => []]] + ), + ] + public function testExecuteForBundleWithoutWebsites(): void + { + $bundleProduct = $this->productRepository->get('bundle1'); + $this->indexer->executeRow($bundleProduct->getId()); + } + /** * Asserts price data in index table. *