The Mojavi 3 Book/Tutorials/Global Templating - The Decorator Pattern
Ever since Mojavi 3 was released earlier this year, people have been looking to create a flexible global templating solution. From using post filters to page controllers, people have been looking for a way to create simple and manageable global templates that will allow for a great deal of flexibility without compromising the need for larges amount of duplicated code.
++ Enter Decorator
The Decorator design pattern, like every other pattern, is nothing more than a way to talk about a reusable concept, or pattern, that a programmer might encounter while coding applications. The Decorator pattern's strength is it's ability to serve as a wrapper for that particular object, while leaving objects like it intact.
The Decorator pattern has been implemented in the =View= class, providing a number of new methods:
public function setSlot ($attributeName, $moduleName, $actionName)
public function setDecoratorDirectory ($directory)
public function isDecorator ()
protected function & getSlots ()
public function getDecoratorTemplate ()
public function getDecoratorDirectory ()
protected function & decorate (&$content)
Now a brief explanation of what each of these do:
- =setSlot= - Creates a slot entry based upon the results of a specially controlled controller->forward()
- =setDecoratorTemplate= - Sets the template that you're going to use for your decorator. This method also automatically turns the decorator switch to =true=
- =isDecorator= - returns true is setDecoratorTemplate has been called, otherwise false.
- =getSlots= - Returns an array of the slots.
- =getDecoratorTemplate= - Returns the decorator template.
- =getDecoratorDirectory= - Returns the decorator directory.
- =decorate= - A method that must be implemented in derivate Views.
Note: these functions are in View, so all derivates of View (i.e. PHPView) have access.
++ Insert Here: Slots
Slots is a new name for an old concept. More or less, slots serve as placeholders that can be populated by the results of a =$controller->forward($mod, $act)= call. And, as you can see, the =setSlot= method takes three parameters:
public function setSlot ($attributeName, $moduleName, $actionName)
The first parameter, $attributeName, serves as the name of the slot. The next two parameters will be used to get the results of that Action, put it in a buffer, and place it into the internal =$slots= member variable.
++ Let's Decorate!
The usage pattern of Views changes little with the implementation of the decorator pattern at the module level (though secondary View authors, i.e. SmartyView et al., do have a few things to play with).
Now let's look at what you're going to need to do implement the new, and NEW decorator features of Mojavi.
+++ Creating a Global Template
First off, we're going to need a great big christma..ehh..template to decorate. While I won't get into breaking down and factoring our global template, keep in mind that this is not the only way to do this.
Example 2: The Christmas Tree (myGlobalTemplate.php)
editSide note: Sometimes you'll have issues with that <?xml [....] ?> declaration, an easy
workaround is to disable short tags in your php.ini file, or to use ini_set() to disable
it.
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
<title><?php echo $template['title']; ?></title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
<style type="text/css" media="all">
<?php echo $template['css']; ?>
</style>
</head>
<body>
<div id="menu">
<?php echo $template['menu']; ?>
</div>
<div id="main">
<?php echo $template['content']; ?>
</div>
</body>
</html>
+++ Putting the ornaments up So now that we have our decorator template, we need to decorate it. The decorating process is fairly simple, and consists of the following simple steps:
- Setting the decorator directory using =setDecoratorDirectory()= (Optional)
- Setting the decorator template using =setDecoratorTemplate()=
- Setting slots =setSlot()=
For example,
Example 3: In the View (IndexSuccessView.class.php)
editclass IndexSuccessView extends PHPView
{
public function execute ()
{
// set our template
$this->setTemplate('IndexSuccess.php');
//setup our decorator template
$this->setDecoratorDirectory(MO_TEMPLATE_DIR);
$this->setDecoratorTemplate('myGlobalTemplate.php');
//setup our slots
//(SlotName, Module, Action)
$this->setSlot('menu', 'Content', 'PopulateMenu');
$this->setSlot('css', 'Content', 'PopulateCss');
// set the title
$this->setAttribute('title', 'Default Action');
}
}
Now you might be wondering where the =content= slot is being populated. Well, =content= is a reserved slot that is automatically populated with the output of the originally requested Action/View pair. /To be Continued..../