Problem encountered at our web agency: A page link integrated into the online store system Magento 2 using a widget was not displayed on our no-route page, even though this was configured accordingly in the Magento backend. The type was set to "Page Link", Package/Theme to "Luma", and all available store views were selected ("All Store Views" would also have been sufficient!). The sort order is irrelevant here. The layout updates were configured for "Specified Page", namely the "CMS No-Route Default Page" ("CMS No Route"). This did not work either, but we will take a closer look at this later:

On the homepage, however, everything works perfectly. So let's take a look at where the layout updates are handled in the widget module. The following file immediately catches our attention:
vendor\magento\module-widget\Model\ResourceModel\Layout\Update.php
In this file, the fetchUpdatesByHandle() function works with the selected handles (layout identifiers). During testing, it becomes apparent that the identifiers / handles have different names here. For example, the handle for the Magento page "CMS No-Route Default Page" is "cms_index_defaultnoroute", while the handle for the Magento page "CMS No-Route Page" is "cms_index_noroute". These handles are also entered in the widget table "widget_instance_page" in the corresponding column.
Just as a quick preview: Instead of "cms_index_noroute", it needs to be "cms_noroute_index", and instead of "cms_index_defaultnoroute", it needs to be "cms_noroute_index_id_no-route". This is what the getDefaultLayoutHandle() function in
vendor\magento\framework\View\Result\Layout.php
requires, as well as the getFullActionName() function in
vendor\magento\framework\App\Request\Http.php
because the handle name of the requested page is constructed from:
$this->getRouteName() .$this->getRouteName() .$delimiter.$this->getControllerName() .$delimiter .$this->getActionName();
The $delimiter variable is an underscore, $this->getRouteName() returns "cms", $this->getControllerName() returns "noroute", and $this->getActionName() returns "index", resulting in "cms_noroute_index". If this string is then unsuccessfully compared against "cms_index_noroute", the layout update is not applied.
A similar situation occurs with "cms_index_defaultnoroute", except that in this case the ID is additionally appended with underscores in the prepareResultPage() function in
F
vendor\magento\module-cms\Helper\Page.php
and subsequently in the addPageLayoutHandles() function in
vendor\magento\framework\View\Result\Page.php
So here the handle "cms_index_defaultnoroute" is compared against "cms_noroute_index_id_no-route" — which cannot work either.
So where do these incorrect handles come from? We find them in the following file:
vendor\magento\module-cms\etc\frontend\page_types.xml
which is used to assemble the handles:
<page_types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_types.xsd">
<type id="cms_index_defaultindex" label="CMS Home Default Page"/>
<type id="cms_index_defaultnoroute" label="CMS No-Route Default Page"/>
<type id="cms_index_index" label="CMS Home Page"/>
<type id="cms_index_nocookies" label="CMS No-Cookies Page"/>
<type id="cms_index_noroute" label="CMS No-Route Page"/>
<type id="cms_page_view" label="CMS Pages (All)"/>
</page_types>
We now need to add the correct handles. It is best not to modify this Core file, but instead to add them in an appropriate extension, for example in the file
app\code\Econcess\Fixhandle\etc\frontend\page_types.xml in the following form (we also included the Default Home Page because it is incorrect in the same way, but this is of course not intended to be a complete list!):
<?xml version="1.0"?>
<page_types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_types.xsd">
<type id="cms_index_index_id_home" label="CMS Home Default Page econcess"/>
<type id="cms_noroute_index_id_no-route" label="CMS No-Route Default Page econcess"/>
<type id="cms_noroute_index" label="CMS No-Route Page econcess"/>
</page_types>
Magento widgets now also work on the aforementioned CMS pages. Tested in an online store running Magento CE 2.2.5.
