sintonia/airtime_mvc/library/propel/contrib/pat/patTemplate.php

2379 lines
59 KiB
PHP

<?PHP
/**
* patTemplate
*
* $Id: patTemplate.php 1347 2009-12-03 21:06:36Z francois $
*
* powerful templating engine
*
* @version 3.0.0
* @package patTemplate
* @author Stephan Schmidt <schst@php.net>
* @license LGPL
* @link http://www.php-tools.net
*/
/**
* template already exists
*/
define( 'PATTEMPLATE_ERROR_TEMPLATE_EXISTS', 5010 );
/**
* template does not exist
*/
define ( 'PATTEMPLATE_WARNING_NO_TEMPLATE', 5011 );
/**
* unknown type
*/
define ( 'PATTEMPLATE_WARNING_UNKNOWN_TYPE', 5012 );
/**
* base class for module could not be found
*/
define( 'PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND', 5050 );
/**
* module could not be found
*/
define( 'PATTEMPLATE_ERROR_MODULE_NOT_FOUND', 5051 );
/**
* array expected
*/
define( 'PATTEMPLATE_ERROR_EXPECTED_ARRAY', 5052 );
/**
* No input
*/
define( 'PATTEMPLATE_ERROR_NO_INPUT', 6000 );
/**
* patTemplate
*
* powerful templating engine
*
* @version 3.0.0
* @package patTemplate
* @author Stephan Schmidt <schst@php.net>
* @license LGPL
* @link http://www.php-tools.net
*/
class patTemplate
{
/**
* standard system vars that identify pat tools
* @var array
*/
var $_systemVars = array(
'appName' => 'patTemplate',
'appVersion' => '3.0.0',
'author' => array(
'Stephan Schmidt <schst@php.net>'
)
);
/**
* default attributes for new templates
* @access private
* @var array
*/
var $_defaultAttributes = array(
'type' => 'standard',
'visibility' => 'visible',
'loop' => 1,
'unusedvars' => 'strip',
'whitespace' => 'keep',
'autoclear' => 'off',
'autoload' => 'on'
);
/**
* options for patTemplate
*
* Currently the following options are implemented:
* - maintainBc defines, whether patTemplate should be backwards compatible.
* This means, that you may use 'default' and 'empty' for subtemplates.
*
* @access private
* @var array
*/
var $_options = array(
'startTag' => '{',
'endTag' => '}',
'root' => '.',
'namespace' => 'patTemplate',
'maintainBc' => true
);
/**
* start tag
*
* @access private
* @var string
*/
var $_startTag = '{';
/**
* end tag
*
* @access private
* @var string
*/
var $_endTag = '}';
/**
* loaded modules
*
* Modules are:
* - Readers
* - Caches
* - Variable modifiers
* - Filters
*
* @access private
* @var array
*/
var $_modules = array();
/**
* directories, where modules can be stored
* @access private
* @var array
*/
var $_moduleDirs = array();
/**
* stores all template names
* @access private
* @var array
*/
var $_templateList = array();
/**
* stores all template data
* @access private
* @var array
*/
var $_templates = array();
/**
* stores all global variables
* @access private
* @var array
*/
var $_globals = array();
/**
* stores all local variables
* @access private
* @var array
*/
var $_vars = array();
/**
* stores the name of the first template that has been
* found
*
* @access private
* @var string
*/
var $_root;
/**
* output filters that should be used
*
* @access private
* @var array
*/
var $_outputFilters = array();
/**
* input filters that should be used
*
* @access private
* @var array
*/
var $_inputFilters = array();
/**
* template cache, that should be used
*
* @access private
* @var array
*/
var $_tmplCache = null;
/**
* Create a new patTemplate instance.
*
* The constructor accepts the type of the templates as sole parameter.
* You may choose one of:
* - html (default)
* - tex
*
* The type influences the tags you are using in your templates.
*
* @access public
* @param string type (either html or tex)
*/
function patTemplate( $type = 'html' )
{
if ( !defined( 'PATTEMPLATE_INCLUDE_PATH' ) )
define( 'PATTEMPLATE_INCLUDE_PATH', dirname( __FILE__ ) . '/patTemplate' );
$this->setType( $type );
}
/**
* sets an option
*
* Currently, the following options are supported
* - maintainBc (true|false)
* - namespace (string)
*
* @access public
* @param string option to set
* @param string value of the option
*/
function setOption( $option, $value )
{
$this->_options[$option] = $value;
}
/**
* gets an option
*
* @access public
* @param string option to get
* @return mixed value of the option
*/
function getOption( $option )
{
if ( !isset( $this->_options[$option] ) )
return null;
return $this->_options[$option];
}
/**
* sets name of directory where templates are stored
*
* @access public
* @param string dir where templates are stored
* @deprecated please use patTemplate::setRoot() instead
*/
function setBasedir( $basedir )
{
$this->_options['root'] = $basedir;
}
/**
* sets root base for the template
*
* The parameter depends on the reader you are using.
*
* @access public
* @param string root base of the templates
*/
function setRoot( $root )
{
$this->_options['root'] = $root;
}
/**
* gets name of root base for the templates
*
* @access public
* @return mixed root base
*/
function getRoot()
{
return $this->_options['root'];
}
/**
* sets namespace of patTemplate tags
*
* @access public
* @param string namespace
*/
function setNamespace( $ns )
{
$this->_options['namespace'] = $ns;
}
/**
* gets namespace of patTemplate tags
*
* @access public
* @return string namespace
*/
function getNamespace()
{
return $this->_options['namespace'];
}
/**
* set default attribute
*
* @access public
* @param string attribute name
* @param mixed attribute value
*/
function setDefaultAttribute( $name, $value )
{
$this->_defaultAttributes[$name] = $value;
}
/**
* set default attributes
*
* @access public
* @param array attributes
*/
function setDefaultAttributes( $attributes )
{
$this->_defaultAttributes = array_merge( $this->_defaultAttributes, $attributes );
}
/**
* get default attributes
*
* @access public
* @return return default attributes
*/
function getDefaultAttributes()
{
return $this->_defaultAttributes;
}
/**
* set the type for the templates
*
* @access public
* @param string type (html or tex)
* @return boolean true on success
*/
function setType( $type )
{
switch( strtolower( $type ) )
{
case "tex":
$this->setTags( '<{', '}>' );
break;
case "html":
$this->setTags( '{', '}' );
break;
default:
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_UNKNOWN_TYPE,
"Unknown type '$type'. Please use 'html' or 'tex'."
);
}
return true;
}
/**
* set the start and end tag for variables
*
* @access public
* @param string start tag
* @param string end tag
* @return boolean true on success
*/
function setTags( $startTag, $endTag )
{
$this->_options['startTag'] = $startTag;
$this->_options['endTag'] = $endTag;
$this->_startTag = $startTag;
$this->_endTag = $endTag;
return true;
}
/**
* get start tag for variables
*
* @access public
* @return string start tag
*/
function getStartTag()
{
return $this->_options['startTag'];
}
/**
* get end tag for variables
*
* @access public
* @return string end tag
*/
function getEndTag()
{
return $this->_options['endTag'];
}
/**
* add a directory where patTemplate should search for
* modules.
*
* You may either pass a string or an array of directories.
*
* patTemplate will be searching for a module in the same
* order you added them. If the module cannot be found in
* the custom folders, it will look in
* patTemplate/$moduleType.
*
* @access public
* @param string module type
* @param string|array directory or directories to search.
*/
function addModuleDir( $moduleType, $dir )
{
if ( !isset( $this->_moduleDirs[$moduleType] ) )
$this->_moduleDirs[$moduleType] = array();
if ( is_array( $dir ) )
$this->_moduleDirs[$moduleType] = array_merge( $this->_moduleDirs[$moduleType], $dir );
else
array_push( $this->_moduleDirs[$moduleType], $dir );
}
/**
* Sets an attribute of a template
*
* supported attributes: visibilty, loop, parse, unusedvars
*
* @param string $template name of the template
* @param string $attribute name of the attribute
* @param mixed $value value of the attribute
* @access public
* @see setAttributes(),getAttribute(), clearAttribute()
*/
function setAttribute( $template, $attribute, $value )
{
$template = strtolower( $template );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
$attribute = strtolower( $attribute );
$this->_templates[$template]['attributes'][$attribute] = $value;
return true;
}
/**
* Sets several attribute of a template
*
* $attributes has to be a assotiative arrays containing attribute/value pairs
* supported attributes: visibilty, loop, parse, unusedvars
*
* @param string $template name of the template
* @param array $attributes attribute/value pairs
* @access public
* @see setAttribute(), getAttribute(), clearAttribute()
*/
function setAttributes( $template, $attributes )
{
if ( !is_array( $attributes ) )
{
return patErrorManager::raiseError( PATTEMPLATE_ERROR_EXPECTED_ARRAY, 'patTemplate::setAttributes: Expected array as second parameter, '.gettype( $attributes ).' given' );
}
$template = strtolower( $template );
$attributes = array_change_key_case( $attributes );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
$this->_templates[$template]['attributes'] = array_merge( $this->_templates[$template]['attributes'], $attributes );
return true;
}
/**
* Get all attributes of a template
*
* @param string name of the template
* @return array attributes
* @access public
*/
function getAttributes( $template )
{
$template = strtolower( $template );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
return $this->_templates[$template]['attributes'];
}
/**
* Gets an attribute of a template
*
* supported attributes: visibilty, loop, parse, unusedvars
*
* @param string $template name of the template
* @param string $attribute name of the attribute
* @return mixed value of the attribute
* @access public
* @see setAttribute(), setAttributes(), clearAttribute()
*/
function getAttribute( $template, $attribute )
{
$template = strtolower( $template );
$attribute = strtolower( $attribute );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
return $this->_templates[$template]['attributes'][$attribute];
}
/**
* Clears an attribute of a template
*
* supported attributes: visibilty, loop, parse, unusedvars
*
* @param string $template name of the template
* @param string $attribute name of the attribute
* @access public
* @see setAttribute(), setAttributes(), getAttribute()
*/
function clearAttribute( $template, $attribute )
{
$template = strtolower( $template );
$attribute = strtolower( $attribute );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
$this->_templates[$template]['attributes'][$attribute] = '';;
return true;
}
/**
* Prepare a template
*
* This can be used if you want to add variables to
* a template, that has not been loaded yet.
*
* @access public
* @param string template name
*/
function prepareTemplate( $name )
{
$name = strtolower( $name );
if ( !isset( $this->_vars[$name] ) )
{
$this->_vars[$name] = array(
'scalar' => array(),
'rows' => array()
);
}
}
/**
* add a variable to a template
*
* A variable may also be an indexed array, but _not_
* an associative array!
*
* @access public
* @param string $template name of the template
* @param string $varname name of the variable
* @param mixed $value value of the variable
*/
function addVar( $template, $varname, $value )
{
$template = strtolower( $template );
$varname = strtoupper( $varname );
if ( !is_array( $value ) )
{
$this->_vars[$template]['scalar'][$varname] = $value;
return true;
}
$cnt = count( $value );
for ( $i = 0; $i < $cnt; $i++ )
{
if ( !isset( $this->_vars[$template]['rows'][$i] ) )
$this->_vars[$template]['rows'][$i] = array();
$this->_vars[$template]['rows'][$i][$varname] = $value[$i];
}
return true;
}
/**
* get the value of a variable
*
* @access public
* @param string name of the template
* @param string name of the variable
* @return string value of the variable, null if the variable is not set
*/
function getVar( $template, $varname )
{
$template = strtolower( $template );
$varname = strtoupper( $varname );
if ( isset( $this->_vars[$template]['scalar'][$varname] ) )
return $this->_vars[$template]['scalar'][$varname];
$value = array();
$cnt = count( $this->_vars[$template]['rows'] );
for ( $i = 0; $i < $cnt; $i++ )
{
if ( !isset( $this->_vars[$template]['rows'][$i][$varname] ) )
continue;
array_push( $value, $this->_vars[$template]['rows'][$i][$varname] );
}
if ( !empty( $value ) )
return $value;
return null;
}
/**
* Adds several variables to a template
*
* Each Template can have an unlimited amount of its own variables
* $variables has to be an assotiative array containing variable/value pairs
*
* @param string $template name of the template
* @param array $variables assotiative array of the variables
* @param string $prefix prefix for all variable names
* @access public
* @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
*/
function addVars( $template, $variables, $prefix = '' )
{
$template = strtolower( $template );
$prefix = strtoupper( $prefix );
$variables = array_change_key_case( $variables, CASE_UPPER );
foreach ( $variables as $varname => $value )
{
$varname = $prefix.$varname;
if ( !is_array( $value ) ) {
if (!is_scalar($value)) {
continue;
}
$this->_vars[$template]['scalar'][$varname] = $value;
continue;
}
$cnt = count( $value );
for ( $i = 0; $i < $cnt; $i++ )
{
if ( !isset( $this->_vars[$template]['rows'][$i] ) )
$this->_vars[$template]['rows'][$i] = array();
$this->_vars[$template]['rows'][$i][$varname] = $value[$i];
}
}
}
/**
* Adds several rows of variables to a template
*
* Each Template can have an unlimited amount of its own variables
* Can be used to add a database result as variables to a template
*
* @param string $template name of the template
* @param array $rows array containing assotiative arrays with variable/value pairs
* @param string $prefix prefix for all variable names
* @access public
* @see addVar(), addVars(), addGlobalVar(), addGlobalVars()
*/
function addRows( $template, $rows, $prefix = '' )
{
$template = strtolower( $template );
$prefix = strtoupper( $prefix );
$cnt = count( $rows );
for ( $i = 0; $i < $cnt; $i++ )
{
if ( !isset( $this->_vars[$template]['rows'][$i] ) )
$this->_vars[$template]['rows'][$i] = array();
$rows[$i] = array_change_key_case( $rows[$i], CASE_UPPER );
foreach ( $rows[$i] as $varname => $value )
{
$this->_vars[$template]['rows'][$i][$prefix.$varname] = $value;
}
}
}
/**
* Adds an object to a template
*
* All properties of the object will be available as template variables.
*
* @param string name of the template
* @param object|array object or array of objects
* @param string prefix for all variable names
* @access public
* @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
*/
function addObject( $template, $object, $prefix = '' )
{
if ( is_array( $object ) )
{
$rows = array();
foreach ( $object as $o )
array_push( $rows, get_object_vars( $o ) );
$this->addRows( $template, $rows, $prefix );
return true;
}
elseif ( is_object( $object ) )
{
$this->addVars( $template, get_object_vars( $object ), $prefix );
return true;
}
return false;
}
/**
* Adds a global variable
*
* Global variables are valid in all templates of this object.
* A global variable has to be scalar, it will be converted to a string.
*
* @access public
* @param string $varname name of the global variable
* @param string $value value of the variable
* @return boolean true on success
* @see addGlobalVars(), addVar(), addVars(), addRows()
*/
function addGlobalVar( $varname, $value )
{
$this->_globals[strtoupper( $varname )] = ( string )$value;
return true;
}
/**
* Adds several global variables
*
* Global variables are valid in all templates of this object.
*
* $variables is an associative array, containing name/value pairs of the variables.
*
* @access public
* @param array $variables array containing the variables
* @param string $prefix prefix for variable names
* @return boolean true on success
* @see addGlobalVar(), addVar(), addVars(), addRows()
*/
function addGlobalVars( $variables, $prefix = '' )
{
$variables = array_change_key_case( $variables, CASE_UPPER );
$prefix = strtoupper( $prefix );
foreach ( $variables as $varname => $value )
{
$this->_globals[$prefix.$varname] = ( string )$value;
}
return true;
}
/**
* get all global variables
*
* @access public
* @return array global variables
*/
function getGlobalVars()
{
return $this->_globals;
}
/**
* checks wether a template exists
*
* @access public
* @param string name of the template
* @return boolean true, if the template exists, false otherwise
*/
function exists( $name )
{
return in_array( strtolower( $name ), $this->_templateList );
}
/**
* enable a template cache
*
* A template cache will improve performace, as the templates
* do not have to be read on each request.
*
* @access public
* @param string name of the template cache
* @param array parameters for the template cache
* @return boolean true on success, patError otherwise
*/
function useTemplateCache( $cache, $params = array() )
{
if ( !is_object( $cache ) )
{
$cache = &$this->loadModule( 'TemplateCache', $cache, $params );
}
if ( patErrorManager::isError( $cache ) )
return $cache;
$this->_tmplCache = &$cache;
return true;
}
/**
* enable an output filter
*
* Output filters are used to modify the template
* result before it is sent to the browser.
*
* They are applied, when displayParsedTemplate() is called.
*
* @access public
* @param string name of the output filter
* @param array parameters for the output filter
* @return boolean true on success, patError otherwise
*/
function applyOutputFilter( $filter, $params = array() )
{
if ( !is_object( $filter ) )
{
$filter = &$this->loadModule( 'OutputFilter', $filter, $params );
}
if ( patErrorManager::isError( $filter ) )
return $filter;
$this->_outputFilters[] = &$filter;
return true;
}
/**
* enable an input filter
*
* input filters are used to modify the template
* stream before it is split into smaller templates-
*
* @access public
* @param string name of the input filter
* @param array parameters for the input filter
* @return boolean true on success, patError otherwise
*/
function applyInputFilter( $filter, $params = array() )
{
if ( !is_object( $filter ) )
{
$filter = &$this->loadModule( 'InputFilter', $filter, $params );
}
if ( patErrorManager::isError( $filter ) )
return $filter;
$this->_inputFilters[] = &$filter;
return true;
}
/**
* open a file and parse for patTemplate tags
*
* @access public
* @param name of the file
* @return true, if the template could be parsed
* @deprecated Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading
* @see readTemplatesFromInput()
*/
function readTemplatesFromFile( $filename )
{
return $this->readTemplatesFromInput( $filename, 'File' );
}
/**
* open any input and parse for patTemplate tags
*
* @access public
* @param string name of the input (filename, shm segment, etc.)
* @param string driver that is used as reader, you may also pass a Reader object
* @param array additional options that will only be used for this template
* @param string name of the template that should be used as a container, should not be used by public
* calls.
* @return boolean true, if the template could be parsed, false otherwise
*/
function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null )
{
if ($input === '') {
return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.');
}
if ( is_array( $options ) )
$options = array_merge( $this->_options, $options );
else
$options = $this->_options;
if ( !is_null( $parseInto ) )
$parseInto = strtolower( $parseInto );
$templates = false;
if ( $this->_tmplCache !== null )
{
/**
* get the unique cache key
*/
$key = $this->_tmplCache->getKey( $input, $options );
$templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key );
/**
* check for error returned from cache
*/
if ( patErrorManager::isError( $templates ) )
return $templates;
}
/**
* templates have not been loaded from cache
*/
if ( $templates === false )
{
if ( !is_object( $reader ) )
{
$reader = &$this->loadModule( 'Reader', $reader );
if ( patErrorManager::isError( $reader ) )
return $reader;
}
$reader->setOptions( $options );
/**
* set the root attributes
*/
if ( !is_null( $parseInto ) )
{
$attributes = $this->getAttributes( $parseInto );
if ( !patErrorManager::isError( $attributes ) )
{
$reader->setRootAttributes( $attributes );
}
}
$templates = $reader->readTemplates( $input );
/**
* check for error returned from reader
*/
if ( patErrorManager::isError( $templates ) )
return $templates;
/**
* store the
*/
if ( $this->_tmplCache !== null )
{
$this->_tmplCache->write( $key, $templates );
}
}
/**
* traverse all templates
*/
foreach ( $templates as $name => $spec )
{
/**
* root template
*/
if ( $name == '__ptroot' )
{
if ( $parseInto === false )
{
continue;
}
if ( !in_array( $parseInto, $this->_templateList ) )
continue;
$spec['loaded'] = true;
$spec['attributes'] = $this->_templates[$parseInto]['attributes'];
$name = $parseInto;
}
else
{
/**
* store the name
*/
array_push( $this->_templateList, $name );
}
/**
* if this is the first template that has been loaded
* set it as the root template
*/
if ( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true )
{
$this->_root = $name;
}
/**
* set some default values
*/
$spec['iteration'] = 0;
$spec['lastMode'] = 'w';
$spec['result'] = '';
$spec['modifyVars'] = array();
$spec['copyVars'] = array();
$spec['defaultVars'] = array();
/**
* store the template
*/
$this->_templates[$name] = $spec;
$this->prepareTemplate( $name );
/**
* store the default values of the variables
*/
foreach ( $spec['varspecs'] as $varname => $varspec )
{
if ( isset( $varspec['modifier'] ) )
{
$this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier'];
}
if ( isset( $varspec['copyfrom'] ) )
{
$this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom'];
}
if ( !isset( $varspec['default'] ) )
continue;
$this->_templates[$name]['defaultVars'][$varname] = $varspec['default'];
if ( !is_null( $this->getVar( $name, $varname ) ) )
continue;
$this->addVar( $name, $varname, $varspec['default'] );
}
unset($this->_templates[$name]['varspecs']);
/**
* autoload the template
*
* Some error management is needed here...
*/
if ( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' )
{
if ( $this->_templates[$name]['loaded'] !== true )
{
if ( $this->_templates[$name]['attributes']['parse'] == 'on' )
{
$this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name );
}
else
{
$this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name );
}
$this->_templates[$name]['loaded'] = true;
}
}
}
return true;
}
/**
* load from template cache
*
* @access private
* @param string name of the input (filename, shm segment, etc.)
* @param string driver that is used as reader, you may also pass a Reader object
* @param array options for the reader
* @param string cache key
* @return array|boolean either an array containing the templates, or false
*/
function _loadTemplatesFromCache( $input, &$reader, $options, $key )
{
if ( is_object( $reader ) )
$statName = $reader->getName();
else
$statName = $reader;
$stat = &$this->loadModule( 'Stat', $statName );
$stat->setOptions( $options );
/**
* get modification time
*/
$modTime = $stat->getModificationTime( $input );
$templates = $this->_tmplCache->load( $key, $modTime );
return $templates;
}
/**
* open any input and load content into template
*
* @access public
* @param string name of the input (filename, shm segment, etc.)
* @param string driver that is used as reader
* @param string name of the template that should be used as a container,
* @return boolean true, if the template could be parsed, false otherwise
*/
function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false )
{
if ( is_array( $options ) )
$options = array_merge( $this->_options, $options );
else
$options = $this->_options;
if ( !is_null( $parseInto ) )
$parseInto = strtolower( $parseInto );
$reader = &$this->loadModule( 'Reader', $reader );
if ( patErrorManager::isError( $reader ) )
{
return $reader;
}
$reader->setOptions($options);
$result = $reader->loadTemplate( $input );
if ( patErrorManager::isError( $result ) )
{
return $result;
}
$this->_templates[$parseInto]['content'] .= $result;
$this->_templates[$parseInto]['loaded'] = true;
return true;
}
/**
* load a template that had autoload="off"
*
* This is needed, if you change the source of a template and want to
* load it, after changing the attribute.
*
* @access public
* @param string template name
* @return boolean true, if template could be loaded
*/
function loadTemplate( $template )
{
$template = strtolower( $template );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
if ( $this->_templates[$template]['loaded'] === true )
return true;
if ( $this->_templates[$template]['attributes']['parse'] == 'on' )
{
return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
}
else
{
return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
}
}
/**
* loads a patTemplate module
*
* Modules are located in the patTemplate folder and include:
* - Readers
* - Caches
* - Variable Modifiers
* - Filters
* - Functions
* - Stats
*
* @access public
* @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
* @param string moduleName
* @param array parameters for the module
* @return object
*/
function &loadModule( $moduleType, $moduleName, $params = array() )
{
if ( !isset( $this->_modules[$moduleType] ) )
$this->_modules[$moduleType] = array();
$sig = md5( $moduleName . serialize( $params ) );
if ( isset( $this->_modules[$moduleType][$sig] ) )
return $this->_modules[$moduleType][$sig];
if ( !class_exists( 'patTemplate_Module' ) )
{
$file = sprintf( "%s/Module.php", $this->getIncludePath() );
if ( !@include_once $file )
return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' );
}
$baseClass = 'patTemplate_' . $moduleType;
if ( !class_exists( $baseClass ) )
{
$baseFile = sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType );
if ( !@include_once $baseFile )
return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." );
}
$moduleClass = 'patTemplate_' . $moduleType . '_' .$moduleName;
if ( !class_exists( $moduleClass ) )
{
if ( isset( $this->_moduleDirs[$moduleType] ) )
$dirs = $this->_moduleDirs[$moduleType];
else
$dirs = array();
array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
foreach ( $dirs as $dir )
{
$moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
if ( @include_once $moduleFile )
break;
return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." );
}
}
if ( !class_exists( $moduleClass ) )
{
return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." );
}
$this->_modules[$moduleType][$sig] = &new $moduleClass;
if ( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) )
{
$this->_modules[$moduleType][$sig]->setTemplateReference( $this );
}
$this->_modules[$moduleType][$sig]->setParams( $params );
return $this->_modules[$moduleType][$sig];
}
/**
* checks whether a module exists.
*
* Modules are located in the patTemplate folder and include:
* - Readers
* - Caches
* - Variable Modifiers
* - Filters
* - Functions
* - Stats
*
* @access public
* @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
* @param string moduleName
* @return boolean
*/
function moduleExists( $moduleType, $moduleName )
{
if ( isset( $this->_moduleDirs[$moduleType] ) )
$dirs = $this->_moduleDirs[$moduleType];
else
$dirs = array();
array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
foreach ( $dirs as $dir )
{
$moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
if ( !file_exists( $moduleFile ) )
continue;
if ( !is_readable( $moduleFile ) )
continue;
return true;
}
return false;
}
/**
* parses a template
*
* Parses a template and stores the parsed content.
* mode can be "w" for write (delete already parsed content) or "a" for append (appends the
* new parsed content to the already parsed content)
*
* @access public
* @param string name of the template
* @param string mode for the parsing
*/
function parseTemplate( $template, $mode = 'w' )
{
$template = strtolower( $template );
if ( !isset( $this->_templates[$template] ) )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$template' does not exist."
);
}
/**
* template is not visible
*/
if ( $this->_templates[$template]['attributes']['visibility'] == 'hidden' )
{
$this->_templates[$template]['result'] = '';
$this->_templates[$template]['parsed'] = true;
return true;
}
/**
* check, if the template has been loaded
* and load it if necessary.
*/
if ( $this->_templates[$template]['loaded'] !== true )
{
if ( $this->_templates[$template]['attributes']['parse'] == 'on' )
{
$result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
}
else
{
$result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
}
if ( patErrorManager::isError( $result ) )
{
return $result;
}
}
/**
* check for autoclear
*/
if (
isset( $this->_templates[$template]['attributes']['autoclear'] ) &&
$this->_templates[$template]['attributes']['autoclear'] == 'yes' &&
$mode === 'w' &&
$this->_templates[$template]['lastMode'] != 'a'
)
{
$this->_templates[$template]['parsed'] = false;
}
/**
* template has been parsed and mode is not 'append'
*/
if ( $this->_templates[$template]['parsed'] === true && $mode === 'w' )
{
return true;
}
$this->_templates[$template]['lastMode'] = $mode;
$this->_initTemplate( $template );
if ( !isset( $this->_vars[$template]['rows'] ) )
$this->_vars[$template]['rows'] = array();
$loop = count( $this->_vars[$template]['rows'] );
/**
* loop at least one times
*/
if ( $loop < 1 )
$loop = 1;
if ( isset( $this->_templates[$template]['attributes']['maxloop'] ) )
{
$loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop'];
}
$this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop );
$start = 0;
if ( isset( $this->_templates[$template]['attributes']['limit'] ) )
{
$p = strpos( $this->_templates[$template]['attributes']['limit'], ',' );
if ( $p === false )
{
$this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] );
$start = 0;
}
else
{
$start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p );
$end = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start;
$this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end );
}
}
/**
* template should be cleared before parsing
*/
if ( $mode == 'w' )
{
$this->_templates[$template]['result'] = '';
$this->_templates[$template]['iteration'] = $start;
}
$loopCount = 0;
for ( $i = $start; $i < $this->_templates[$template]['loop']; $i++ )
{
$finished = false;
unset( $this->_templates[$template]['vars'] );
/**
* fetch the variables
*/
$this->_fetchVariables( $template );
/**
* fetch the template
*/
$result = $this->_fetchTemplate( $template );
if ( $result === false )
{
$this->_templates[$template]['iteration']++;
continue;
}
/**
* parse
*/
$this->_parseVariables( $template );
$this->_parseDependencies( $template );
/**
* store result
*/
$this->_templates[$template]['result'] .= $this->_templates[$template]['work'];
$this->_templates[$template]['iteration']++;
++$loopCount;
/**
* check for maximum loops
*/
if ( isset( $this->_templates[$template]['attributes']['maxloop'] ) )
{
if ( $loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ( $loop-1 ) )
{
$loopCount = 0;
$finished = true;
$this->_templates[$template]['parsed'] = true;
$this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' );
$this->_templates[$template]['parsed'] = false;
$this->_templates[$template]['result'] = '';
}
}
}
if ( !$finished && isset( $this->_templates[$template]['attributes']['maxloop'] ) )
{
$this->_templates[$template]['parsed'] = true;
$this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false );
$this->_templates[$template]['parsed'] = false;
$this->_templates[$template]['result'] = '';
$this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = '';
}
$this->_parseGlobals($template);
$this->_handleUnusedVars( $template );
$this->_templates[$template]['parsed'] = true;
if ( isset( $this->_templates[$template]['attributes']['autoclear'] ) && $this->_templates[$template]['attributes']['autoclear'] == 'yes' )
{
$this->_vars[$template] = array(
'scalar' => array(),
'rows' => array()
);
}
return true;
}
/**
* Initialize a template
*
* This method checks the variable specifications and
* copys variables from other templates.
*
* @access private
* @param string name of the template
* @return boolean true on success
*/
function _initTemplate( $template )
{
foreach ( $this->_templates[$template]['copyVars'] as $dest => $src )
{
/**
* copy from the same template
*/
if ( !is_array( $src ) )
{
$srcTemplate = $template;
$srcVar = $src;
}
else
{
$srcTemplate = $src[0];
$srcVar = $src[1];
}
$copied = false;
/**
* copy from another template
*/
if ( isset( $this->_vars[$srcTemplate] ) )
{
if ( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) )
{
$this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar];
continue;
}
$rows = count( $this->_vars[$srcTemplate]['rows'] );
for ( $i = 0; $i < $rows; $i++ )
{
if ( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) )
continue;
if ( !isset( $this->_vars[$template]['rows'][$i] ) )
$this->_vars[$template]['rows'][$i] = array();
$this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar];
$copied = true;
}
}
if ( !$copied && isset( $this->_globals[$srcVar] ))
{
$this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar];
}
}
return true;
}
/**
* parse all variables in a template
*
* @access private
* @param string
*/
function _parseVariables( $template )
{
/**
* modify variables before parsing
*/
$this->_applyModifers($template, $this->_templates[$template]['vars']);
foreach ( $this->_templates[$template]['vars'] as $key => $value )
{
if ( is_array( $value ) )
{
if ( count( $this->_templates[$template]['currentDependencies'] ) == 1 )
{
$child = $this->_templates[$template]['currentDependencies'][0];
}
else
{
if ( isset( $this->_templates[$template]['attributes']['child'] ) )
$child = $this->_templates[$template]['attributes']['child'];
else
continue;
}
$this->setAttribute( $child, 'autoclear', 'yes' );
$this->addVar( $child, $key, $value );
continue;
}
$var = $this->_startTag.$key.$this->_endTag;
$this->_templates[$template]['work'] = @str_replace( $var, $value, $this->_templates[$template]['work'] );
}
return true;
}
/**
* parse global variables in the template
*
* @access private
* @param string name of the template
* @return boolean
*/
function _parseGlobals($template)
{
$globalVars = $this->_globals;
$this->_applyModifers($template, $globalVars);
foreach ( $globalVars as $key => $value )
{
if ( is_array( $value ) )
{
continue;
}
$var = $this->_startTag.$key.$this->_endTag;
$this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] );
}
return true;
}
/**
* apply variable modifiers
*
* The variables will be passed by reference.
*
* @access private
* @param string name of the template (use modifiers from this template)
* @param array variables to which the modifiers should be applied
* @return boolean
*/
function _applyModifers($template, &$vars)
{
foreach ( $this->_templates[$template]['modifyVars'] as $varname => $modifier )
{
if ( !isset( $vars[$varname] ) )
continue;
if ( ( $modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable( $modifier['mod'] ) )
{
$vars[$varname] = call_user_func( $modifier['mod'], $vars[$varname] );
continue;
}
if ( $modifier['type'] === 'php' )
continue;
$mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) );
$vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] );
}
return true;
}
/**
* parse all dependencies in a template
*
* @access private
* @param string
*/
function _parseDependencies( $template )
{
$countDep = count( $this->_templates[$template]['currentDependencies'] );
for ( $i = 0; $i < $countDep; $i++ )
{
$depTemplate = $this->_templates[$template]['currentDependencies'][$i];
$this->parseTemplate( $depTemplate );
$var = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag;
$this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] );
}
return true;
}
/**
* fetch plain template
*
* The template content will be stored in the template
* configuration so it can be used by other
* methods.
*
* @access private
* @param string template name
* @return boolean
*/
function _fetchTemplate( $template )
{
switch( $this->_templates[$template]['attributes']['type'] )
{
/**
* condition template
*/
case 'condition':
$value = $this->_getConditionValue( $template, $this->_templates[$template]['attributes']['conditionvar'] );
if ( $value === false )
{
$this->_templates[$template]['work'] = '';
$this->_templates[$template]['currentDependencies'] = array();
}
else
{
$this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data'];
$this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
}
break;
/**
* condition template
*/
case 'simplecondition':
foreach ( $this->_templates[$template]['attributes']['requiredvars'] as $var )
{
if ( $var[0] !== $template )
$this->_fetchVariables($var[0]);
if ( isset( $this->_templates[$var[0]]['vars'][$var[1]] ) && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 )
continue;
if (isset($this->_templates[$template]['attributes']['useglobals']))
{
if (isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1)
continue;
}
$this->_templates[$template]['work'] = '';
$this->_templates[$template]['currentDependencies'] = array();
break 2;
}
$this->_templates[$template]['work'] = $this->_templates[$template]['content'];
$this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies'];
break;
/**
* modulo template
*/
case 'modulo':
// check for empty template
if ($this->_hasVariables($template)) {
$value = ( $this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
} else {
$value = '__empty';
}
$value = $this->_getConditionValue( $template, $value, false );
if ( $value === false )
{
$this->_templates[$template]['work'] = '';
$this->_templates[$template]['currentDependencies'] = array();
}
else
{
$this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data'];
$this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
}
break;
/**
* standard template
*/
default:
$this->_templates[$template]['work'] = $this->_templates[$template]['content'];
$this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies'];
break;
}
return true;
}
/**
* check, whether a template contains variables
*
* @access private
* @param string template name
* @return boolean
*/
function _hasVariables($template)
{
if (!empty($this->_vars[$template]['scalar'])) {
return true;
}
if (isset($this->_vars[$template]['rows'][$this->_templates[$template]['iteration']])) {
return true;
}
return false;
}
/**
* fetch the value of a condition variable
*
* _fetchVariables() has to be called before this
* method is being called.
*
* @access private
* @param string template name
* @param string condition value
* @param boolean flag that indicates whether value is the name of the variable that should be resolved
*
* @todo split this method into smaller check methods that will be called according to
* a priority list
*/
function _getConditionValue( $template, $value, $isVar = true )
{
if ( $isVar === true )
{
if ( isset( $this->_templates[$template]['attributes']['conditiontmpl'] ) )
{
$_template = $this->_templates[$template]['attributes']['conditiontmpl'];
$this->_fetchVariables( $_template );
}
else
{
$_template = $template;
}
/**
* get the value from the template variables
*/
if ( !isset( $this->_templates[$_template]['vars'][$value] ) || strlen( $this->_templates[$_template]['vars'][$value] ) === 0 )
{
if ( $this->_templates[$template]['attributes']['useglobals'] == 'yes' || $this->_templates[$template]['attributes']['useglobals'] == 'useglobals' )
{
if ( isset( $this->_globals[$value] ) && strlen( $this->_globals[$value] ) > 0 )
{
$value = $this->_globals[$value];
}
else
{
$value = '__empty';
}
}
else
{
$value = '__empty';
}
}
else
{
$value = $this->_templates[$_template]['vars'][$value];
}
}
else
{
$_template = $template;
}
/**
* is __first?
*/
if ( $this->_templates[$_template]['iteration'] == 0 )
{
if ( isset( $this->_templates[$template]['subtemplates']['__first'] ) )
{
return '__first';
}
}
/**
* is __last?
*/
$max = $this->_templates[$_template]['loop'] - 1;
if ( $this->_templates[$_template]['iteration'] == $max )
{
if ( isset( $this->_templates[$template]['subtemplates']['__last'] ) )
{
return '__last';
}
}
/**
* found an exact match
*/
if ( isset( $this->_templates[$template]['subtemplates'][$value] ) )
{
return $value;
}
/**
* is __default?
*/
if ( isset( $this->_templates[$template]['subtemplates']['__default'] ) )
{
return '__default';
}
return false;
}
/**
* fetch variables for a template
*
* The variables will be stored in the template
* configuration so they can be used by other
* methods.
*
* @access private
* @param string template name
* @return boolean
*/
function _fetchVariables( $template )
{
/**
* variables already have been fetched
*/
if ( isset( $this->_templates[$template]['vars'] ) )
{
return true;
}
$iteration = $this->_templates[$template]['iteration'];
if ( isset( $this->_templates[$template]['attributes']['varscope'] ) )
{
$scopeTemplate = $this->_templates[$template]['attributes']['varscope'];
if ($this->exists($scopeTemplate)) {
$this->_fetchVariables( $scopeTemplate );
$vars = $this->_templates[$scopeTemplate]['vars'];
} else {
patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'Template \''.$scopeTemplate.'\' does not exist, referenced in varscope attribute of template \''.$template.'\'');
$vars = array();
}
}
else
{
$vars = array();
}
/**
* get the scalar variables
*/
if ( isset( $this->_vars[$template] ) && isset( $this->_vars[$template]['scalar'] ) )
{
$vars = array_merge( $vars, $this->_vars[$template]['scalar'] );
}
/**
* get the row variables
*/
if ( isset( $this->_vars[$template]['rows'][$iteration] ) )
{
$vars = array_merge( $vars, $this->_vars[$template]['rows'][$iteration] );
}
/**
* add some system variables
*/
$currentRow = $iteration + 1;
$vars['PAT_ROW_VAR'] = $currentRow;
if ( $this->_templates[$template]['attributes']['type'] == 'modulo' )
{
$vars['PAT_MODULO_REP'] = ceil( $currentRow / $this->_templates[$template]['attributes']['modulo'] );
$vars['PAT_MODULO'] = ( $this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
}
if ( $this->_templates[$template]['attributes']['addsystemvars'] !== false )
{
$vars['PATTEMPLATE_VERSION'] = $this->_systemVars['appVersion'];
$vars['PAT_LOOPS'] = $this->_templates[$template]['loop'];
switch ($this->_templates[$template]['attributes']['addsystemvars'])
{
case 'boolean':
$trueValue = 'true';
$falseValue = 'false';
break;
case 'integer':
$trueValue = '1';
$falseValue = '0';
break;
default:
$trueValue = $this->_templates[$template]['attributes']['addsystemvars'];
$falseValue = '';
break;
}
$vars['PAT_IS_ODD'] = ( $currentRow % 2 == 1 ) ? $trueValue : $falseValue;
$vars['PAT_IS_EVEN'] = ( $currentRow % 2 == 0 ) ? $trueValue : $falseValue;
$vars['PAT_IS_FIRST'] = ( $currentRow == 1 ) ? $trueValue : $falseValue;
$vars['PAT_IS_LAST'] = ( $currentRow == $this->_templates[$template]['loop'] ) ? $trueValue : $falseValue;
}
$this->_templates[$template]['vars'] = $vars;
return true;
}
/**
* handle all unused variables in a template
*
* This is influenced by the 'unusedvars' attribute of the
* template
*
* @access private
* @param string
*/
function _handleUnusedVars( $template )
{
$regexp = '/('.$this->_startTag.'[^a-z]+'.$this->_endTag.')/U';
switch( $this->_templates[$template]['attributes']['unusedvars'] )
{
case 'comment':
$this->_templates[$template]['result'] = preg_replace( $regexp, '<!-- \\1 -->', $this->_templates[$template]['result'] );
break;
case 'strip':
$this->_templates[$template]['result'] = preg_replace( $regexp, '', $this->_templates[$template]['result'] );
break;
case 'nbsp':
$this->_templates[$template]['result'] = preg_replace( $regexp, '&nbsp;', $this->_templates[$template]['result'] );
break;
case 'ignore':
break;
default:
$this->_templates[$template]['result'] = preg_replace( $regexp, $this->_templates[$template]['attributes']['unusedvars'], $this->_templates[$template]['result'] );
break;
}
return true;
}
/**
* returns a parsed Template
*
* If the template already has been parsed, it just returns the parsed template.
* If the template has not been loaded, it will be loaded.
*
* @access public
* @param string name of the template
* @return string Content of the parsed template
* @see displayParsedTemplate()
*/
function getParsedTemplate( $name = null )
{
if ( is_null( $name ) )
$name = $this->_root;
$name = strtolower( $name );
$result = $this->parseTemplate( $name );
if ( patErrorManager::isError( $result ) )
return $result;
return $this->_templates[$name]['result'];
}
/**
* displays a parsed Template
*
* If the template has not been loaded, it will be loaded.
*
* @see getParsedTemplate()
* @param string name of the template
* @return boolean true on success
* @access public
*/
function displayParsedTemplate( $name = null )
{
$result = $this->getParsedTemplate( $name );
/**
* error happened
*/
if ( patErrorManager::isError( $result ) )
return $result;
$cnt = count( $this->_outputFilters );
for ( $i = 0; $i < $cnt; $i++ )
{
$result = $this->_outputFilters[$i]->apply( $result );
}
echo $result;
return true;
}
/**
* parse a template and push the result into a variable of any other
* template
*
* If the template already has been parsed, it will just be pushed into the variable.
* If the template has not been loaded, it will be loaded.
*
* @access public
* @param string name of the template
* @return string Content of the parsed template
* @param boolean if set to true, the value will be appended to the value already stored.
* @see getParsedTemplate()
* @see addVar()
*/
function parseIntoVar( $srcTmpl, $destTmpl, $var, $append = false )
{
$srcTmpl = strtolower( $srcTmpl );
$destTmpl = strtolower( $destTmpl );
$var = strtoupper($var);
$result = $this->parseTemplate( $srcTmpl );
if ( patErrorManager::isError( $result ) )
return $result;
if ( $append !== true || !isset( $this->_vars[$destTmpl]['scalar'][$var] ) )
$this->_vars[$destTmpl]['scalar'][$var] = '';
$this->_vars[$destTmpl]['scalar'][$var] .= $this->_templates[$srcTmpl]['result'];
return true;
}
/**
* clears a parsed Template
*
* Parsed Content, variables and the loop attribute are cleared
*
* If you will not be using this template anymore, then you should
* call freeTemplate()
*
* @access public
* @param string name of the template
* @param boolean set this to true to clear all child templates, too
* @see clearAllTemplates()
* @see freeTemplate()
*/
function clearTemplate( $name, $recursive = false )
{
$name = strtolower( $name );
$this->_templates[$name]['parsed'] = false;
$this->_templates[$name]['work'] = '';
$this->_templates[$name]['iteration'] = 0;
$this->_templates[$name]['result'] = '';
$this->_vars[$name] = array(
'scalar' => array(),
'rows' => array()
);
if (!empty($this->_templates[$name]['defaultVars'])) {
foreach ($this->_templates[$name]['defaultVars'] as $varname => $value) {
$this->addVar($name, $varname, $value);
}
}
/**
* clear child templates as well
*/
if ( $recursive === true )
{
$deps = $this->_getDependencies( $name );
foreach ( $deps as $dep )
{
$this->clearTemplate( $dep, true );
}
}
return true;
}
/**
* clears all templates
*
* @access public
* @uses clearTemplate()
*/
function clearAllTemplates()
{
$templates = array_keys( $this->_templates );
$cnt = count( $templates );
for ( $i = 0; $i < $cnt; $i++ )
{
$this->clearTemplate( $templates[$i] );
}
return true;
}
/**
* frees a template
*
* All memory consumed by the template
* will be freed.
*
* @access public
* @param string name of the template
* @param boolean clear dependencies of the template
* @see freeAllTemplates()
*/
function freeTemplate( $name, $recursive = false )
{
$name = strtolower( $name );
$key = array_search( $name, $this->_templateList );
if ( $key === false )
{
return patErrorManager::raiseWarning(
PATTEMPLATE_WARNING_NO_TEMPLATE,
"Template '$name' does not exist."
);
}
unset( $this->_templateList[$key] );
$this->_templateList = array_values( $this->_templateList );
/**
* free child templates as well
*/
if ( $recursive === true )
{
$deps = $this->_getDependencies( $name );
foreach ( $deps as $dep )
{
$this->freeTemplate( $dep, true );
}
}
unset( $this->_templates[$name] );
unset( $this->_vars[$name] );
return true;
}
/**
* frees all templates
*
* All memory consumed by the templates
* will be freed.
*
* @access public
* @see freeTemplate()
*/
function freeAllTemplates()
{
$this->_templates = array();
$this->_vars = array();
}
/**
* get _all_ dependencies of a template,
* regardless of the subtemplates
*
* @access private
* @param string template name
* @return array list of all subtemplates
*/
function _getDependencies( $template )
{
$deps = array();
if ( isset( $this->_templates[$template]['dependencies'] ) )
$deps = $this->_templates[$template]['dependencies'];
if ( isset( $this->_templates[$template]['subtemplates'] ) )
{
foreach ( $this->_templates[$template]['subtemplates'] as $sub )
{
if ( isset( $sub['dependencies'] ) )
$deps = array_merge( $deps, $sub['dependencies'] );
}
}
$deps = array_unique( $deps );
return $deps;
}
/**
* Displays useful information about all or named templates
*
* This method breaks BC, as it now awaits an array instead of
* unlimited parameters.
*
* @param mixed array of templates that should be dumped, or null if you
* want all templates to be dumped
* @param string dumper
* @access public
*/
function dump( $restrict = null, $dumper = 'Html' )
{
if ( is_string( $restrict ) )
$restrict = array( $restrict );
$dumper = &$this->loadModule( 'Dump', $dumper );
if ( patErrorManager::isError( $dumper ) )
{
return $dumper;
}
if ( is_null( $restrict ) )
{
$templates = $this->_templates;
$vars = $this->_vars;
}
else
{
$restrict = array_map( 'strtolower', $restrict );
$templates = array();
$vars = array();
foreach ( $this->_templates as $name => $spec )
{
if ( !in_array( $name, $restrict ) )
continue;
$templates[$name] = $spec;
$vars[$name] = $this->_vars[$name];
}
}
$dumper->displayHeader();
$dumper->dumpGlobals( $this->_globals );
$dumper->dumpTemplates( $templates, $vars );
$dumper->displayFooter();
return true;
}
/**
* get the include path
*
* @access public
*/
function getIncludePath()
{
return PATTEMPLATE_INCLUDE_PATH;
}
/**
* apply input filters that have been set
*
* This is being called by the readers.
*
* @access public
* @param string template
* @return string filtered templeta
*/
function applyInputFilters( $template )
{
$cnt = count( $this->_inputFilters );
for ( $i = 0; $i < $cnt; $i++ )
{
$template = $this->_inputFilters[$i]->apply( $template );
}
return $template;
}
/**
* Convert the template to its string representation.
*
* This method allows you to just echo the patTemplate
* object in order to display the template.
*
* Requires PHP5
*
* <code>
* $tmpl = new patTemplate();
* $tmpl->readTemplatesFromFile( 'myfile.tmpl' );
* echo $tmpl;
* </code>
*
* @access private
* @return string
*/
function __toString()
{
return $this->getParsedTemplate();
}
}