Working with CS Cart: Template Suggestions

It has been a little while since I posted my first “Working with CS Cart” entry. The previous post showed you how to change the footer of an existing CS Cart skin, something useful but not really complex like for example selecting different page templates depending on the page or controller you are viewing.

One of my clients had some very varying templates for different sections of the cart. If you are familiar with Drupal you know that the Drupal system looks automatically for specific template names depending on the currently requested URL based on specific criteria. Essentially this is exactly what I needed CS Cart to do, however I had to include a little hack in order to implement such a mechanism.

Suggestion Criteria

Usually the frame of a website design stays the same which would logically reside in the index.tpl, however the display of the actual content might be different for several sections/pages in the cart. For this we will have to modify the main.tpl file. Here you will see the default way of displaying the “frame” for content in CS Cart but what if we had a design that has a different structure for the home page and inner pages? Further more, what if one category has a different structure than the rest? Well now we are getting closer to build up our criteria. To make things short let me sum up the criteria I have setup for my client’s project:

  • Each controller (index, pages, products, categories etc.) may have a different structure
  • One or more pages may have a different structure
  • One or more categories may have a different structure
  • One or more products may have a different structure

Having those criteria defined gives us a great deal of flexibility to basically be able to control the content’s “frame” in any situation.

Smarty Modifier: Looking for a template

Unfortunately CS Cart nor Smarty have any built-in functionality to check whether or not a template exists from within a template, so I had to go in and quickly implement such a functionality. In order to keep things simple and not change any core code I had to think of a way to implement template suggestions from within a .tpl file which would require extending Smarty. Ideally an implementation of the required functionality would look something like this

{if $page_template|valid_template}
  {include file="`$page_template`"}
{else}
  {include file="default.tpl"}
{/if}

Looking through the Smarty documentation you will learn that this function is a Smarty modifier but in fact we are not modifying any values only running a quick check on the existence  of a template file. So we will simply create a new modifier for Smarty in order to do the check. Go to your CS Cart installation and create a file called modifier.valid_template.php in the /lib/templater/plugins open it up and copy and paste the following code into it

<?php
/**
 * Checks the presense of a template.
 * Usage example:
 * {if $page.include_file|valid_template}{include file=$page.include_file}{/if}
 */
 $GLOBALS['smarty'] = $smarty;
 function smarty_modifier_valid_template($template_name)
 {
   $smarty = $GLOBALS['smarty'];
   return($smarty->template_exists($template_name));
 }
?>

We are simply creating a wrapper for the Smarty template_exists function. Now whenever we use this modifier we can check if a template path is actually an existing template.

Putting it together

Now we have our function to check if a template exists and our criteria. It is time to put it all to work. First of all we will create the implementation of our first criteria “Each controller may have a different structure”. For this back up the main.tpl file before editing it. Once this is done simply rename the backup to “default.tpl” so that we have a fallback template in case no specific templates were found for any of the controllers. Now we will replace the content of main.tpl with this

{capture assign='page_template}main/page_{$controller}.tpl{/capture}
{if $page_template|valid_template}
  {include file="`$page_template`"}
{else}
  {include file="main/default.tpl"}
{/if}

It is as simple as these 6 lines to have custom layout for each of the controllers. Note that this snippet will look for the templates in the directory “main” which will have to be created manually and all page_<controller_name>.tpl files will reside in there.

Now you can create for example a page_index.tpl in order to differentiate the structure of the main.tpl for the homepage from the rest of the site. For any other controller simply create a file called ‘page_<controller_name>.tpl’ in your skin. If you are not sure about what controller is used for the section you want to change, simply enable debugging from the administration, navigate to the page you want to have changed and look up the “$controller” value in the debug window.

This change will only comply to our first criteria; we need more. For this we will need to create some more files and folders. I will document here how to implement suggestions for pages only but the same method can be applied to categories and products too. For better maintainability we create a new folder called “pages” in the “main” folder where all the page specific templates and a default.tpl fallback will reside. Also create a file called “page_pages.tpl” in the “main” folder. Here we will add the following code

{capture assign='page_template}main/pages/page_pages_{$page.page_id}.tpl{/capture}
{if $page_template|valid_template}
  {include file="`$page_template`"}
{else}
  {include file="main/pages/default.tpl"}
{/if}

Now we have setup a mechanism for CS Cart to look for main/pages/page_pages_<page_id>.tpl for page specific structures. Simply create folders and files for the products and categories controllers to do the same and you’re good to go.

Simple, ain’t it?