2

This really confuses me !!

I came to a situation, where I need to create a new block (core/template block) programmatically, if there is CMS Block present in a page layout. In general case, according to my knowledge, there are two work around for this.

1. Add a block through layout

In most of the case, this would be the best idea to do this task. We can add a block to a page if an appropriate layout handle is available. But unfortunately, in my case, I dont have any static block specific layout handle available (for cms pages, we know there is cms_page handle). So I can't rely on this method

2. Use an observer

The second method would be listen to an appropriate observer. Again, I cannot find a static block based observer that get triggered during layout/block loading time. However there are some general observers that I can rely on. I think controller_action_layout_generate_blocks_before can use in my case. But here I am facing my real problem

My real Problem

So when I use controller_action_layout_generate_blocks_before event in my case, the problem is that, I cannot retrieve blocks based on their type. I can filter blocks based on their name, but not based on their type. ie

$observer->getEvent()->getLayout()->getBlock('block_name'); //this work; Used name
$observer->getEvent()->getLayout()->getBlock('cms/block'); //this wont; use type

I cant rely on names in fact. Because I want to get all cms/block type blocks and add a new template after checking some of their custom property that I have set with static block

So how can I get all cms/block through an observer ? Is it even possible. Please share your thoughts.

3 Answers 3

5

Use this:

           <core_block_abstract_prepare_layout_before>
                <observers>
                    <ssd_test>
                        <class>ssd_test/observer</class>
                        <method>generateBlocks</method>
                        <type>singleton</type>
                    </ssd_test>
                </observers>
            </core_block_abstract_prepare_layout_before>

Observer:

public function generateBlocks($observer)
    {
        /**
         * @var $block Mage_Core_Block_Abstract
         */
        $block = $observer->getEvent()->getBlock();
        if ($block->getType() == 'cms/block') {
            //do something
        }
    }

Refer to protected function _toHtml() of the Mage_Cms_Block_Block if you want to do some changes.

Update (another solution)

    <controller_action_layout_generate_blocks_after>
        <observers>
            <ssd_test>
                <class>ssd_test/observer</class>
                <method>generateBlocks</method>
                <type>singleton</type>
            </ssd_test>
        </observers>
    </controller_action_layout_generate_blocks_after>

Observer.php:

public function generateBlocks($observer)
    {
        /**
         * @var $l Mage_Core_Model_Layout
         */
        $l = $observer->getEvent()->getLayout();

        $newBlock = $l->createBlock(
            'Mage_Core_Block_Template',
            'new_block_name_here',
            array('template' => 'some_template.phtml')
        );

        foreach ($l->getAllBlocks() as $block) {
            if ($block->getType() == 'cms/block') {
                $l->getBlock('some_block_name')->append($newBlock);
            }
        }
    }
3

Could you not simply listen to the event core_block_abstract_to_html_before then check the block type on the event and update the template based on this? Something like the following should do it.

$block = $observer->getBlock();
if ($block instanceof Mage_Cms_Block_Block) {
    // Make your changes here
}

This would work for all blocks, but if you know say that this only happens in a few instances then I would suggest changing the template via layout xml.

Or if you want to append something to a block but leave to original as it is you could use the core_block_abstract_to_html_after get the transport passed to the event. Then get the html set against this and append what you need. Again this event gives you the block so you can limit your code so simply Mage_Cms_Block_Block

$block = $observer->getBlock();
if ($block instanceof Mage_Cms_Block_Block) {
    $transport = $observer->getTransport();
    $html = $transport->getHtml();
    $html .= 'We need to append something here';
    $transport->setHtml($html);
}
0

As far as i remember you can get all blocks as a collection or as an array from the layout an then loop through checking their type using " instance of" operator.

2
  • which observer that I need to use for that. When i tried getAllBlocks(), it gave me an empty array. observer is ----generate_blocks_before Aug 15, 2014 at 10:40
  • What is about controller_action_layout_generate_blocks_after
    – Amasty
    Aug 15, 2014 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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