View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFDEV:Zend Proposal Zone Template}

{composition-setup}

{zone-data:component-name}
Zend_Controller_Plugin
{zone-data}

{zone-data:proposer-list}
[~ixti]
{zone-data}

{zone-data:revision}
1.1 - 14 January 2008: Initial release of proposal
1.2 - 21 May 2008: Ready for review
{zone-data}

{zone-data:overview}
This plugin will help to use [web templates|http://en.wikipedia.org/wiki/Web_template].
{zone-data}

{zone-data:references}
* [Web Template|http://en.wikipedia.org/wiki/Web_template]
{zone-data}

{zone-data:requirements}{zone-data}

{zone-data:dependencies}
* Zend_Controller_Plugin_Abstract
{zone-data}

{zone-data:operation}
This plugin can use simple or complex template name format.
* Simple format is used when you don't need different representations within single template.
* Complex format used when you want to make, for example, different templates with one design. For example it can be used to create different templates for admin panel and other part of web site but in one common design.

The use of Plugin very simple. All you have to do is - set path where your templates are stored (when initaiting new instance of object), then set template name's format and set default template name.

If you want to use Smarty with this plugin, all you have to do is extend Zend_View and setView($zend_view_smarty) where $zend_view_smarty is initiated object of Zend_View_Smarty, for more details on extending Zend_View see [Zend Framework manual|http://framework.zend.com/manual/en/zend.view.scripts.html#zend.view.scripts.templates].

This plugin assigns all segments of $_body form Zend_Controller_Response to view's variables using their names. So if you'll appendBody() in your controller, it will be assigned to $this->default in view script.
{zone-data}

{zone-data:milestones}
! - TODO, ? - Idea
* !: Add availability to fall back to default template if specified template wasn't found.
* ?: [DONE] Rename plugin to Zend_Controller_Plugin_Template
{zone-data}

{zone-data:class-list}
* Zend_Controller_Plugin_Template
{zone-data}

{zone-data:use-cases}
||UC-01 (Simple)||
{deck:id=UC-01}
{card:label=Bootstrap}
h5. File: project/html/index.php
{code:php}
<?php

define('BASE_PATH', realpath('project'));
define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'application');

require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

$plugin = new Zend_Controller_Plugin_Template(APP_PATH
. DIRECTORY_SEPARATOR
. 'templates');

$ctrl = Dzen_Controller_Front::getInstance()
->setControllerDirectory(APP_PATH . DIRECTORY_SEPARATOR . 'controllers')
->registerPlugin($plugin)
->throwExceptions(true)
->dispatch();
{code}
{card}
{card:label=IndexController}
h5. File: project/application/controllers/IndexController.php
{code:php}
<?php

class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
// Template: default.phtml
}

public function fooAction()
{
$this->getResponse()->insert(':template', 'printer');
// Template: printer.phtml
}
}
{code}
{card}
{card:label=Template "default"}
h5. File: project/application/templates/default.phtml
{code:php}
<html>
<head>
<title>BookshelfProject</title>
</head>
<body>
<div id="header">
<img src="images/logo.png" />
</div>
<div id="body">
<?php $this->default; ?>
</div>
<div id="footer">
Copyrights Bookworm 2008.
</div>
</body>
</html>
{code}
{card}
{card:label=Template "printer"}
h5. File: project/application/templates/printer.phtml
{code:php}
<html>
<head>
<title>BookshelfProject</title>
</head>
<body>
<div id="header">
Printed from BookshelfProject on <?php echo date('Y/m/d'); ?>
</div>
<div id="body">
<?php $this->default; ?>
</div>
<div id="footer">
Copyrights Bookworm 2008.
</div>
</body>
</html>
{code}
{card}
{deck}
||UC-02 (Complex)||
{deck:id=UC-02}
{card:label=Bootstrap}
h5. File: project/html/index.php
{code:php}
<?php

define('BASE_PATH', realpath('project'));
define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'application');

require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

$plugin = new Zend_Controller_Plugin_Template(APP_PATH
. DIRECTORY_SEPARATOR
. 'templates');
$plugin ->setScriptNameFormat('{name0}/{name1}.phtml');
$plugin ->setDefaultTemplateName('default|default');

$ctrl = Dzen_Controller_Front::getInstance()
->setControllerDirectory(APP_PATH . DIRECTORY_SEPARATOR . 'controllers')
->registerPlugin($plugin)
->throwExceptions(true)
->dispatch();
{code}
{card}
{card:label=IndexController}
h5. File: project/application/controllers/IndexController.php
{code:php}
<?php

class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
// Template: default/default.phtml
}

