So I'm trying to accomplish the following: I want to add a third view mode to the product listing (I called it "gridx5") using event observers.
I originally did it via Blocks rewrites and it was working fine but I want to do it via observers now as it's conflicting with 3rd party modules depending on which website I install the module.
So here it what I've got:
config.xml
<global>
<events>
<core_block_abstract_to_html_before>
<observers>
<extendedcatalog_toolbar_modes>
<type>singleton</type>
<class>extendedcatalog/observer</class>
<method>addToolbarModes</method>
</extendedcatalog_toolbar_modes>
</observers>
</core_block_abstract_to_html_before>
</events>
</global>
In my observer, I've got this:
public function addToolbarModes(Varien_Event_Observer $observer)
{
$block = $observer->getEvent()->getBlock();
if ($block instanceof Mage_Catalog_Block_Product_List) {
switch (Mage::getStoreConfig('catalog/frontend/list_mode')) {
case 'grid':
$block->setModes(array('grid' => $block->__('Grid')));
break;
case 'gridx5':
$block->setModes(array('gridx5' => $block->__('Grid x5')));
break;
case 'list':
$block->setModes(array('list' => $block->__('List')));
break;
/*** Etc for the other cases ***/
}
}
}
So everything above works, but according to my tests, here is what happens.
So basically in _beforeToHtml
function of the Mage_Catalog_Block_Product_List
block, you've got this part of code:
if ($modes = $this->getModes()) {
$toolbar->setModes($modes);
}
This is where this block is supposed to set the modes of the toolbar block. Then in the setModes
of the Mage_Catalog_Block_Product_List_Toolbar
block:
public function setModes($modes)
{
if(!isset($this->_availableMode)){
$this->_availableMode = $modes;
}
return $this;
}
HERE is the problem, by default the $_availableMode
is an empty array.
But that means the condition above is ALWAYS true right ?
EDIT based on questions asked:
- Why using the
setModes
function onMage_Catalog_Block_Product_List_Toolbar
does not work:
In the _construct()
method, the _availableModes
is supposed to be set with a value like this:
switch (Mage::getStoreConfig('catalog/frontend/list_mode')) {
case 'grid':
$this->_availableMode = array('grid' => $this->__('Grid'));
break;
case 'list':
$this->_availableMode = array('list' => $this->__('List'));
break;
case 'grid-list':
$this->_availableMode = array('grid' => $this->__('Grid'), 'list' => $this->__('List'));
break;
case 'list-grid':
$this->_availableMode = array('list' => $this->__('List'), 'grid' => $this->__('Grid'));
break;
}
However, as my mode value is "gridx5" is not listed in the cases of the switch, the variable keep its original value defined at the top of the file, so an empty array.
Thus when I use the setModes
method, the variable is considered as set so my value is automatically skipped with the code below:
public function setModes($modes)
{
if(!isset($this->_availableMode)){
$this->_availableMode = $modes;
}
return $this;
}
So three questions here (EDIT: added the answers):
am I doing something wrong ? No, definitely was the good idea.
shouldn't Magento use if(empty()) instead of if (!isset()) ? Yes and No, see below.
can I do it WITHOUT rewriting the toolbar block NOR rewriting the setModes function ? It is actually not possible to add a new mode without rewriting the toolbar block.
Reasons behind that is the following code in the toolbar block, it is too closed to let anyone add a new mode without rewriting everything. That's why Magento uses !isset because of empty, there is no reason to use the least because no one can add a mode using the setModes.
Below is the other parts of the code (does not include the construct function as already pasted above) that I found too strict to let someone add a mode via observer:
public function getDefaultPerPageValue()
{
if ($this->getCurrentMode() == 'list') {
if ($default = $this->getDefaultListPerPage()) {
return $default;
}
return Mage::getStoreConfig('catalog/frontend/list_per_page');
}
elseif ($this->getCurrentMode() == 'grid') {
if ($default = $this->getDefaultGridPerPage()) {
return $default;
}
return Mage::getStoreConfig('catalog/frontend/grid_per_page');
}
return 0;
}
public function getAvailableLimit()
{
$currentMode = $this->getCurrentMode();
if (in_array($currentMode, array('list', 'grid'))) {
return $this->_getAvailableLimit($currentMode);
} else {
return $this->_defaultAvailableLimit;
}
}