4

I'm trying to change the layout handle for specific CMS pages in the back end.

To do this I'm trying to use the following in Design->Page Layout->Layout Update XML

<update handle="store_page" />

My aim is to write a specific layout in the local.xml, pulling in other blocks just for those CMS pages marked as a Store Page.

However when I put this code in it does not update the handle for the CMS page - is anyone able to offer any help on where I may be going wrong or if this is possible? Is there a better way to achieve this?

6

You can't do that. Specifically, you can't use the <update/> tag in a CMS page's Layout Update XML field.

Magento processes the <update/> nodes when it is initially loading the layout update files, and layout updates from the core_layout_update table. This is done with the fetchRecursiveUpdates function.

#File: app/code/core/Mage/Core/Model/Layout/Update.php

public function fetchPackageLayoutUpdates($handle)
{
    //...
        $this->fetchRecursiveUpdates($updateXml);
    //...

    return true;
}

public function fetchDbLayoutUpdates($handle)
{
    //...
    $this->fetchRecursiveUpdates($updateXml);        
    //...        
}

//...
public function fetchRecursiveUpdates($updateXml)
{
    foreach ($updateXml->children() as $child) {
        if (strtolower($child->getName())=='update' && isset($child['handle'])) {
            $this->merge((string)$child['handle']);
            // Adding merged layout handle to the list of applied hanles
            $this->addHandle((string)$child['handle']);
        }
    }
    return $this;
}

A CMS page, however, is rendered later on via a helper method. The rendering of a CMS page includes this code

#File: app/code/core/Mage/Cms/Helper/Page.php

$action->loadLayoutUpdates();
$layoutUpdate = ($page->getCustomLayoutUpdateXml() && $inRange)
    ? $page->getCustomLayoutUpdateXml() : $page->getLayoutUpdateXml();
$action->getLayout()->getUpdate()->addUpdate($layoutUpdate);
$action->generateLayoutXml()->generateLayoutBlocks();    

The loadLayoutUpdates call is the standard loading of the layout, including the fetchRecursiveUpdates mentioned above.

Then, Magento looks for a custom layout XML update set on the CMS page object

$layoutUpdate = ($page->getCustomLayoutUpdateXml() && $inRange)
    ? $page->getCustomLayoutUpdateXml() : $page->getLayoutUpdateXml();

and adds it directly to the list of updates to apply

$action->getLayout()->getUpdate()->addUpdate($layoutUpdate);

This means the scanning for the update tag is never done.

If I was trying to implement something like this, I'd add a new block in the CMS page's layout update XML, and then add the shared layout items programmatically in the blocks _prepareLayout method. (not sure off the top of my head if that would work w/r/t to timing, but that'd be where I'd start)

2

The <update /> directive adds the handle (and its directives) to the current rendering scope; it does not replace the current handle.

  • The directives in the new handle are not being applied, to test it I am trying to add a body class which is not getting shown. My local.xml code is: <store_page> <reference name="root"> <action method="addBodyClass"><className>store-page</className></action> </reference> </store_page> – Adam May 24 '13 at 12:22
  • Currently debugging this - I'm getting the same (bug) behavior as you. – benmarks May 24 '13 at 13:05
  • Thanks, is there an alternative way to achieve this that you know of? – Adam May 24 '13 at 13:44
  • Each cms page has its own handle IIRC.... – benmarks May 24 '13 at 14:57
  • They do but the objective was to make it more manageable by the client, they could just put the one line of xml in the layout updates as opposed to updating each handle via the local.xml file. Must be a bug then? – Adam May 24 '13 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.