public function fooAction()
{
$this->getResponse()->insert(':template', 'reverted');
// Template: reverted/default.phtml
}
}
{code}
{card}
{card:label=AdminController}
h5. File: project/application/controllers/AdminController.php
{code:php}
<?php

class AdminController extends Zend_Controller_Action
{
public function init()
{
$this->getResponse()->insert(':template', '|admin');
}

public function indexAction()
{
// Template: default/admin.phtml
}

public function fooAction()
{
$template = 'reverted' . $this->getResponse()->getBody(':template');
$this->getResponse()->insert(':template', $template);
// Template: reverted/admin.phtml
}
}
{code}
{card}
{deck}
{zone-data}

{zone-data:skeletons}
{code:php}
class Zend_Controller_Plugin_Template extends Zend_Controller_Plugin_Abstract
{
/**
* Path where templates stored
*
* @var string
*/
protected $_templateBasePath;

/**
* Name of default template which will be used if special segment ':template'
* was not present in Response object.
*
* If you're using complex script name format {@link $_scriptNameFormat}
* you'll have to use complex default template name and devide parts with
* pipe '|'.
*
* @see $_scriptNameFormat
* @var string
*/
protected $_defaultTemplateName = 'default';

/**
* Format of script name composing. {name} will be replaced with template
* name. So format can be '{name}/core.phtml' for complex templates.
*
* Complex script name format.
* {name} also can be as {nameN}, where N=0, N+1. This might be useful for
* more complex design templates. For example, you have two designs:
* 'PinkFloyd' and 'VelvetUnderground'. And each of them has two templates:
* 'admin' and 'default'. So you can specify $_scriptNameFormat as
* '{name0}/{name1}.phtml'. But you'll also need to
* {@link setDefaultTemplateName()} to 'PinkFloyd|default' if you want to use
* 'PinkFloyd' design as default, and 'default' template as default.
*
* @see $_defaultTemplateName
* @var string
*/
protected $_scriptNameFormat = '{name}.phtml';

/**
* Instance of Zend_View.
*
* @var object
*/
protected $_view;

/**
* Class constructor. Set path to where templates stored.
*
* @param string $pathToTemplates
*/
public function __construct($pathToTemplates)
{
$this->_templateBasePath = (string) $pathToTemplates;
if (!file_exists($this->_templateBasePath) || !is_dir($this->_templateBasePath)) {
throw new Zend_Controller_Exception('Missing templates directory.');
}
}

/**
* Set default template's name.
*
* @see $_defaultTemplateName
* @param string $name
* @return Zend_Controller_Plugin_ResponsedView
*/
public function setDefaultTemplateName($name)
{
$this->_defaultTemplateName = (string) $name;
return $this;
}

/**
* Retrieve default template's name.
*
* @see $_defaultTemplateName
* @return string
*/
public function getDefaultTemplateName()
{
return $this->_defaultTemplateName;
}

/**
* Set format of script name composing.
*
* @see $_scriptNameFormat
* @param string $format
* @return Zend_Controller_Plugin_ResponsedView
*/
public function setScriptNameFormat($format)
{
$this->_scriptNameFormat = (string) $format;
return $this;
}

/**
* Retrieve template script name.
*
* @param string $templateName
* @return string
*/
public function getScriptName($templateName = null)
{
$template_parts = explode('|', $this->getDefaultTemplateName());
foreach (explode('|', (string) $templateName) as $key => $val) {
if (null != $val) {
$template_parts[$key] = $val;
}
}

$script_name = str_replace('{name}', $template_parts[0], $this->_scriptNameFormat);
foreach ($template_parts as $id => $name) {
$script_name = str_replace('{name' . $id . '}', $name, $script_name);
}
return $script_name;
}

/**
* Set initiated view object (Subclass of {@link Zend_View}.
*
* @param object|null $view
* @return Zend_Controller_Plugin_ResponsedView
*/
public function setView($view = null)
{
if (null === $view) {
$view = new Zend_View();
}

if (!($view instanceof Zend_View)) {
throw new Zend_Controller_Exception('Invalid View object.');
}

$this->_view = $view;

return $this;
}

/**
* Get initiated view object.
*
* @see $_view
* @see setView()
* @return object
*/
public function getView()
{
if (!isset($this->_view)) {
$this->setView();
}

return $this->_view;
}

public function dispatchLoopShutdown()
{
$response = $this->getResponse();
$template = $this->getScriptName($response->getBody(':template'));
$response ->clearBody(':template');

$view = $this->getView();
$view ->setScriptPath($this->_templateBasePath);

foreach ($response->getBody(true) as $segment => $content) {
$view->assign($segment, $content);
}

$response ->clearBody();
$response ->setBody($view->render($template));
}
}
{code}
{zone-data}

{zone-template-instance}]]></ac:plain-text-body></ac:macro>