How to check whether a block exist ( based on its type )
-
11-12-2019 - |
Question
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.
Solution
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);
}
}
}
OTHER TIPS
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);
}
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.