The Mojavi 3 Book/Tutorials/Decorator Profiling

Prerequisites

edit

Before reading this tutorial, one should introduce themself to the ((Global Templating - The Decorator Pattern Tutorial)(Tutorials)). Before reading this tutorial, one should introduce themself to the ((http://wiki.mojavi.org:81/159.html)(Global Templating Tutorial)).


++ Profiling

++ Profiling


Decorator profiling is a simple idea: Separate your different arrangements of Decorator template, and populators, into scripts that make those calls automatically. Decorator profiling is a simple idea: Separate your different arrangements of Decorator template, and populators, into scripts that make those calls automatically. To begin, let us take a look, evolutionarily, how one might separate the different display modes, or profiles, from the actual views.

++ Stage 1: Hardcode

In this example, a simple example of direct decoration of templates, does it's job. But it fails to provide a simple means for replicating this pattern of decorator/slot population in other Views without a copy/paste. // 1 ka ans kya h?

Example 1: Hardcoded decorator information

edit
class 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');

}

}

++ Step 2: Include

The second stage of abstraction is to create a separate script (a separate php file) and directly include it into your Views - eliminating copied code.

Example 2: Included decorator information

edit
class IndexSuccessView extends PHPView
{

public function execute ()
{

// set our template
$this->setTemplate('IndexSuccess.php');

// set the title
$this->setAttribute('title', 'Default Action');

//get our profile
require(MO_TEMPLATE_DIR . '/profiles/Default.profile.php');

}

}

As you can see, all the decorator calls have been removed, and an include place in their stead. The include file is below:

Example Profile: Default.profile.php

edit
<?php

//setup our decorator template
$this->setDecoratorDirectory(MO_TEMPLATE_DIR);
$this->setDecoratorTemplate('myGlobalTemplate.php');

//setup our slots
$this->setSlot('menu', 'Content', 'PopulateMenu');
$this->setSlot('css', 'Content', 'PopulateCss');

?>

++ Step 3: =setProfile()=

The last stage, or what I would propose, is to create a simple method that loads our profiles for us, and perhaps provides with a few other utility functions such as

hasProfile()
loadProfile() or setProfile()

Example 3: Included decorator information

edit
class IndexSuccessView extends PHPView
{

public function execute ()
{

// set our template
$this->setTemplate('IndexSuccess.php');

// set the title
$this->setAttribute('title', 'Default Action');

//get our profile
$this->setProfile('Default');

}

}

++ The =setProfile()= Method

Don't be deceived, the =setProfile()= method and the include method are, in the end, equivalent. One requires one more function call than the other, but I believe that the simplicity of the =setProfile()= makes it superior, along with providing automatic detection of profiles, and automatically searching in the proper directories (The directories that would store profiles, I suppose, would be MO_TEMPLATE_DIR/templates/profiles/).

Example 4: The setProfile() method

edit
Note: This function is untested and may contain errors.


public function setProfile($name, $module = null)
{

//is the module null?
if($module === null)
{

//set the directory to the global profile directory
$dir = MO_TEMPLATE_DIR . '/profiles';

}
else
{

//set the directory to the module profile directory
$dir = MO_MODULE_DIR . '/' . $module . '/templates/profiles';

}

//setup the profile path
$profile = $dir . '/' . $name . '.profile.php';

//can we read it?
if(is_readable($profile))
{

//get the file
require($profile);

//set the profile up
$this->profile = $name;
return true;

}
else
{

//profile failed, set null
$this->profile = null;
return false;

}

}

The member variable =$profile= will allow for a check to be run during View's preRenderCheck()