Skip to content

Commit 3da1ebe

Browse files
committed
MAGETWO-90798: Customer is redirected to 404 from Catalog page if switches to the Store with another root Category
1 parent af84959 commit 3da1ebe

File tree

5 files changed

+302
-0
lines changed

5 files changed

+302
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogUrlRewrite\Plugin\Store\Block;
9+
10+
use Magento\Framework\Data\Helper\PostHelper;
11+
use Magento\Store\Api\StoreResolverInterface;
12+
use Magento\Store\Model\Store;
13+
use Magento\UrlRewrite\Model\UrlFinderInterface;
14+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
15+
use Magento\Framework\App\Request\Http as HttpRequest;
16+
17+
/**
18+
* Plugin makes connection between Store and UrlRewrite modules
19+
* because Magento\Store\Block\Switcher should not know about UrlRewrite module functionality.
20+
*/
21+
class Switcher
22+
{
23+
/**
24+
* @var PostHelper
25+
*/
26+
private $postHelper;
27+
28+
/**
29+
* @var UrlFinderInterface
30+
*/
31+
private $urlFinder;
32+
33+
/**
34+
* @var HttpRequest
35+
*/
36+
private $request;
37+
38+
/**
39+
* @param PostHelper $postHelper
40+
* @param UrlFinderInterface $urlFinder
41+
* @param HttpRequest $request
42+
*/
43+
public function __construct(
44+
PostHelper $postHelper,
45+
UrlFinderInterface $urlFinder,
46+
HttpRequest $request
47+
) {
48+
$this->postHelper = $postHelper;
49+
$this->urlFinder = $urlFinder;
50+
$this->request = $request;
51+
}
52+
53+
/**
54+
* @param \Magento\Store\Block\Switcher $subject
55+
* @param string $result
56+
* @param Store $store
57+
* @param array $data
58+
* @return string
59+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
60+
*/
61+
public function afterGetTargetStorePostData(
62+
\Magento\Store\Block\Switcher $subject,
63+
string $result,
64+
Store $store,
65+
array $data = []
66+
): string {
67+
$data[StoreResolverInterface::PARAM_NAME] = $store->getCode();
68+
$currentUrl = $store->getCurrentUrl(true);
69+
$baseUrl = $store->getBaseUrl();
70+
$urlPath = parse_url($currentUrl, PHP_URL_PATH);
71+
$urlToSwitch = $currentUrl;
72+
73+
//check only catalog pages
74+
if ($this->request->getFrontName() === 'catalog') {
75+
$currentRewrite = $this->urlFinder->findOneByData([
76+
UrlRewrite::REQUEST_PATH => ltrim($urlPath, '/'),
77+
UrlRewrite::STORE_ID => $store->getId(),
78+
]);
79+
if (null === $currentRewrite) {
80+
$urlToSwitch = $baseUrl;
81+
}
82+
}
83+
84+
return $this->postHelper->getPostData($urlToSwitch, $data);
85+
}
86+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="\Magento\Store\Block\Switcher">
10+
<plugin name="store_switcher_plugin" type="Magento\CatalogUrlRewrite\Plugin\Store\Block\Switcher"/>
11+
</type>
12+
</config>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogUrlRewrite\Plugin\Store\Block;
9+
10+
/**
11+
* Integration tests for Magento\CatalogUrlRewrite\Plugin\Store\Block\Switcher block.
12+
*/
13+
class SwitcherTest extends \PHPUnit\Framework\TestCase
14+
{
15+
/**
16+
* @var \Magento\TestFramework\ObjectManager
17+
*/
18+
private $objectManager;
19+
20+
/**
21+
* @var \Magento\Store\Block\Switcher
22+
*/
23+
private $model;
24+
25+
/**
26+
* @var \Magento\Store\Api\StoreRepositoryInterface
27+
*/
28+
private $storeRepository;
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
protected function setUp()
34+
{
35+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
36+
$this->model = $this->objectManager->create(\Magento\Store\Block\Switcher::class);
37+
$this->storeRepository = $this->objectManager->create(\Magento\Store\Api\StoreRepositoryInterface::class);
38+
}
39+
40+
/**
41+
* Test that after switching from Store 1 to Store 2 with another root Category user gets correct store url.
42+
*
43+
* @magentoDataFixture Magento/Store/_files/store.php
44+
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/two_categories_per_two_store_groups.php
45+
* @magentoAppArea frontend
46+
* @return void
47+
*/
48+
public function testGetTargetStorePostData(): void
49+
{
50+
$storeCode = 'test';
51+
$store = $this->storeRepository->get($storeCode);
52+
$result = json_decode($this->model->getTargetStorePostData($store), true);
53+
54+
$this->assertContains($storeCode, $result['action']);
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
9+
10+
/** @var \Magento\Catalog\Model\Category $category */
11+
$category = $objectManager->create(\Magento\Catalog\Model\Category::class);
12+
$category->isObjectNew(true);
13+
$category->setId(333)
14+
->setCreatedAt('2014-06-23 09:50:07')
15+
->setName('Category 1')
16+
->setParentId(2)
17+
->setPath('1/2/3')
18+
->setLevel(2)
19+
->setAvailableSortBy('name')
20+
->setDefaultSortBy('name')
21+
->setIsActive(true)
22+
->setPosition(1)
23+
->setAvailableSortBy(['position'])
24+
->save();
25+
26+
/** @var $product \Magento\Catalog\Model\Product */
27+
$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
28+
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
29+
->setId(333)
30+
->setAttributeSetId(4)
31+
->setStoreId(1)
32+
->setWebsiteIds([1])
33+
->setName('Simple Product Three')
34+
->setSku('simple333')
35+
->setPrice(10)
36+
->setWeight(18)
37+
->setStockData(['use_config_manage_stock' => 0])
38+
->setCategoryIds([333])
39+
->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
40+
->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
41+
->save();
42+
43+
/** @var \Magento\Store\Model\Store $store */
44+
$store = $objectManager->create(\Magento\Store\Model\Store::class);
45+
46+
$category->setStoreId($store->load('default')->getId())
47+
->setName('category-default-store')
48+
->setUrlKey('category-default-store')
49+
->save();
50+
51+
$rootCategoryForTestStoreGroup = $objectManager->create(\Magento\Catalog\Model\Category::class);
52+
$rootCategoryForTestStoreGroup->isObjectNew(true);
53+
$rootCategoryForTestStoreGroup->setId(334)
54+
->setCreatedAt('2014-06-23 09:50:07')
55+
->setName('Category 2')
56+
->setParentId(1)
57+
->setPath('1/2/334')
58+
->setLevel(2)
59+
->setAvailableSortBy('name')
60+
->setDefaultSortBy('name')
61+
->setIsActive(true)
62+
->setPosition(1)
63+
->setAvailableSortBy(['position'])
64+
->save();
65+
66+
$rootCategoryForTestStoreGroup->setStoreId($store->load('test')->getId())
67+
->setName('category-test-store')
68+
->setUrlKey('category-test-store')
69+
->save();
70+
71+
$storeCode = 'test';
72+
/** @var \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository */
73+
$categoryRepository = $objectManager->create(\Magento\Catalog\Api\CategoryRepositoryInterface::class);
74+
/** @var \Magento\Catalog\Api\Data\CategoryInterface $category */
75+
$category = $categoryRepository->get(334);
76+
/** @var \Magento\Store\Api\StoreRepositoryInterface $storeRepository */
77+
$storeRepository = $objectManager->create(\Magento\Store\Api\StoreRepositoryInterface::class);
78+
/** @var \Magento\Store\Api\Data\StoreInterface $store */
79+
$store = $storeRepository->get($storeCode);
80+
81+
/** @var \Magento\Store\Model\Group $storeGroup */
82+
$storeGroup = $objectManager->create(\Magento\Store\Model\Group::class);
83+
$storeGroup->setWebsiteId('1');
84+
$storeGroup->setCode('test_store_group');
85+
$storeGroup->setName('Test Store Group');
86+
$storeGroup->setRootCategoryId($category->getId());
87+
$storeGroup->setDefaultStoreId($store->getId());
88+
$storeGroup->save();
89+
90+
$store->setGroupId($storeGroup->getId())->save();
91+
92+
/* Refresh stores memory cache */
93+
$objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->reinitStores();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Framework\Registry;
9+
use Magento\Store\Model\Group;
10+
use Magento\TestFramework\Helper\Bootstrap;
11+
use Magento\Catalog\Api\CategoryListInterface;
12+
use Magento\Catalog\Api\CategoryRepositoryInterface;
13+
use Magento\Framework\Api\SearchCriteriaBuilder;
14+
15+
$objectManager = Bootstrap::getObjectManager();
16+
17+
/** @var Registry $registry */
18+
$registry = $objectManager->get(Registry::class);
19+
$registry->unregister('isSecureArea');
20+
$registry->register('isSecureArea', true);
21+
// Delete product
22+
$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
23+
try {
24+
$product = $productRepository->get('simple333', false, null, true);
25+
$product->delete();
26+
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) {
27+
//Product already removed
28+
}
29+
// Delete first category
30+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
31+
$searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class);
32+
$searchCriteria = $searchCriteriaBuilder->addFilter('name', 'Category 1')->create();
33+
/** @var CategoryListInterface $categoryList */
34+
$categoryList = $objectManager->get(CategoryListInterface::class);
35+
$categories = $categoryList->getList($searchCriteria)->getItems();
36+
/** @var CategoryRepositoryInterface $categoryRepository */
37+
$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class);
38+
foreach ($categories as $category) {
39+
$categoryRepository->delete($category);
40+
}
41+
// Delete second category
42+
$searchCriteria = $searchCriteriaBuilder->addFilter('name', 'Category 2')->create();
43+
$categories = $categoryList->getList($searchCriteria)->getItems();
44+
foreach ($categories as $category) {
45+
$categoryRepository->delete($category);
46+
}
47+
// Delete store group
48+
/** @var Group $store */
49+
$storeGroup = $objectManager->get(Group::class);
50+
$storeGroup->load('test_store_group', 'code');
51+
if ($storeGroup->getId()) {
52+
$storeGroup->delete();
53+
}
54+
$registry->unregister('isSecureArea');
55+
$registry->register('isSecureArea', false);

0 commit comments

Comments
 (0)