3 November 2015

Updating your modules for SUPEE-6788

I was surprised today to be reading some of the answers on SE to a question on how to update your modules to be compatible with the recent SUPEE-6788 patch.  Some people really seem to be misunderstanding whats needed here and making things a lot more complex than needed.

As you probably know the main change introduced by the patch is removing the use of custom admin frontnames forcing you to base your admin requests off the main admin controllers frontname which is admin by default, so instead of a path like /somefrontname/somecontroller/someaction you instead must use /admin/somecontroller/someaction.  I've seen some people saying that you have to now put your admin controllers inside an adminhtml directory, and also that your controller name must be unique.  Neither of these are true, but the second does depend on what you are trying to achieve, you see the method you are now forced to use can not only be used to add your own admin request paths, it can also be used to rewrite an existing controller.

So here is a short tutorial on how to update your module to work with SUPEE-6788, hopefully clearing up a few misconceptions along the way.

The first thing to say is that there has been two methods of adding your own admin requests for a long time, so using the method this patch forces you to is nothing new.  Granted the documentation released with the patch was far from extensive, and misses out the fact that altering your admin routing may also introduce a requirement to update layout files, calls to generate admin URLs and adminhtml menu additions, on top of config.xml.  There was however enough to information to understand the config.xml change needed and so figure out any extra bits that might be needed.

So lets get down to the code.  You might currently have a router configured like this in your config.xml:

<?xml version="1.0"?>
<config>
    ...
    <admin>
        <routers>
            <somemodule>
                <use>admin</use>
                <args>
                    <module>Namespace_Module</module>
                    <frontName>somemodule</frontName>
                </args>
            </somemodule>
        </routers>
    </admin>
    ...
</config>

An admin menu item configured liked this in adminhtml.xml:

<?xml version="1.0"?>
<config>
    ...
    <menu>
        <sales>
            <children>
                <somemodule translate="title">
                    <title>Menu Title</title>
                    <sort_order>20</sort_order>
                    <action>somemodule/somecontroller/someaction</action>
                </somemodule>
            </children>
        </sales>
    </menu>
    ...
</config>

Layout handles configured like this in your layout file:

<?xml version="1.0"?>
<layout version="0.1.0">
    ...
    <somemodule_somecontroller_someaction>
        <reference name="content">
            ...
        </reference>
    </somemodule_somecontroller_someaction>
    ...
</layout>

And calls to generate admin URLs like this:

$url = Mage::helper('adminhtml')->getUrl('somemodule/somecontroller/someaction');

So that's what your module might look like at the moment. To update it to work with the new restrictions in the SUPEE-6788 patch you need to update it as follows. Now you should define your router in config.xml like this:

<?xml version="1.0"?>
<config>
    ...
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <Namespace_Module after="Mage_Adminhtml">Namespace_Module</Namespace_Module>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
    ...
</config>

Declaring your router like this means that when looking for a routing match for the Mage_Adminhtml module (which all core admin requests are routed to), your module is also checked for a routing match. In the example above we use after="Mage_Adminhtml" which means Mage_Adminhtml is checked for a match first, then your module if no match was found. You can also use before="Mage_Adminhtml" which will mean your module is checked for a routing match before Mage_Adminhtml. This means that if you have an equivalent controller to one in Mage_Adminhtml then you will rewrite requests to that controller to your module as routing matches your module first and Mage_Adminhtml is not checked.

So if you want to rewrite a controller use before, but if you just are adding your own controller use after to save the overhead of checking for a match against your module for every admin request.

One other thing to note with declaring routing this way is that you can define the starting directory location for your controllers. So above we have:

<Namespace_Module after="Mage_Adminhtml">Namespace_Module</Namespace_Module>

This means that controller classes will be searched for in the Namespace/Module/controllers/ directory of you module. If you instead used:

<Namespace_Module after="Mage_Adminhtml">Namespace_Module_Adminhtml</Namespace_Module>

controller classes would then be searched for in the Namespace/Module/controllers/Adminhtml/ directory of your module. This is a fairly popular, but certainly not required way of doing things and probably goes back to a time when this routing request was mainly used just for rewriting controllers, where you may also have defined your own custom routing URL.

With your module routing configured like this, you would add your admin menu item in adminhtml.xml like this:

<?xml version="1.0"?>
<config>
    ...
    <menu>
        <sales>
            <children>
                <somemodule translate="title">
                    <title>Menu Title</title>
                    <sort_order>20</sort_order>
                    <action>adminhtml/somecontroller/someaction</action>
                </somemodule>
            </children>
        </sales>
    </menu>
    ...
</config>

Your layout file would look then like this:

<?xml version="1.0"?>
<layout version="0.1.0">
    ...
    <adminhtml_somecontroller_someaction>
        <reference name="content">
            ...
        </reference>
    </adminhtml_somecontroller_someaction>
    ...
</layout>

And calls to generate admin URLs would now be:

$url = Mage::helper('adminhtml')->getUrl('adminhtml/somecontroller/someaction');

So to summarise it's as simple as altering the routing in config.xml and then changing frontname references to 'adminhtml' in adminhtml.xml, layout files and calls to getUrl().

No comments:

Post a Comment