Search

Mar 1, 2024

Magento 2: Load the another store page when URLs result in 404s on the current store (by the request path)

Lexim/Seo/etc/frontend/events.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <!-- Detect 404 page and switch store -->
    <!-- event controller_action_predispatch_cms_noroute_index. It will call only for 404 pages. -->
    <event name="controller_action_predispatch_cms_noroute_index">
        <observer name="check_404_and_redirect_to_fr" instance="Lexim\Seo\Observer\NotFoundRedirectHandler" />
    </event>
</config>


Lexim/Seo/Observer/NotFoundRedirectHandler.php


<?php
declare(strict_types=1);

namespace Lexim\Seo\Observer;

use Magento\Framework\App\ActionFlag;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Exception\NoSuchEntityException;

use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\StoreCookieManagerInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;

/**
 * Class NotFoundRedirectHandler
 *
 * @package Lexim\Seo\Observer
 */
class NotFoundRedirectHandler implements ObserverInterface
{
    /** @var ResponseInterface */
    private $_responseInterface;

    /** @var Http */
    private $_request;

    /** @var ActionFlag */
    private $_actionFlag;

    /** @var StoreManagerInterface */
    private $_storeManagerInterface;

    /** @var UrlFinderInterface */
    private $_urlFinder;

    /** @var HttpContext */
    private $_httpContext;

    /** @var StoreCookieManagerInterface */
    private $_storeCookieManager;


    /**
     * NotFoundRedirectHandler constructor.
     *
     * @param Http $request
     * @param ActionFlag $actionFlag
     * @param ResponseInterface $responseInterface
     * @param StoreManagerInterface $_storeManagerInterface
     * @param UrlFinderInterface $_urlFinder
     * @param HttpContext $_httpContext
     * @param StoreCookieManagerInterface $_storeCookieManager
     */
    public function __construct(
        Http                        $request,
        ActionFlag                  $actionFlag,
        ResponseInterface           $responseInterface,
        StoreManagerInterface       $_storeManagerInterface,
        UrlFinderInterface          $_urlFinder,
        HttpContext                 $_httpContext,
        StoreCookieManagerInterface $_storeCookieManager,

    )
    {
        $this->_request = $request;
        $this->_actionFlag = $actionFlag;
        $this->_responseInterface = $responseInterface;
        $this->_storeManagerInterface = $_storeManagerInterface;
        $this->_urlFinder = $_urlFinder;
        $this->_httpContext = $_httpContext;
        $this->_storeCookieManager = $_storeCookieManager;
    }

    /**
     * @param Observer $observer
     *
     * @return void
     */
    public function execute(Observer $observer)
    {
        $getFullActionName = $this->_request->getFullActionName(); // _noroute_index, cms_noroute_index
        $getRequestString = $this->_request->getRequestString(); // "/what-is-adaptive-clothing-fr"
        $getRequestString = ltrim($getRequestString, "/");
        $isAjax = intval($this->_request->isAjax()); // 0, 1
        $storeCode = $this->getCurrentStoreCode();

        if (
            in_array($getFullActionName, ['cms_noroute_index', '_noroute_index']) &&
            $isAjax == 0 &&
            $storeCode === 'english'
        ) {

            $allStores = $this->getAllStores();
            $frenchCode = 'french';
            $frenchStore = $allStores[$frenchCode] ?? null;
            if ($frenchStore) {
                $frenchId = $frenchStore->getId();
                $frRewrite = $this->findOneData($getRequestString, $frenchId);

                if ($frRewrite) {
                    // Switch CA Store from english to french
                    $this->_httpContext->setValue('store', $frenchCode, $frenchCode);
                    $this->_storeCookieManager->setStoreCookie($frenchStore);

                    // Prevent the default action from being executed
                    $this->_actionFlag->set('', ActionInterface::FLAG_NO_DISPATCH, true);

                    // Redirect to the current URL in french
                    $this->_responseInterface->setRedirect($getRequestString);
                }
            }
        }

    }

    /**
     * @param $requestPath
     * @param $storeId
     *
     * @return UrlRewrite|null
     */
    protected function findOneData($requestPath, $storeId)
    {
        return $this->_urlFinder->findOneByData(
            [
                UrlRewrite::REQUEST_PATH => $requestPath,
                UrlRewrite::STORE_ID => $storeId
            ]
        );
    }

    /**
     * @return StoreInterface[]
     */
    protected function getAllStores(): array
    {
        $stores = $this->_storeManagerInterface->getStores(true, true);
        if (isset($stores['admin'])) { // remove admin store
            unset($stores['admin']);
        }
        return $stores;
    }

    /**
     * @return string
     * @throws NoSuchEntityException
     */
    protected function getCurrentStoreCode(): string
    {
        $curStore = $this->getCurrentStore();
        return $curStore->getCode(); // english, french, us
    }

    /**
     * @return StoreInterface
     * @throws NoSuchEntityException
     */
    protected function getCurrentStore()
    {
        return $this->_storeManagerInterface->getStore();
    }

}

No comments:

Post a Comment