diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Storage/DynamicStorage.php b/app/code/Magento/CatalogUrlRewrite/Model/Storage/DynamicStorage.php index d9e9705ac039d..9da95d4270b74 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Storage/DynamicStorage.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Storage/DynamicStorage.php @@ -179,13 +179,16 @@ private function findProductRewriteByRequestPath(array $data): ?array unset($data[UrlRewrite::IS_AUTOGENERATED]); $categoryFromDb = $this->connection->fetchRow($this->prepareSelect($data)); + if ($categoryFromDb === false) { + return null; + } + if ($categoryFromDb[UrlRewrite::REDIRECT_TYPE]) { $productFromDb[UrlRewrite::REDIRECT_TYPE] = OptionProvider::PERMANENT; $categoryPath = str_replace($categorySuffix, '', $categoryFromDb[UrlRewrite::TARGET_PATH]); } - if ($categoryFromDb === false - || !$productResource->canBeShowInCategory( + if (!$productResource->canBeShowInCategory( $productFromDb[UrlRewrite::ENTITY_ID], $categoryFromDb[UrlRewrite::ENTITY_ID] ) diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Storage/DynamicStorageTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Storage/DynamicStorageTest.php new file mode 100644 index 0000000000000..4389498a3297b --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Storage/DynamicStorageTest.php @@ -0,0 +1,327 @@ +urlRewriteFactoryMock = $this->getMockBuilder(UrlRewriteFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->dataObjectHelperMock = $this->getMockBuilder(DataObjectHelper::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceConnectionMock = $this->getMockBuilder(ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->connectionMock + ->method('select') + ->willReturn($this->selectMock); + + $this->resourceConnectionMock + ->method('getConnection') + ->willReturn($this->connectionMock); + + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMock(); + + $this->productResourceMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->productFactoryMock = $this->getMockBuilder(ProductFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->productFactoryMock + ->method('create') + ->willReturn($this->productResourceMock); + + $this->object = new DynamicStorage( + $this->urlRewriteFactoryMock, + $this->dataObjectHelperMock, + $this->resourceConnectionMock, + $this->scopeConfigMock, + $this->productFactoryMock + ); + } + + /** + * @dataProvider findProductRewriteByRequestPathDataProvider + * @param array $data + * @param array|false $productFromDb + * @param string $categorySuffix + * @param array|false $categoryFromDb + * @param bool $canBeShownInCategory + * @param array|null $expectedProductRewrite + * @throws \ReflectionException + */ + public function testFindProductRewriteByRequestPath( + array $data, + $productFromDb, + string $categorySuffix, + $categoryFromDb, + bool $canBeShownInCategory, + ?array $expectedProductRewrite + ): void { + $this->connectionMock->expects($this->any()) + ->method('fetchRow') + ->will($this->onConsecutiveCalls($productFromDb, $categoryFromDb)); + + $scopeConfigMap = [ + [ + CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX, + ScopeInterface::SCOPE_STORE, + $data['store_id'], + $categorySuffix + ] + ]; + + $this->scopeConfigMock + ->method('getValue') + ->willReturnMap($scopeConfigMap); + + $this->productResourceMock + ->method('canBeShowInCategory') + ->willReturn($canBeShownInCategory); + + $method = new ReflectionMethod($this->object, 'findProductRewriteByRequestPath'); + $method->setAccessible(true); + + $this->assertSame($expectedProductRewrite, $method->invoke($this->object, $data)); + } + + /** + * @return array + */ + public function findProductRewriteByRequestPathDataProvider(): array + { + return [ + [ + // Non-existing product + [ + 'request_path' => 'test.html', + 'store_id' => 1 + ], + false, + '', + null, + true, + null + ], + [ + // Non-existing category + [ + 'request_path' => 'a/test.html', + 'store_id' => 1 + ], + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'test.html', + 'target_path' => 'catalog/product/view/id/1', + 'redirect_type' => '0', + ], + '.html', + false, + true, + null + ], + [ + // Existing category + [ + 'request_path' => 'shop/test.html', + 'store_id' => 1 + ], + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'test.html', + 'target_path' => 'catalog/product/view/id/1', + 'redirect_type' => '0', + ], + '.html', + [ + 'entity_type' => 'category', + 'entity_id' => '3', + 'request_path' => 'shop.html', + 'target_path' => 'catalog/category/view/id/3', + 'redirect_type' => '0', + ], + true, + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'shop/test.html', + 'target_path' => 'catalog/product/view/id/1/category/3', + 'redirect_type' => '0', + ] + ], + [ + // Existing category, but can't be shown in category + [ + 'request_path' => 'shop/test.html', + 'store_id' => 1 + ], + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'test.html', + 'target_path' => 'catalog/product/view/id/1', + 'redirect_type' => '0', + ], + '.html', + [ + 'entity_type' => 'category', + 'entity_id' => '3', + 'request_path' => 'shop.html', + 'target_path' => 'catalog/category/view/id/3', + 'redirect_type' => '0', + ], + false, + null + ], + [ + // Existing category, with product 301 redirect type + [ + 'request_path' => 'shop/test.html', + 'store_id' => 1 + ], + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'test.html', + 'target_path' => 'test-new.html', + 'redirect_type' => OptionProvider::PERMANENT, + ], + '.html', + [ + 'entity_type' => 'category', + 'entity_id' => '3', + 'request_path' => 'shop.html', + 'target_path' => 'catalog/category/view/id/3', + 'redirect_type' => '0', + ], + true, + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'shop/test.html', + 'target_path' => 'shop/test-new.html', + 'redirect_type' => OptionProvider::PERMANENT, + ] + ], + [ + // Existing category, with category 301 redirect type + [ + 'request_path' => 'shop/test.html', + 'store_id' => 1 + ], + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'test.html', + 'target_path' => 'catalog/product/view/id/1', + 'redirect_type' => '0', + ], + '.html', + [ + 'entity_type' => 'category', + 'entity_id' => '3', + 'request_path' => 'shop.html', + 'target_path' => 'shop-new.html', + 'redirect_type' => OptionProvider::PERMANENT, + ], + true, + [ + 'entity_type' => 'product', + 'entity_id' => '1', + 'request_path' => 'shop/test.html', + 'target_path' => 'shop-new/test.html', + 'redirect_type' => OptionProvider::PERMANENT, + ] + ], + ]; + } +}