Magento 2.1.10 - Front controller reached 100 router match iterations caused by IWD StoreLocator
-
17-12-2020 - |
Question
I recently updated my Magento version from 2.1.1 to 2.1.10 and the module mentioned in the title is causing that exception. module version is 2.0.6
I contacted their support, and was told it is a known issue, and they're planning to solve it in the next release. The problem is that no one knows when the next release is planned and I need to put the application live in some days, so I need to solve the issue.
Actually they sent me a sort of patch, in order to substitue the di.xml
in app/code/IWD/StoreLocator/etc/frontend/di.xml
, that is just a commented version of the original one, and changed the url to store locator page to 'storelocator'.
patched di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!--<type name="Magento\Framework\App\RouterList">-->
<!--<arguments>-->
<!--<argument name="routerList" xsi:type="array">-->
<!--<item name="storelocatorroute" xsi:type="array">-->
<!--<item name="class" xsi:type="string">IWD\StoreLocator\Controller\Router</item>-->
<!--<item name="disable" xsi:type="boolean">false</item>-->
<!--<item name="sortOrder" xsi:type="string">22</item>-->
<!--</item>-->
<!--</argument>-->
<!--</arguments>-->
<!--</type>-->
</config>
Exception is disappeared, but the map contains no markers at all, hence stores are not displayed.
Does anyone has a clue on the issue?
EDIT - The router causing the problem
public function match(\Magento\Framework\App\RequestInterface $request)
{
$status = $this->_scopeConfig->getValue('iwd_storelocator/general/is_active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
if(!$status){
return;
}
$locatorRoute = $this->_scopeConfig->getValue('iwd_storelocator/general/path', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$path = strtolower($locatorRoute);
$path = trim($locatorRoute);
$identifier = trim($request->getPathInfo(), '/');
$action = $request->getActionName();
if($identifier == $locatorRoute) {
$request->setModuleName('storelocator')
->setControllerName('index')
->setActionName($action);
} else {
//There is no match
return;
}
/*
* We have match and now we will forward action
*/
return $this->actionFactory->create(
'Magento\Framework\App\Action\Forward',
['request' => $request]
);
}
EDIT 2 To avoid redirection I've added a dummy counter to the controller, to avoid too many redirections, like this
if($identifier == $locatorRoute && $this->count < 2) {
$request->setModuleName('storelocator')
->setControllerName('index')
->setActionName($action);
} else {
return;
}
but I get the same result as commenting the di.xml, so no marker is shown on the map.
Solution
The extension support has very kindly sent me a patch to be applied that solves the problem and told me I could post the code here. Maybe it could be of help for someone else.
Just substitute the app/code/IWD/StoreLocator/Block/Search.php
with this one:
<?php
namespace IWD\StoreLocator\Block;
use Magento\Framework\View\Element\Template;
use IWD\StoreLocator\Model\ResourceModel\Item\CollectionFactory as ItemCollectionFactory;
/**
* Class Search
* @package IWD\StoreLocator\Block
*/
class Search extends Template
{
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $scopeConfig;
/**
* @var \Magento\Directory\Model\CountryFactory
*/
private $countryFactory;
/**
* @var \Magento\Directory\Model\RegionFactory
*/
private $regionFactory;
/**
* @var ItemCollectionFactory
*/
private $ItemCollectionFactory;
/**
* @var \IWD\StoreLocator\Model\Image
*/
private $imageHelper;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $storeManager;
/**
* Search constructor.
* @param Template\Context $context
* @param \Magento\Directory\Model\CountryFactory $countryFactory
* @param \Magento\Directory\Model\RegionFactory $regionFactory
* @param ItemCollectionFactory $ItemCollectionFactory
* @param \IWD\StoreLocator\Model\Image $imageHelper
*/
public function __construct(
Template\Context $context,
\Magento\Directory\Model\CountryFactory $countryFactory,
\Magento\Directory\Model\RegionFactory $regionFactory,
ItemCollectionFactory $ItemCollectionFactory,
\IWD\StoreLocator\Model\Image $imageHelper
) {
$this->countryFactory = $countryFactory;
$this->regionFactory = $regionFactory;
$this->ItemCollectionFactory = $ItemCollectionFactory;
$this->storeManager = $context->getStoreManager();
$this->imageHelper = $imageHelper;
$this->scopeConfig = $context->getScopeConfig();
parent::__construct($context);
}
/**
* @return $this
*/
protected function _prepareLayout()
{
$metaTitle = $this->scopeConfig->getValue('iwd_storelocator/general/meta_title', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$metaKeywords = $this->scopeConfig->getValue('iwd_storelocator/general/meta_keyword', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$metaDescription = $this->scopeConfig->getValue('iwd_storelocator/general/meta_description', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$this->pageConfig->getTitle()->set($metaTitle);
$this->pageConfig->setKeywords($metaKeywords);
$this->pageConfig->setDescription($metaDescription);
$pageMainTitle = $this->getLayout()->getBlock('page.main.title');
if ($pageMainTitle) {
// Setting empty page title if content heading is absent
$pageMainTitle->setPageTitle($this->escapeHtml($metaTitle));
}
return parent::_prepareLayout();
}
public function getGMBrowserApiKey()
{
return $this->scopeConfig->getValue('iwd_storelocator/gm/browser_api_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}
public function getSearchOnLoad()
{
return (int)$this->scopeConfig->getValue('iwd_storelocator/search/search_onload', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}
public function getConfigOption($path, $bool = false)
{
if (!$bool) {
return $this->scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}
return (bool)$this->scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}
public function init()
{
$metric = $this->scopeConfig->getValue('iwd_storelocator/search/metric', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
if ($metric == 1) {
$metric = __('Km');
} elseif ($metric == 2) {
$metric = __('Miles');
}
$fillColor = $this->getConfigOption("iwd_storelocator/design/fill_color");
if (!preg_match('/#/i', $fillColor)) {
$fillColor= '#' . $fillColor;
}
$strokeColor = $this->getConfigOption("iwd_storelocator/design/stroke_color");
if (!preg_match('/#/i', $strokeColor)) {
$strokeColor= '#' . $strokeColor;
}
$folderName = \IWD\StoreLocator\Model\Config\Backend\Image\Marker::UPLOAD_DIR;
$placeholder = $this->getConfigOption('iwd_storelocator/design/placeholder');
if (!empty($placeholder)) {
$path = $folderName . '/' . $placeholder;
$placeholder = $this->_urlBuilder->getBaseUrl(['_type' => \Magento\Framework\UrlInterface::URL_TYPE_MEDIA]) . $path;
} else {
$placeholder = $this->getViewFileUrl('IWD_StoreLocator::images/placeholder.png');
}
$marker = $this->getConfigOption('iwd_storelocator/gm/marker');
if (!empty($marker)) {
$path = $folderName . '/' . $marker;
$marker = $this->_urlBuilder->getBaseUrl(['_type' => \Magento\Framework\UrlInterface::URL_TYPE_MEDIA]) . $path;
} else {
$marker = $this->getViewFileUrl('IWD_StoreLocator::images/marker.png');
}
$data = [
'StoreLocator'=>[
'url' => $this->_urlBuilder->getBaseUrl().'rest/V1/storelocator/search',
'searchOnload' => $this->getSearchOnLoad(),
'markerUrl' => $this->getViewFileUrl('IWD_StoreLocator::images/marker.png'),
'closeUrl' => $this->getViewFileUrl('IWD_StoreLocator::images/close.png'),
'pagination' => (int)$this->getConfigOption('iwd_storelocator/search/pagination'),
'dropdown' => $this->_prepareCountrytRegion(),
'baseUrlImage' => $this->imageHelper->getBaseUrl(),
'radiusDecorator' => [
'active' => (int)$this->getConfigOption("iwd_storelocator/design/hightlight_result"),
'fillColor' => $fillColor,
'fillOpacity' => $this->getConfigOption("iwd_storelocator/design/opacity"),
'strokeColor' => $strokeColor,
'strokeOpacity' => $this->getConfigOption("iwd_storelocator/design/stroke_opacity"),
'strokeWeight'=> $this->getConfigOption("iwd_storelocator/design/stroke_weight"),
],
'metric' => $metric,
'placeholder_visability' => !$this->getConfigOption("iwd_storelocator/design/hide_placeholders", true),
'empty_message' =>$this->getConfigOption('iwd_storelocator/search/message'),
'placeholder' => $placeholder,
'marker' => $marker,
'pageSize' => $this->getConfigOption('iwd_storelocator/search/page_size'),
]
];
return json_encode($data);
}
private function _prepareCountrytRegion()
{
$list = $this->_getListCountries();
foreach ($list as $code => &$country) {
$country = ['regions'=>$this->_getRegions($code)];
}
return $list;
}
private function _getRegions($country)
{
$storeId = $this->storeManager->getStore()->getId();
$collection = $this->ItemCollectionFactory->create();
$collection->addFieldToFilter('is_active', ['eq' => 1]);
$collection->addFieldToFilter('country_id', ['eq' => $country]);
$collection->addStoreFilter($storeId, true);
$regions = [];
foreach ($collection as $blockModel) {
$regions[] = $blockModel->getRegionId();
}
$regions = array_unique($regions);
sort($regions);
$result = [];
foreach ($regions as $region) {
$regionModel = $this->regionFactory->create()->load($region);
if ($regionModel->getId()) {
$result[$regionModel->getName()] = $region;
}
}
return $result;
}
private function _getListCountries()
{
$storeId = $this->storeManager->getStore()->getId();
$collection = $this->ItemCollectionFactory->create();
$collection->addFieldToFilter('is_active', ['eq' => 1]);
$collection->addStoreFilter($storeId, true);
$countries = [];
foreach ($collection as $blockModel) {
$countries[] = $blockModel->getCountryId();
}
$countries = array_unique($countries);
$data = [];
foreach ($countries as $code) {
if (!empty($code)) {
$data[$code] = $this->countryFactory->create()->loadByCode($code)->getName();
}
}
return $data;
}
/**
* @return bool
*/
public function getScrollWheel()
{
return $this->getConfigOption("iwd_storelocator/gm/scrollwheel_zooming");
}
/**
* @return bool
*/
public function getScaleControl()
{
return $this->getConfigOption("iwd_storelocator/gm/scale_control");
}
/**
* @return bool
*/
public function getMapTypeControl()
{
return $this->getConfigOption("iwd_storelocator/gm/type_control");
}
/**
* @return bool
*/
public function getCmsBlock()
{
return $this->getConfigOption("iwd_storelocator/general/cms");
}
}