diff --git a/app/code/Magento/Catalog/Controller/Category/View.php b/app/code/Magento/Catalog/Controller/Category/View.php
index da7c5326587e3..10487e50c91cf 100644
--- a/app/code/Magento/Catalog/Controller/Category/View.php
+++ b/app/code/Magento/Catalog/Controller/Category/View.php
@@ -3,6 +3,9 @@
* Copyright 2014 Adobe
* All Rights Reserved.
*/
+
+declare(strict_types=1);
+
namespace Magento\Catalog\Controller\Category;
use Magento\Catalog\Api\CategoryRepositoryInterface;
@@ -11,8 +14,8 @@
use Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager;
use Magento\Catalog\Model\Design;
use Magento\Catalog\Model\Layer\Resolver;
-use Magento\Catalog\Model\Product\ProductList\ToolbarMemorizer;
use Magento\Catalog\Model\Product\ProductList\Toolbar;
+use Magento\Catalog\Model\Product\ProductList\ToolbarMemorizer;
use Magento\Catalog\Model\Session;
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
use Magento\Framework\App\Action\Action;
@@ -21,8 +24,10 @@
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Controller\Result\Forward;
use Magento\Framework\Controller\Result\ForwardFactory;
-use Magento\Framework\Controller\ResultFactory;
+use Magento\Framework\Controller\Result\Redirect;
+use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
@@ -121,8 +126,8 @@ class View extends Action implements HttpGetActionInterface, HttpPostActionInter
* @param CategoryRepositoryInterface $categoryRepository
* @param ToolbarMemorizer|null $toolbarMemorizer
* @param LayoutUpdateManager|null $layoutUpdateManager
- * @param CategoryHelper $categoryHelper
- * @param LoggerInterface $logger
+ * @param CategoryHelper|null $categoryHelper
+ * @param LoggerInterface|null $logger
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -189,7 +194,7 @@ protected function _initCategory()
['category' => $category, 'controller_action' => $this]
);
} catch (LocalizedException $e) {
- $this->logger->critical($e);
+ $this->logger->critical((string)$e);
return false;
}
@@ -199,63 +204,99 @@ protected function _initCategory()
/**
* Category view action
*
+ * @return ResultInterface
* @throws NoSuchEntityException
*/
public function execute()
{
- $result = null;
-
if ($this->_request->getParam(ActionInterface::PARAM_NAME_URL_ENCODED)) {
//phpcs:ignore Magento2.Legacy.ObsoleteResponse
return $this->resultRedirectFactory->create()->setUrl($this->_redirect->getRedirectUrl());
}
$category = $this->_initCategory();
- if ($category) {
- $this->layerResolver->create(Resolver::CATALOG_LAYER_CATEGORY);
- $settings = $this->_catalogDesign->getDesignSettings($category);
+ if (!$category) {
+ return $this->resultForwardFactory->create()->forward('noroute');
+ }
- // apply custom design
- if ($settings->getCustomDesign()) {
- $this->_catalogDesign->applyCustomDesign($settings->getCustomDesign());
- }
+ $pageRedirect = $this->handlePageRedirect($category);
+ if ($pageRedirect) {
+ return $pageRedirect;
+ }
- $this->_catalogSession->setLastViewedCategoryId($category->getId());
+ $page = $this->preparePage($category);
- $page = $this->resultPageFactory->create();
- // apply custom layout (page) template once the blocks are generated
- if ($settings->getPageLayout()) {
- $page->getConfig()->setPageLayout($settings->getPageLayout());
- }
+ if ($this->shouldRedirectOnToolbarAction()) {
+ $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
+ }
- $pageType = $this->getPageType($category);
+ return $page;
+ }
- if (!$category->hasChildren()) {
- // Two levels removed from parent. Need to add default page type.
- $parentPageType = strtok($pageType, '_');
- $page->addPageLayoutHandles(['type' => $parentPageType], null, false);
- }
- $page->addPageLayoutHandles(['type' => $pageType], null, false);
- $categoryDisplayMode = is_string($category->getDisplayMode()) ?
- strtolower($category->getDisplayMode()) : '';
- $page->addPageLayoutHandles(['displaymode' => $categoryDisplayMode], null, false);
- $page->addPageLayoutHandles(['id' => $category->getId()]);
+ /**
+ * @param Category $category
+ * @return Redirect|null
+ */
+ private function handlePageRedirect(Category $category): ?Redirect
+ {
+ if ($this->_request->getParam(Toolbar::PAGE_PARM_NAME) < 0) {
+ return $this->resultRedirectFactory->create()
+ ->setHttpResponseCode(301)
+ ->setUrl($category->getUrl());
+ }
- // apply custom layout update once layout is loaded
- $this->applyLayoutUpdates($page, $settings);
+ return null;
+ }
- $page->getConfig()->addBodyClass('page-products')
- ->addBodyClass('categorypath-' . $this->categoryUrlPathGenerator->getUrlPath($category))
- ->addBodyClass('category-' . $category->getUrlKey());
+ /**
+ * @param Category $category
+ * @return Page
+ */
+ private function preparePage(Category $category): Page
+ {
+ $this->layerResolver->create(Resolver::CATALOG_LAYER_CATEGORY);
+ $settings = $this->_catalogDesign->getDesignSettings($category);
- if ($this->shouldRedirectOnToolbarAction()) {
- $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
- }
- return $page;
- } elseif (!$this->getResponse()->isRedirect()) {
- $result = $this->resultForwardFactory->create()->forward('noroute');
+ if ($settings->getCustomDesign()) {
+ $this->_catalogDesign->applyCustomDesign($settings->getCustomDesign());
+ }
+
+ $this->_catalogSession->setLastViewedCategoryId($category->getId());
+
+ $page = $this->resultPageFactory->create();
+ if ($settings->getPageLayout()) {
+ $page->getConfig()->setPageLayout($settings->getPageLayout());
+ }
+
+ $this->addPageLayoutHandles($page, $category);
+ $this->applyLayoutUpdates($page, $settings);
+
+ $page->getConfig()->addBodyClass('page-products')
+ ->addBodyClass('categorypath-' . $this->categoryUrlPathGenerator->getUrlPath($category))
+ ->addBodyClass('category-' . $category->getUrlKey());
+
+ return $page;
+ }
+
+ /**
+ * @param Page $page
+ * @param Category $category
+ * @return void
+ */
+ private function addPageLayoutHandles(Page $page, Category $category): void
+ {
+ $pageType = $this->getPageType($category);
+
+ if (!$category->hasChildren()) {
+ $parentPageType = strtok($pageType, '_');
+ $page->addPageLayoutHandles(['type' => $parentPageType], null, false);
}
- return $result;
+ $page->addPageLayoutHandles(['type' => $pageType], null, false);
+
+ $categoryDisplayMode = is_string($category->getDisplayMode()) ?
+ strtolower($category->getDisplayMode()) : '';
+ $page->addPageLayoutHandles(['displaymode' => $categoryDisplayMode], null, false);
+ $page->addPageLayoutHandles(['id' => $category->getId()]);
}
/**
@@ -264,11 +305,11 @@ public function execute()
* @param Category $category
* @return string
*/
- private function getPageType(Category $category) : string
+ private function getPageType(Category $category): string
{
$hasChildren = $category->hasChildren();
if ($category->getIsAnchor()) {
- return $hasChildren ? 'layered' : 'layered_without_children';
+ return $hasChildren ? 'layered' : 'layered_without_children';
}
return $hasChildren ? 'default' : 'default_without_children';
@@ -284,7 +325,7 @@ private function getPageType(Category $category) : string
private function applyLayoutUpdates(
Page $page,
DataObject $settings
- ) {
+ ): void {
$layoutUpdates = $settings->getLayoutUpdates();
if ($layoutUpdates && is_array($layoutUpdates)) {
foreach ($layoutUpdates as $layoutUpdate) {
@@ -293,7 +334,6 @@ private function applyLayoutUpdates(
}
}
- //Selected files
if ($settings->getPageLayoutHandles()) {
$page->addPageLayoutHandles($settings->getPageLayoutHandles());
}
@@ -308,11 +348,11 @@ private function shouldRedirectOnToolbarAction(): bool
{
$params = $this->getRequest()->getParams();
- return $this->toolbarMemorizer->isMemorizingAllowed() && empty(array_intersect([
+ return $this->toolbarMemorizer->isMemorizingAllowed() && !empty(array_intersect([
Toolbar::ORDER_PARAM_NAME,
Toolbar::DIRECTION_PARAM_NAME,
Toolbar::MODE_PARAM_NAME,
Toolbar::LIMIT_PARAM_NAME
- ], array_keys($params))) === false;
+ ], array_keys($params)));
}
}
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPaginationResetOnNegativePageNumberTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPaginationResetOnNegativePageNumberTest.xml
new file mode 100644
index 0000000000000..ff1e3d22a2479
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPaginationResetOnNegativePageNumberTest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/CatalogSearch/Controller/Result/Index.php b/app/code/Magento/CatalogSearch/Controller/Result/Index.php
index 61d55d10dd45b..ff32f01494769 100644
--- a/app/code/Magento/CatalogSearch/Controller/Result/Index.php
+++ b/app/code/Magento/CatalogSearch/Controller/Result/Index.php
@@ -3,8 +3,10 @@
* Copyright 2014 Adobe
* All Rights Reserved.
*/
+
namespace Magento\CatalogSearch\Controller\Result;
+use Magento\Catalog\Model\Product\ProductList\Toolbar;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Catalog\Model\Layer\Resolver;
use Magento\Catalog\Model\Session;
@@ -22,11 +24,9 @@ class Index extends \Magento\Framework\App\Action\Action implements HttpGetActio
/**
* No results default handle.
*/
- const DEFAULT_NO_RESULT_HANDLE = 'catalogsearch_result_index_noresults';
+ public const DEFAULT_NO_RESULT_HANDLE = 'catalogsearch_result_index_noresults';
/**
- * Catalog session
- *
* @var Session
*/
protected $_catalogSession;
@@ -42,8 +42,6 @@ class Index extends \Magento\Framework\App\Action\Action implements HttpGetActio
private $_queryFactory;
/**
- * Catalog Layer Resolver
- *
* @var Resolver
*/
private $layerResolver;
@@ -88,28 +86,37 @@ public function execute()
$queryText = $query->getQueryText();
- if ($queryText != '') {
- $catalogSearchHelper = $this->_objectManager->get(\Magento\CatalogSearch\Helper\Data::class);
+ if (empty($queryText)) {
+ $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
+ return;
+ }
+
+ // Negative ?p= value is not supported, redirect to a base version of category page.
+ if ($this->_request->getParam(Toolbar::PAGE_PARM_NAME) < 0) {
+ $this->getResponse()->setRedirect(
+ $this->_url->getUrl('*/*', ['_current' => true, '_query' => [Toolbar::PAGE_PARM_NAME => null]])
+ );
+ return;
+ }
- $getAdditionalRequestParameters = $this->getRequest()->getParams();
- unset($getAdditionalRequestParameters[QueryFactory::QUERY_VAR_NAME]);
+ $catalogSearchHelper = $this->_objectManager->get(\Magento\CatalogSearch\Helper\Data::class);
- $handles = null;
- if ($query->getNumResults() == 0) {
- $this->_view->getPage()->initLayout();
- $handles = $this->_view->getLayout()->getUpdate()->getHandles();
- $handles[] = static::DEFAULT_NO_RESULT_HANDLE;
- }
+ $getAdditionalRequestParameters = $this->getRequest()->getParams();
+ unset($getAdditionalRequestParameters[QueryFactory::QUERY_VAR_NAME]);
- if (empty($getAdditionalRequestParameters) &&
- $this->_objectManager->get(PopularSearchTerms::class)->isCacheable($queryText, $storeId)
- ) {
- $this->getCacheableResult($catalogSearchHelper, $query, $handles);
- } else {
- $this->getNotCacheableResult($catalogSearchHelper, $query, $handles);
- }
+ $handles = null;
+ if ($query->getNumResults() == 0) {
+ $this->_view->getPage()->initLayout();
+ $handles = $this->_view->getLayout()->getUpdate()->getHandles();
+ $handles[] = static::DEFAULT_NO_RESULT_HANDLE;
+ }
+
+ if (empty($getAdditionalRequestParameters) &&
+ $this->_objectManager->get(PopularSearchTerms::class)->isCacheable($queryText, $storeId)
+ ) {
+ $this->getCacheableResult($catalogSearchHelper, $query, $handles);
} else {
- $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
+ $this->getNotCacheableResult($catalogSearchHelper, $query, $handles);
}
}
diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/CatalogSearchWithNegativePageNumberTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/CatalogSearchWithNegativePageNumberTest.xml
new file mode 100644
index 0000000000000..a4b9a90ab9bd7
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/CatalogSearchWithNegativePageNumberTest.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+