Magento: Editing top navigation sub nav structure - magento

I need to do a bit of major editing to the sub navigation displayed from the standard Magento top level navigation.
I've gone into top.phtml and found that it calls a function in the core Mage code, Is it possible to have a file in my theme run before this is called or do I have to create a totally custom navigation/use a extension?

You're always more than welcome to simply replace the design/frontend/[package]/[theme]/catalog/navigation/top.phtml template with your own markup which you can then iterate over as you please.
The Block class already provides some basic methods that can be used to build your nav menu how you like it, such as getStoreCategories(), isCategoryActive(), getCurrenetChildCategories(), etc.
Alternatively, as mentioned by Peter, you can rewrite the Block class to change specific methods or include your own methods which are then accessible from the template file.

To override Mage_Catalog_Block_Navigation:
in app/etc/modules/Yourmodule_Catalog.xml:
<?xml version="1.0"?>
<config>
<modules>
<Yourmodule_Catalog>
<active>true</active>
<codePool>local</codePool>
<depends />
</Yourmodule_Catalog>
</modules>
</config>
in app/code/local/Yourmodule/Catalog/etc/config.xml:
<?xml version="1.0"?>
<config>
<modules>
<Yourmodule_Catalog>
<version>0.1.0</version>
</Yourmodule_Catalog>
</modules>
<global>
<blocks>
<catalog>
<rewrite>
<navigation>Yourmodule_Catalog_Block_Navigation</navigation>
</rewrite>
</catalog>
</blocks>
</global>
in app/code/local/Yourmodule/Catalog/Block/Navigation.php:
<?php
class Yourmodule_Catalog_Block_Navigation extends Mage_Catalog_Block_Navigation
{
.... the methods you want to override...
}
And that's it.

Related

How to override Magento model classes with as little copy-paste as possible?

I want to change a single line of code in a single method in e.g. the class Mage_Reports_Model_Resource_Product_Collection. The easiest way seems to be to copy the entire class file to app/code/local/..., but then I have replaced the original class, not overridden a method.
How can I create a new class that inherits from e.g. Mage_Reports_Model_Resource_Product_Collection and only override one method? And still tell Magento to use my new class instead of the original.
Here's the working code to rewrite product collection:
<global>
<models>
<reports_resource>
<rewrite>
<product_collection>Company_ModelName_Model_Resource_Product_Collection</product_collection>
</rewrite>
</reports_resource>
</models>
</global>
It should work for Mage::getResourceModel('reports/product_collection') call.
Yeah and I haven't included the <config> tag, I think you should already have even <global> one, so I felt it wasn't necessary.
Theoretically the rewriting of the model would be...
<config>
<global>
<models>
<reports>
<rewrite>
<resource_product_collection>Namespace_Extension_Model_Resource_Product_Collection</resource_product_collection>
</rewrite>
</reports>
</models>
</global>
</config>
I've never personally rewritten a resource model though, so I can't swear it will work. It will very much depend on how the collection is getting loaded.

Menu of categories "not included in navigation bar"

If I am right, in Magento the renderCategoriesMenuHtml() function helps in displaying the menu of "categories included in the navigation menu bar".
I'd like to modify the renderCategoriesMenuHtml() function to display the menu of "categories that are not included in the navigation menu bar".
In short, I need to display a menu of categories that have the attribute "Include in navigation menu" set to no in the admin panel.
Thanks in advance.
Magento has a facility for changing or adding to functionality of classes known as class overrides or class rewrites. The following example assumes a namespace of "Custom" and a module name of "Nav".
First, register a module:
<?xml version="1.0" encoding="UTF-8"?>
<!-- app/etc/modules/whatever.xml -->
<config>
<modules>
<Custom_Nav><!-- must match your namespace & module folder names -->
<active>true</active>
<codePool>local</codePool>
</Custom_Nav>
</modules>
</config>
Based on the above, the application will look for a configuration file for your module:
<?xml version="1.0" encoding="UTF-8"?>
<!-- app/code/local/Custom/Nav/etc/config.xml -->
<config>
<global>
<blocks>
<catalog>
<rewrite>
<navigation>Custom_Nav_Block_Rewrite_Navigation</navigation>
</rewrite>
</catalog>
</blocks>
</global>
</config>
What this does is to rewrite the class name in the block creation factory method. The catalog navigation block is added in catalog.xml layout update XML (<block type="catalog/navigation" .../>). The above xpath will cause the class name to map to Custom_Nav_Block_Rewrite_Navigation rather than the usual Mage_Catalog_Block_Navigation, and it is this class which will be instantiated.
The final step is to create the class definition, extending from the original class for the sake of maintainability and to obey DRY:
<?php
/* app/code/local/Custom/Nav/Block/Rewrite/Navigation.php */
class Custom_Nav_Block_Rewrite_Navigation extends Mage_Catalog_Block_Navigation
{
//custom method overrides & additions belong here
}
Clear the config & block_html caches and the changes should be visible. To verify, enable template path hints + block class names via the admin panel, or create a simple script in the site root:
<?php
/* test.php in Magento root folder */
ini_set('display_errors',true);
include 'app/Mage.php';
Mage::setIsDeveloperMode(true);
Mage::app();
var_dump(Mage::getConfig()->getBlockClassName('catalog/navigation'));
Point the browser to http://site.com/test.php and the output should show the rewritten class name.

