Magento's core code is calling _setActiveMenu
after it loads the layout. So your setActive
gets called, but then Magento calls setActive
again, so Magento wins.
Details: To render a Magento layout, the author of a controller action method needs to call
$this->loadLayout();
$this->renderLayout();
When they call loadLayout
, that's the method which goes through the layout update XML, instantiates the configured blocks, and calls any <action/>
methods.
In the report controllers, the soldAction
method looks like this
#File: app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php
public function soldAction()
{
$this->_title($this->__('Reports'))
->_title($this->__('Products'))
->_title($this->__('Products Ordered'));
$this->_initAction()
->_setActiveMenu('report/product/sold')
->_addBreadcrumb(Mage::helper('reports')->__('Products Ordered'), Mage::helper('reports')->__('Products Ordered'))
->_addContent($this->getLayout()->createBlock('adminhtml/report_product_sold'))
->renderLayout();
}
So where's the call to loadLayout
? Is happens in _initAction
.
#File: app/code/core/Mage/Adminhtml/Controller/Report/Abstract.php
public function _initAction()
{
$this->loadLayout()
->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports'));
return $this;
}
So, since the report controller calls loadLayout
first, and then sets the active menu, your layout update XML can never win.
One possible solution is an event observer for controller_action_layout_render_before
, and if the listener set the active menu if you're on the correct page (otherwise just return early from the observer)