?
Path : /home/admin/domains/happytokorea.com/public_html_bk/libraries/pattemplate/ |
Current File : /home/admin/domains/happytokorea.com/public_html_bk/libraries/pattemplate/patTemplate.php |
<?PHP /** * patTemplate * * $Id: patTemplate.php 12694 2009-09-11 21:03:02Z ian $ * * powerful templating engine * * @version 3.1.0 * @package patTemplate * @author Stephan Schmidt <schst@php.net> * @license LGPL * @link http://www.php-tools.net */ // ** Following line Joomla! specific ** require_once( dirname( __FILE__ ) . '/patErrorManager.php' ); /** * 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 ); /** * Recursion */ define( 'PATTEMPLATE_ERROR_RECURSION', 6010 ); /** * patTemplate * * powerful templating engine * * @version 3.1.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.1.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' => array('__default' => '.'), 'namespace' => 'patTemplate', 'maintainBc' => true, 'defaultFunction' => false ); /** * 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; /** * placeholders, that have been discovered * * @access private * @var array */ var $_discoveredPlaceholders = array(); /** * 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->setRoot($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, $reader = '__default') { $this->_options['root'][$reader] = $root; } /** * gets name of root base for the templates * * @access public * @return mixed root base */ function getRoot($reader = '__default') { return $this->_options['root'][$reader]; } /** * sets namespace of patTemplate tags * * If you want to use more than one namespace, you may set this to * an array. All tags in these namespaces will be treated as patTemplate * tags. * * @access public * @param string|array namespace(s) */ function setNamespace($ns) { $this->_options['namespace'] = $ns; } /** * gets namespace of patTemplate tags * * @access public * @return string|array namespace(s) */ 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(); if(!isset($this->_vars[$template]['rows'])) return null; $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; } /** * clear the value of a variable * * @access public * @param string name of the template * @param string name of the variable * @return boolean * @see clearVars(), clearTemplate() */ function clearVar( $template, $varname ) { $template = strtolower( $template ); $varname = strtoupper( $varname ); if (isset( $this->_vars[$template]['scalar'][$varname] )) { unset ($this->_vars[$template]['scalar'][$varname]); return true; } $result = false; $cnt = count( $this->_vars[$template]['rows'] ); for ($i = 0; $i < $cnt; $i++) { if (!isset($this->_vars[$template]['rows'][$i][$varname])) { continue; } unset($this->_vars[$template]['rows'][$i][$varname]); $result = true; } return $result; } /** * 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]; } } } /** * Clear all variables in a template * * This clears only variables, but does * * @access public * @param string $template name of the template * @return boolean * @see clearVar(), clearTemplate() */ function clearVars( $template ) { $template = strtolower($template); $this->_vars[$template] = array( 'scalar' => array(), 'rows' => array() ); return true; } /** * 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. * * @access public * @param string name of the template * @param object|array object or array of objects * @param string prefix for all variable names * @param boolean ignore private properties (starting with _) * @see addVar(), addRows(), addGlobalVar(), addGlobalVars() */ function addObject( $template, $object, $prefix = '', $ignorePrivate = false ) { if( is_array( $object ) ) { $rows = array(); foreach($object as $o) { array_push( $rows, $this->getObjectVars($o, $ignorePrivate) ); } return $this->addRows( $template, $rows, $prefix ); } elseif (is_object($object)) { return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix ); } return false; } /** * get the vars from an object * * @access private * @param object * @param boolean ignore private properties (starting with _) * @return array */ function getObjectVars($obj, $ignorePrivate = false) { if (method_exists($obj, 'getVars')) { return $obj->getVars(); } $vars = get_object_vars($obj); if ($ignorePrivate === false) { return $vars; } foreach ($vars as $var => $value) { if ($var{0} == '_') { unset($vars[$var]); } } return $vars; } /** * 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; } /** * Clears a global variable * * @access public * @param string $varname name of the global variable * @return boolean true on success * @see clearVar(), clearVars(), clearGlobalVars() */ function clearGlobalVar( $varname ) { $varname = strtoupper( $varname ); if (!isset($this->_globals[$varname])) { return false; } unset($this->_globals[$varname]); return true; } /** * Clears all global variables * * @access public * @return boolean true on success * @see clearVar(), clearVars(), clearGlobalVar() */ function clearGlobalVars() { $this->_globals = array(); 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(), $template = null ) { if (!is_object($filter)) { $filter = &$this->loadModule( 'OutputFilter', $filter, $params ); } if (patErrorManager::isError($filter)) { return $filter; } if ($template === null) { $this->_outputFilters[] = &$filter; return true; } $template = strtolower($template); if (!$this->exists($template)) { return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist'); } $this->_templates[$template]['attributes']['outputfilter'] = &$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 ((string)$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; } } if ($reader->isInUse()) { $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true); 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(), $new = false ) { if( !isset( $this->_modules[$moduleType] ) ) $this->_modules[$moduleType] = array(); $sig = md5( $moduleName . serialize( $params ) ); if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) { return $this->_modules[$moduleType][$sig]; } if( !class_exists( 'patTemplate_Module' ) ) { $file = sprintf( "%s/Module.php", $this->getIncludePath() ); if( !file_exists( $file ) or !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( !file_exists( $baseFile ) or !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 ); $found = false; foreach( $dirs as $dir ) { $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) ); if ( file_exists( $moduleFile ) and include_once $moduleFile) { $found = true; break; } } if( !$found ) { 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 ) { // !!!JOOMLA VARIATION!!! // cache checks on files static $paths; if (!$paths) { $paths = array(); } 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 (!isset( $paths[$moduleFile] )) { if (!file_exists($moduleFile)) { $paths[$moduleFile] = false; } else if (!is_readable($moduleFile)) { $paths[$moduleFile] = false; } else { $paths[$moduleFile] = true; } } if (!$paths[$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 ); $result = $this->_parseDependencies( $template ); if (patErrorManager::isError($result)) { return $result; } /** * 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() ); } if (isset($this->_templates[$template]['attributes']['outputfilter'])) { if (is_object($this->_templates[$template]['attributes']['outputfilter'])) { $filter = &$this->_templates[$template]['attributes']['outputfilter']; } else { $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']); } if (patErrorManager::isError($filter)) { return $filter; } $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']); } 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'] ); } // apply the default modifier if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) { $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier']; if (is_callable($defaultModifier)) { $type = 'php'; } else { $type = 'custom'; $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier)); } foreach (array_keys($vars) as $varname) { if (isset($this->_templates[$template]['modifyVars'][$varname])) { continue; } if ($type === 'php') { $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]); } else { $vars[$varname] = $defaultModifier->modify($vars[$varname], array()); } } } 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]; if ($depTemplate == $template) { return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion'); } $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 ) { // different template scope if( $var[0] !== $template ) { $this->_fetchVariables($var[0]); } $value = null; // fetch the local variable if( isset( $this->_templates[$var[0]]['vars'][$var[1]] ) && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) { $value = $this->_templates[$var[0]]['vars'][$var[1]]; } if (isset($this->_templates[$template]['attributes']['useglobals'])) { if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) { $value = $this->_globals[$var[1]]; } } if ($value !== null) { if ($var[2] === null) { continue; } else { // Joomla! addition 23-June-2005 // value wrapped in ## uses regex for comparison $condition = $var[2]; if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) { if (preg_match( $condition, $value )) { continue; } } else if ($condition == $value) { continue; } /* Pat Original if ($var[2] == $value) { 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 = (string)($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; } // if value is empty and a template for empty has been defined, this // has priority if ($value === '__empty' && isset($this->_templates[$template]['subtemplates']['__empty'])) { return $value; } // only one iteration (but not empty), use the __single condition if ($value !== '__empty' && $this->_templates[$_template]['loop'] === 1) { if( isset($this->_templates[$template]['subtemplates']['__single'])) { return '__single'; } } else { // is __first? if( $this->_templates[$_template]['iteration'] == 0 ) { if( isset( $this->_templates[$template]['subtemplates']['__first'] ) ) { return '__first'; } } /** * is __last? */ if (isset($this->_templates[$_template]['loop'])) { $max = $this->_templates[$_template]['loop'] - 1; if( $this->_templates[$_template]['iteration'] == $max ) { if( isset( $this->_templates[$template]['subtemplates']['__last'] ) ) { return '__last'; } } } } // search for exact match foreach (array_keys($this->_templates[$template]['subtemplates']) as $key) { if (isset($this->_templates[$template]['subtemplates'][$key]['attributes']['var'])) { $var = $this->_templates[$template]['subtemplates'][$key]['attributes']['var']; if (isset($this->_templates[$template]['vars'][$var])) { $current = $this->_templates[$template]['vars'][$var]; } else { $current = null; } } else { $current = $key; } if ((string)$value === (string)$current) { return $key; } } /** * 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']; $vars = array(); if( isset( $this->_templates[$template]['attributes']['varscope'] ) ) { if (!is_array($this->_templates[$template]['attributes']['varscope'])) { $this->_templates[$template]['attributes']['varscope'] = array($this->_templates[$template]['attributes']['varscope']); } foreach ($this->_templates[$template]['attributes']['varscope'] as $scopeTemplate) { if ($this->exists($scopeTemplate)) { $this->_fetchVariables( $scopeTemplate ); $vars = array_merge($this->_templates[$scopeTemplate]['vars'], $vars); } else { patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'Template \''.$scopeTemplate.'\' does not exist, referenced in varscope attribute of template \''.$template.'\''); } } } 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 + $this->_templates[$template]['attributes']['rowoffset']; $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; $vars['PAT_ROW_TYPE'] = ( $currentRow % 2 == 1 ) ? 'odd' : 'even'; } $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\\2 -->', $this->_templates[$template]['result'] ); break; case 'strip': $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1', $this->_templates[$template]['result'] ); break; case 'nbsp': $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1 ', $this->_templates[$template]['result'] ); break; case 'ignore': break; default: $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1'.$this->_templates[$template]['attributes']['unusedvars'], $this->_templates[$template]['result'] ); break; } // replace quoted variables $regexp = '/[\\\]'.$this->_startTag.'([^a-z]+)[\\\]'.$this->_endTag.'/U'; $this->_templates[$template]['result'] = preg_replace( $regexp, $this->_startTag.'\\1'.$this->_endTag, $this->_templates[$template]['result'] ); 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 * @param boolean whether to apply output filters * @return string Content of the parsed template * @see displayParsedTemplate() */ function getParsedTemplate( $name = null, $applyFilters = false ) { if (is_null($name)) { $name = $this->_root; } $name = strtolower( $name ); $result = $this->parseTemplate( $name ); if (patErrorManager::isError( $result )) { return $result; } if ($applyFilters === false) { return $this->_templates[$name]['result']; } $result = $this->_templates[$name]['result']; $cnt = count ($this->_outputFilters); for ($i = 0; $i < $cnt; $i++) { $result = $this->_outputFilters[$i]->apply( $result ); } return $result; } /** * displays a parsed Template * * If the template has not been loaded, it will be loaded. * * @see getParsedTemplate() * @param string name of the template * @param boolean whether to apply output filters * @return boolean true on success * @access public */ function displayParsedTemplate($name = null, $applyFilters = true) { $result = $this->getParsedTemplate($name, $applyFilters); /** * error happened */ if (patErrorManager::isError($result)) { return $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] ); if (isset($this->_discoveredPlaceholders[$name])) { unset($this->_discoveredPlaceholders[$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(); $this->_templateList = 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 * @return string */ 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; } /** * checks, whether a placeholder exists in a template * * @access public * @param string name of the placeholder * @param string name of the template * @param boolean whether to use the cached result of a previous call */ function placeholderExists($placeholder, $tmpl, $cached = true) { $tmpl = strtolower($tmpl); $placeholder = strtoupper($placeholder); if (!$this->exists($tmpl)) { return false; } if ($cached === true) { if (isset($this->_discoveredPlaceholders[$tmpl]) && isset($this->_discoveredPlaceholders[$tmpl][$placeholder])) { return $this->_discoveredPlaceholders[$tmpl][$placeholder]; } } if (isset($this->_templates[$tmpl]['subtemplates'])) { $content = ''; foreach ($this->_templates[$tmpl]['subtemplates'] as $temp) { if (!isset($temp['data'])) { continue; } $content .= $temp['data']; } } else { $content = $this->_templates[$tmpl]['content']; } $search = $this->_startTag . $placeholder . $this->_endTag; if (strstr($content, $search) !== false) { $this->_discoveredPlaceholders[$tmpl][$placeholder] = true; return true; } $this->_discoveredPlaceholders[$tmpl][$placeholder] = false; return false; } /** * 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(); } } ?>