How to scale image in cms Magento

When the admin adds an image to a cms page in Magento, and then resize the image:
then the image at the frontend retains its original size, but scaled.
Is there any solution to save the image in smaller size when the page is saved?
There's no way this will happen with any default magento. However, you could put together a module that will observe your cms page saved data. Take for instance this event:
cms_page_prepare_save
with parameters:
array(’page’ ⇒ $model, ‘request’ ⇒ $this→getRequest())
You can create the module starting with only 3 files:
/app/etc/Electricjesus_Cms.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Electricjesus_Cms>
<active>true</active>
<codePool>local</codePool>
</Electricjesus_Cms>
</modules>
</config>
/app/code/local/Electricjesus/Cms/etc/config.xml:
<?xml version="1.0"?>
<config>
<modules>
<Electricjesus_Cms>
<version>0.1.0</version>
</Electricjesus_Cms>
</modules>
<global>
<models>
<cms>
<class>Electricjesus_Cms_Model</class>
</cms>
</models>
<events>
<cms_page_prepare_save>
<observers>
<prepareSave>
<class>cms/observer</class>
<method>prepareSave</method>
</prepareSave>
</observers>
</cms_page_prepare_save>
</events>
</global>
</config>
/app/code/local/Electricjesus/Cms/Model/Observer.php:
<?php
class Electricjesus_Cms_Model_Observer {
function prepareSave ( $observer ) {
$request = $observer->getRequest();
$params = $request->getParams();
// scan the request and params for stuff related with the images..
// find out scaling and pass into a good resizer like TimThumb or
// Zend_Filter_ImageSize etc.
}
}
While the above answer is not complete, this is a good place to start. I'll try and develop a complete solution whenever I have more time on it.
Alternative method:
Since I mentioned TimThumb above, you can also deploy that at your magento root and start adding your images via HTML editor instead of the usual WYSIWYG editor. If installing thumb.php on your website root directory, you can use it like so:
<img src="/thumb.php?src=images/image.jpg&w=100&h=50" alt="Hey" />
Good luck!

Make a custom observer fire before an existing Magento observer

Is there a way to make an observer that you have custom made have higher priority than the Magento one that fires on the same event. My problem is I am modifying the output of the Welcome block but the PageCache for enterprise fires on the same corecore_block_abstract_to_html_after event.
I tried putting this in my config but it didn't work like cron jobs do.
<core_block_abstract_to_html_after>
<observers>
<modify_welcome>
<type>singleton</type>
<class>groupname_page/observer</class>
<method>changeWelcomeText</method>
</modify_welcome>
<enterprise_pagecache>
<class>enterprise_pagecache/observer</class>
<method>renderBlockPlaceholder</method>
</enterprise_pagecache>
</observers>
</core_block_abstract_to_html_after>
/app/etc/modules/Groupname_Page.xml
<config>
<modules>
<Groupname_Page>
<active>true</active>
<codePool>local</codePool>
<depends>
<!-- Your dependencies go here -->
</depends>
</Groupname_Page>
<Enterprise_PageCache>
<depends>
<Groupname_Page />
</depends>
</Enterprise_PageCache>
</modules>
</config>
There is no way to control order of observers.
If you take a look on the Mage_Core_Model_App::dispatchEvent() method, you'll see how Magento get all observers for a given event from config.xml files and fires them one by one.
Rewriting the Welcome block will help you.
another option is to disable the enterprise cache observer and in your own observer run the method that would have been executed by the disabled observer
In your module's config.xml:
<core_block_abstract_to_html_after>
<observers>
<modify_welcome>
<type>singleton</type>
<class>groupname_page/observer</class>
<method>changeWelcomeText</method>
</modify_welcome>
<enterprise_pagecache>
<type>disabled</type>
</enterprise_pagecache>
</observers>
</core_block_abstract_to_html_after>
And in your Observer.php:
public function changeWelcomeText(Varien_Event_Observer $observer)
{
//do the stuff you want your observer to do first
//and after it's done, call the Enterprise observer's method
Mage::getSingleton('enterprise_pagecache/observer')->renderBlockPlaceholder($observer);
}
HTH

Override code-behind for a block in Magento

I am writing a module to extend the Core/Catalog/Product/View/Media.php class so I can expose new methods in my template. I followed a number of guides online, including Alan Storms excellent series, but have had little success. ( http://alanstorm.com/magento_config )
I posted my code on Github: https://github.com/razialx/Magento-Overwrite-Block
I am not getting any errors in the logs, it just isn't loading my class. Very perplexed.
One thought I had was that I may only be able to rewrite classes that are explicitly defined. I know the Mage_Catalog_Block_Product_View_Media class is never defined in a config file, though I assume it is referenced by the layout xml file catalog.xml
<block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media.phtml"/>
Your config.xml is slightly off. Give the following a try.
<config>
<modules>
<Test_Catalog>
<version>1.0.0.0.0</version>
</Test_Catalog>
</modules>
<global>
<blocks>
<catalog>
<rewrite>
<product_view_media>Test_Catalog_Block_Product_View_Media</product_view_media>
</rewrite>
</catalog>
</blocks>
</global>
</config>
Your <blocks> node needs to be enclosed in a <global> node.

Resources