Blogs
Ok, so in the last post I talked about JSP Include Buffer.
That post talked about how you'd override JSPs from Liferay's core in a maintainable way. Now I'd like to introduce you to a Liferay Theme feature, new in 6.1, that will grant you much more power when it comes to manipulating portal views from your theme using that plus this additional feature.
From your theme you can now include templates (following the same path maning as they are found in the core) in your themes which override those of the core, provided they have a template extension matching that of your themes. They will override the default view of the portatl but only where and when your theme is applied.
Now think about this! When you apply a theme onto any page of your portal, you can alter the view of any portlet on just those pages!
Let me illustrate with an example. I'll use the exact same example that was intriduced in the previous post just so it easier to follow along.
Assuming for the moment that our theme is a Freemarker theme, we add the following template to our theme:
<SDK_ROOT>/themes/my-theme/docroot/_diffs/templates/html/taglib/ui/page_iterator/start.ftl
In this template we place the following code (using the buffer pattern):
<#assign liferay_util = PortalJspTagLibs["/WEB-INF/tld/liferay-util.tld"] /> <@liferay_util["buffer"] var="html"> <@liferay_util["include"] page="/html/taglib/ui/page_iterator/start.jsp" strict=true useCustomPage=false /> </@> <div style="border: 4px solid red; padding: 4px;"> ${html} </div>
So, you should note two things.
First, unlike in the previous post I don't have to use the .portal encoded name for the jsp because it's still where it started, the portal didn't relocate it since my override is in the theme (it only does that when using hook plugins).
Second, the attribute strict=true. As I mentioned before, but will again, this is to prevent the portal from doing a lookup for overrides when making the call to the underlying JSP (this is to avoid infinite recursion since we're in an override right now).
Ok, I can noew enhance or alter this view no problem without having to reproduce the whole of the original logic and I'm doing it from my theme no less!
What more could you ask for?
Well it turns out there IS more that could be asked and since it was asked for, we made it reality (that's what we do at Liferay, we make wishes come true).
The question was "Could you override a JSP, but only for a particular portlet?"
Since overriding a blog JSP only in blogs doesn't really make sense, nor does overriding a blog JSP only for message boards, the main case here is with taglib JSPs. Liferay has a vast number of tags and their view logic are largely implemented with JSPs.
So, the answer to that is, "Yes, now you can override a JSP in your theme for only specific portlets!"
How do you do it?
Simple! All you need to do is add the portlet Id of the target portlet, between the file name of the original JSP and the extension of the template like so:
<SDK_ROOT>/themes/my-theme/docroot/_diffs/templates/html/taglib/ui/page_iterator/start.19.ftl
Using a similar template containing (note the green border instead):
<#assign liferay_util = PortalJspTagLibs["/WEB-INF/tld/liferay-util.tld"] /> <@liferay_util["buffer"] var="html"> <@liferay_util["include"] page="/html/taglib/ui/page_iterator/start.jsp" strict=true useCustomPage=false /> </@> <div style="border: 4px solid green; padding: 4px;"> ${html} </div>
Now, you'll note that we have two new tempalate files in our theme:
_diffs/templates/html/taglib/ui/page_iterator/start.ftl _diffs/templates/html/taglib/ui/page_iterator/start.19.ftl
These two files do not conflict, and the precendence will be:
1. portlet specific template
2. non portlet specific template
3. (no file) default
If your template is trying to override the JSP for a portlet that is in a plugin, make sure to use the fully qualified portletId (which is encoded using the pattern portletid_WAR_plugincontextname).
Now if you place two portlets on the page while this theme is in effect on it, and each of those portlets use the liferay-util:page-iterator tag, and one of those portlets is the Message Boards Portlet (19) then you should see both red and green boxes around those parts of the page.
Oh, and remember that you CAN do the same from a Velocity theme:
_diffs/templates/html/taglib/ui/page_iterator/start.vm _diffs/templates/html/taglib/ui/page_iterator/start.19.vm
The template (using the buffer pattern) would look more like this:
#set ($bufferTagClass = $portal.class.forName("com.liferay.taglib.util.BufferTag"))
#set ($includeTagClass = $portal.class.forName("com.liferay.taglib.util.IncludeTag"))
#set ($bufferTag = $bufferTagClass.newInstance())
#set ($V = $bufferTag.setPageContext($pageContext))
#set ($V = $bufferTag.setParent(null))
#set ($V = $bufferTag.setVar('html'))
#if ($bufferTag.doStartTag() == 2)
#set ($V = $bufferTag.setBodyContent($pageContext.pushBody()))
#set ($V = $bufferTag.doInitBody())
#set ($includeTag = $includeTagClass.newInstance())
#set ($V = $includeTag.setPageContext($pageContext))
#set ($V = $includeTag.setPage('/html/taglib/ui/page_iterator/start.jsp'))
#set ($V = $includeTag.setStrict(true))
#set ($V = $includeTag.setUseCustomPage(false))
#set ($V = $includeTag.runTag())
#set ($V = $bufferTag.doAfterBody())
#set ($V = $pageContext.popBody())
#set ($V = $bufferTag.doEndTag())
#end
<div style="border: 4px solid red; padding: 4px;">
${pageContext.findAttribute('html')}
</div>
Now, I hope you find more uses for these features that colourful boxes. Good luck!

