Magento – What do I do when an extension overwrites a class globally and I want to use the original

extensionsmagento-1overrides

We're using an extension which globally overwrites the Mage_Catalog_Block_Product_List_Toolbar block.

<global>
    <blocks>
        <catalog>
            <rewrite>
                <product_list_toolbar>Amasty_Shopby_Block_Catalog_Product_List_Toolbar</product_list_toolbar>
            </rewrite>
        </catalog>
    </blocks>
</global>

While the extension works in the context of a layered navigation category, the rewritten class doesn't work properly when we insert an arbitrary product list into another (custom) view in our own in-house module. If we take out the extension overwrite just for testing purposes, everything works fine.

How can we undo an extension's rewrite just for our own controller, without editing the extension developer's community code?

Best Answer

Caveats: There's no designed way to do what you're asking in the system. The following should work, but I've never tried it out extensively on a production system, and there may be situations where it will cause more trouble that it's worth. Only proceed if you're comfortable debugging problems related to the changing the rewrites of a working system.

Step 1 is undoing the rewrite. The Magento configuration tree can be changed at runtime. So, if you run the following code

$config = Mage::getConfig();        
$config->setNode(
    'global/blocks/catalog/rewrite/product_list_toolbar',
    'Mage_Catalog_Block_Product_List_Toolbar'
);

Then Magento will instantiate the original Mage_Catalog_Block_Product_List_Toolbar block for the remainder of the request.

Step 2 is deciding where to call this in your module. Since this is just for your controller and it's rewriting a block that won't be instantiated until the end of your controller, I'd add a method to your controller class something like this

protected function _undoRewrites()
{
    $config = Mage::getConfig();        
    $config->setNode(
        'global/blocks/catalog/rewrite/product_list_toolbar',
        'Mage_Catalog_Block_Product_List_Toolbar'
    );    
}

and then just call this method at the start of each of your actions

public function indexAction()
{
    $this->_undoRewrites();
    $test = Mage::getSingleton('core/layout')->createBlock('catalog/product_list_toolbar');        
    var_dump($test);
}

This may seem a little clunky, but I think it's a good idea to be clunky (i.e. obvious) when you're being clever with Magento's system objects. Another place for this could be the controller_action_predispatch or controller_action_predispatch_front_controller_action events and/or applied conditionally.

Just remember the rewrite won't be undone until this method is called. That means if you attempt to instantiate a block before calling _undoRewrites, the rewritten class will be used to instantiate the object.

Related Topic