Magento Admin Initialization

In this blog post we will see how magento admin interface initializes, how the adminhtml area/theme loads and other such things.

Admin Router Matching

The first step is route matching, i.e based on the URL opened magento recognizes that its an admin route.
This process happens in the Mage_Core_Controller_Varien_Front class, here we the have two routers “Mage_Core_Controller_Varien_Router_Admin” and “Mage_Core_Controller_Varien_Router_Standard”

The admin router, loads the router defined in “Mage/Adminhtml/etc/config.xml”

<admin>
        <routers>
            <adminhtml>
                <use>admin</use>
                <args>
                    <module>Mage_Adminhtml</module>
                    <frontName>admin</frontName>
                </args>
            </adminhtml>
        </routers>
    </admin>

It mentioned here the frontName should be “admin”. So any URL which has “admin” matches this module.
So lets assume we have a URL “http://127.0.0.1/magento/index.php/admin/customer/index/key/d7a5d6abf3c1c8b8b975cc863ced13a7/”
Here /admin matches the module “Mage_Adminhtml”
next /customer matches the CustomerController and /index is the indexAction

Admin Controller

We know that all admin controllers extend the class “Mage_Adminhtml_Controller_Action” . If you look at the “preDispatch()” function in this controller, many important things happen here.

        Mage::getDesign()
            ->setArea($this->_currentArea)
            ->setPackageName((string)Mage::getConfig()->getNode('stores/admin/design/package/name'))
            ->setTheme((string)Mage::getConfig()->getNode('stores/admin/design/theme/default'))
        ;
        foreach (array('layout', 'template', 'skin', 'locale') as $type) {
            if ($value = (string)Mage::getConfig()->getNode("stores/admin/design/theme/{$type}")) {
                Mage::getDesign()->setTheme($type, $value);
            }
        }

Above we how the admin package and theme is set, also how layout, template, skin, locale folders are set.
Next we have

$this->getLayout()->setArea($this->_currentArea);  
parent::preDispatch();

This two lines are very important. The first line sets “adminhtml” as the current area in layout object and in parent::preDispatch() we have the code

Mage::app()->loadArea($this->getLayout()->getArea());

So basically because of this “adminhtml” area gets set in “core/app” object, and because of this “adminhtml” events start getting fired. Before this step any event in area “adminhtml” wont work.

Next we have

        $_isValidFormKey = true;
        $_isValidSecretKey = true;
        $_keyErrorMsg = '';
        if (Mage::getSingleton('admin/session')->isLoggedIn()) {
            if ($this->getRequest()->isPost()) {
                $_isValidFormKey = $this->_validateFormKey();
                $_keyErrorMsg = Mage::helper('adminhtml')->__('Invalid Form Key. Please refresh the page.');
            } elseif (Mage::getSingleton('adminhtml/url')->useSecretKey()) {
                $_isValidSecretKey = $this->_validateSecretKey();
                $_keyErrorMsg = Mage::helper('adminhtml')->__('Invalid Secret Key. Please refresh the page.');
            }
        }

Here validation of form key or secret key happens. Even url in magento admin is validated for “csrf” and this where it happens.

Admin Login Check

In the config.xml of “Mage_Adminhtml” module there is an event defined “controller_action_predispatch”. This event calls the function “actionPreDispatchAdmin” in class “Mage_Admin_Model_Observer”.
This is where the login check for admin happens, if user is not logged in then he is redirected to a “denied” page. Only these actions are excluded from login check

        $openActions = array(
            'forgotpassword',
            'resetpassword',
            'resetpasswordpost',
            'logout',
            'refresh' // captcha refresh
        );

Also if user is logged in already then function called is “refreshAcl” in “admin/session” object.

Admin User Permission/ACL

Above we saw if user is logged in then “refreshAcl” function gets called.
This function is defined as

    public function refreshAcl($user = null)
    {
        if (is_null($user)) {
            $user = $this->getUser();
        }
        if (!$user) {
            return $this;
        }
        if (!$this->getAcl() || $user->getReloadAclFlag()) {
            $this->setAcl(Mage::getResourceModel('admin/acl')->loadAcl());
        }
        if ($user->getReloadAclFlag()) {
            $user->unsetData('password');
            $user->setReloadAclFlag('0')->save();
        }
        return $this;
    }

So when user logs in first time only then the “loadAcl” function is called on the resource model. Or else the entire user acl is stored in session. There is also another way to reload acl for user, but setting the “reload_acl_flag”

$user->setReloadAclFlag(true)

If we do this then acl will again be loading fully.