Previously I wrote about an annoying little bug in Magento’s widget engine that I just had to figure out and fix. Today I want to discuss a new feature that we have created and added to the widget engine to fill in for a sadly missing feature in Magento. The ability to add widgets to specific CMS pages.
This may come as a surprise, but out-of-the box Magento can only apply widgets to CMS pages in two contexts: The home page and all CMS pages! This always seemed strange to me, until I started learning how widgets work. Then it made some sense, but not enough to not fix it.
Everything you see when a page is rendered in Magento is likely defined by an XML language we call Layout. Using Layout, we specify blocks of content, how they should be displayed and when they should be displayed. Typically, this Layout is loaded from many XML files on disk and merged together to get the final presentation. However, Magento also has the ability to define Layout updates in the database. You may have seen this before on the CMS Page editor, where there is a text area box for layout update XML:
Magento widgets work by generating Layout XML updates for you and storing them in the database. So, if we configure the following layout update in the Widget editor:
It will produce the following Layout Update in the database:
Notice the field “Handle.” That is the Layout handle which is how we determine which pieces of Layout to process when rendering a page. [cms_index_index] is a special handle that represents viewing the home page. If we go to the home page in our trusty debugger, we can view all the handles that are loaded. Notice entry number 4. It matches the handle we found in our database layout update. That means the Layout XML for our widget will be loaded and processed on the home page.
So, for each of those handles, the corresponding Layout will be loaded. Easy enough. Let’s compare the Layout Handles for viewing two separate CMS pages: ‘Our Mission’ and ‘News For You.’
Notice, they are exactly the same. There is no way to differentiate these two pages based on Layout handles… Dang! So, for us to be able to specify a specific page (or set of pages) for Widget Layout Updates, we will need to have a handle that uniquely identifies each page that shows up in the handle list. To do this, we will need to inject a new handle into the system before Layout is loaded.
To accomplish this, I created a new Event Observer that would observe when rendering a CMS page. Event Observers are a powerful way of adding your own functionality to the Magento system without having to modify any core files. It is the preferred way to ‘get things done’ when developing on the platform. The configuration XML for this event is as follows.
The actual observer code is simple enough. I grab the CMS page object and the actual controller from the observer and add a new handle that includes the ID of the page that will be rendered. The code listing for this can be seen below:
Having done this, why don’t we check our layout handles for those two pages we tested before. If we look at this screenshot below we will see that they now have a distinguishing handle for each one!
We are half way there. Now all we need to do is extend the widget layout update designer to let us pick specific CMS pages. That, however, will have to wait until our next post on June 17th, 2015. And remember, all of the code for this post and the next will be available on our GitHub page.