Adding Module pages to your Magento Sitemap

In earlier Magento versions it wasn’t possible to add additionals entries to your Magento Sitemap without overriding or extending Mage_Sitemap_Model_Sitemap.

Luckily, with the introduction of two events, sitemap_categories_generating_before & sitemap_products_generating_before, this became possible and therefore way simpler, too. Unless you don’t have to extend Mage_Sitemap_Model_Sitemap anyway, for example because you want to add images to your sitemap, you rather want to use these events.

Good to know…

Which event you want to choose depends on the changefreq and priority values you’d prefer for your additional page entries. You can look them up or change them in your Magento Sitemap configurations under System > Configuration > Catalog > Google Sitemap.

Even tho Magento is adding entries for category-, product- and CMS-pages, it does not fire an event for the latter one. Hence you have to choose between your category & product sitemap values.

In our example we prefer the product sitemap values. Therefore we go with the event sitemap_products_generating_before.

To it then!

Lets assume our custom module creates dynamic “News” pages and stores the page information, including the page URLs, within our model database table.

So first we add an event listener to the <global> tag in our module’s config.xml:

    <events>
        <sitemap_products_generating_before>
            <observers>
                <{your_unique_event_observer_name}>
                    <class>{Brand}_{Module}_Model_Observer</class>
                    <method>addPagesToSitemap</method>
                </{your_unique_event_observer_name}>
            </observers>
        </sitemap_products_generating_before>
    </events>

Then, in our module’s Observer, we let the method addPagesToSitemap add extra items to the product collection:

<?php
class {Brand}_{Module}_Model_Observer
{   
    function addPagesToSitemap(Varien_Event_Observer $observer){

        $sitemapItems = $observer->getEvent()->getCollection()->getItems();

        // Get your module's page collection including their urls
        // Adjust the following lines to your needs
        $collection = Mage::getModel('{brand}_{module}/pages')->getCollection()
            ->addFieldToSelect(array('page_id','url'))
            ->addFieldToFilter('display', 1);
        // My module stores the page path separately,
        // you might don't need this:
        $modulePagePath = Mage::helper('{my-modules-helper}')->getNewsPath();

        foreach($collection as $_item){
            $varienObject = new Varien_Object();
            // We don't want to override 
            // any existing product/category items
            $uniqueId = '{module}'.$_item->getPageId();         
            $varienObject->setId($uniqueId);

            // You might want to adjust this if your item
            // stores the complete url. Don't add the base url tho,
            // Mage_Sitemap_Model_Sitemap::generateXml adds it
            $varienObject->setUrl($modulePagePath . DS . $_item->getUrl());

            $sitemapItems[$uniqueId] = $varienObject;
        }
        $observer->getEvent()->getCollection()->setItems($sitemapItems);

        return $this;
    }
}

Well and that’s it! You can test it by manually generating your Magento Sitemap under Catalog > Google Sitemap.


(Tested in Magento 1.9.2.2)

Displaying the child thumbnail instead of the configurable’s

Situation

Earlier in October we noticed that Magento’s “native” cart item renderer is not displaying the child thumbnail, despite our proper store configuration:

screenshot_checkout_shoppingcart

It kept showing the parent’s product thumbnail instead of displaying the child thumbnail.

Problem

I took a look at method getProductThumbnail:

 /**
 * Get product thumbnail image
 *
 * @return Mage_Catalog_Model_Product_Image
 */
 public function getProductThumbnail()
 {
   $product = $this->getChildProduct();
   if (!$product || !$product->getData('thumbnail')
   || ($product->getData('thumbnail') == 'no_selection')
   || (Mage::getStoreConfig(self::CONFIGURABLE_PRODUCT_IMAGE) == self::USE_PARENT_IMAGE)) {
     $product = $this->getProduct();
   }
   return $this->helper('catalog/image')->init($product, 'thumbnail');
 }

As you can see in line 75, it’s supposed to differentiate, however, it does not. This is because we need to check whether the config value and const value are identical (===) rather than just equal (==).

Solution

We can easily fix this by adding a new block that will extend Mage_Checkout_Block_Cart_Item_Renderer_Configurable. Montareno_Cart is one of our custom modules we were already using for cart modifications. If you don’t have such a custom module yet, just create one. This way we can overwrite method getProductThumbnail:

class Montareno_Cart_Block_Renderer_Configurable extends Mage_Checkout_Block_Cart_Item_Renderer_Configurable
 /**
 * Get product thumbnail image
 * FIX: comparison for identity rather than equality
 *
 * @return Mage_Catalog_Model_Product_Image
 */
 public function getProductThumbnail()
 {
     $product = $this->getChildProduct();
     if (!$product || !$product->getData('thumbnail')
     || ($product->getData('thumbnail') == 'no_selection')
     || (Mage::getStoreConfig(parent::CONFIGURABLE_PRODUCT_IMAGE) === parent::USE_PARENT_IMAGE)) {
       $product = $this->getProduct();
   }
   return $this->helper('catalog/image')->init($product, 'thumbnail');
 }
 
}

In order to make Magento actually use our modified renderer we need to replace checkout/cart_item_renderer_configurable in all cart layout files. Just take a look in your checkout.xml or the layout file of any other cart module you’re might using. This is an example of how our modifying module’s xml could look like:

    <default>
        <reference name="cart_sidebar">
        	<action method="addItemRender"><type>configurable</type><block>montareno_cart/renderer_configurable</block><template>checkout/cart/sidebar/default.phtml</template></action>
        </reference>
    </default>

    <checkout_cart_index>
        <reference name="checkout.cart">
        	<action method="addItemRender"><type>configurable</type><block>montareno_cart/renderer_configurable</block><template>checkout/cart/item/default.phtml</template></action>
        </reference>
    </checkout_cart_index>

    <checkout_onepage_review translate="label">
        <reference name="root">
            <action method="addItemRender"><type>configurable</type><block>montareno_cart/renderer_configurable</block><template>checkout/onepage/review/item.phtml</template></action>
        </reference>
    </checkout_onepage_review>

If you are offering multishipping in your store, you have to adjust these layout tags, too.

(At the time of writing we were working on a Magento CE 1.9.2.2 install on Ubuntu 12.04 / PHP 5.3.10)