* * version: 1.1 * * a previous version is available at opentemplates.sf.net * * Released under the MIT License * * Copyright (c) 2001-2003 Ludovico Magnocavallo * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * - The above copyright notice and this permission notice shall be included in all copies or substantial * portions of the Software. * * - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ require_once 'PEAR.php'; class Template extends PEAR { // general properties var $classname = 'Template'; var $root = ''; var $unresolved = 'keep'; var $deep_parsing = false; // parse text resulting from previous parsing when parsing outer templates // utility arrays var $_files = array(); // holds file handles as keys, filenames as values var $_templates = array(); // holds raw templates from files and blocks var $_vars = array(); // holds variable names as keys, values as values var $_errors = array(); function Template($root = '', $unresolved = 'keep', $deep_parsing = true) { $this->PEAR(); // unresolved variables $this->unresolved = $unresolved; //$unresolved; // keep|remove|comment $this->deep_parsing = $deep_parsing; // root directory if (!empty($root)) $this->setRoot($root); } function setRoot($root) { if (empty($root) || !is_dir($root)) return $this->raiseError("root $root not found or not a directory", 'setRoot', __LINE__); if (substr($root, - 1) != '/') $root .= '/'; $this->root = $root; } function get($name = null) { if (!(substr($name, 0, 1) == '_')) return $this->$name; } function getVars() { return($this->_vars); } function getVar($var) { return $this->_vars[$var]; } function getFile($file) { return $this->_files[$file]; } function getTemplate($template) { return $this->_templates[$template]; } function setFile($handle, $filename = '') { if (is_array($handle)) $this->_files = array_merge($this->_files, $handle); else if (is_string($handle)) $this->_files[$handle] = $filename; else return $this->raiseError("handle $handle is of unsupported type", 'setFile', __LINE__); } function setVar($name, $value = '') { if (is_array($name)) $this->_vars = array_merge($this->_vars, $name); else if (is_string($name)) $this->_vars[$name] = $value; else return $this->raiseError("name $name is of unsupported type", 'setVar', __LINE__); } function loadFile($handle) { if (!isset($this->_files[$handle])) return $this->raiseError("handle $handle is empty", 'loadFile', __LINE__); if (!file_exists($this->root . $this->_files[$handle])) return $this->raiseError("file " . $this->root . $this->_files[$handle] . " for handle $handle is non existent", 'loadFile', __LINE__); return( join('', file($this->root . $this->_files[$handle])) ); } function setBlock($parent, $handle, $replacement = '') { if (empty($this->_templates[$parent])) { $loaded_file = $this->loadFile($parent); if ($this->isError($loaded_file)) return $loaded_file; $this->_templates[$parent] = $loaded_file; } if (empty($replacement)) $replacement = strtoupper($handle); $re = '/(.*?)/s'; if (!preg_match($re, $this->_templates[$parent], $m)) { return $this->raiseError("block $handle not found", 'setBlock', __LINE__); } $this->_templates[$parent] = str_replace($m[0], '{' . $replacement . '}', $this->_templates[$parent]); $this->_templates[$handle] = $m[1]; } function parseBlock($target, $handle, &$vars, $parent = '') { if (!empty($parent)) { $ret = $this->setBlock($parent, $handle, $target); if ($this->isError($ret)) return $ret; } else { return $this->raiseError("no block template for handle $handle", 'parseBlock', __LINE__); } $block = $this->_templates[$handle]; $template = ''; $varnames = array(); $string = true; foreach ($vars as $k => $v) { if (is_array($vars[$k])) { $string = false; foreach ($vars[$k] as $key => $value) { $varnames[] = '{' . $handle . '_' . $key . '}'; } } else if (is_string($vars[$k]) || is_int($vars[$k])) { $varnames[] = '{' . $handle . '_0}'; } else { return $this->raiseError("unknown vars value", 'parseBlock', __LINE__); } break; } $varnames[] = '{' . $handle . '_}'; foreach ($vars as $k => $v) { if ($string) { $template .= str_replace($varnames, array($vars[$k], $k), $block); } else { array_push($vars[$k], $k); $template .= str_replace($varnames, $vars[$k], $block); } } $this->_vars[$target] = $template; } function parse($target, $handle, $append = false) { if (empty($this->_templates[$handle])) { $loaded_file = $this->loadFile($handle); if ($this->isError($loaded_file)) return $loaded_file; $this->_templates[$handle] = $loaded_file; } $template = preg_replace_callback('/{([^}]+)}/', array($this, 'subst'), $this->_templates[$handle]); if ($append && isset($this->_vars[$target])) $this->_vars[$target] .= $template; else $this->_vars[$target] = $template; return($template); } function subst($handle) { $handle = $handle[1]; if (isset($this->_vars[$handle])) { if ($this->deep_parsing) return preg_replace_callback('/{([\w]+)}/', array($this, 'subst'), $this->_vars[$handle]); else return $this->_vars[$handle]; } switch ($this->unresolved) { case 'comment': return(''); case 'remove': return(''); default: // 'keep', catches non standard values return('{' . $handle . '}'); } } function pparse($target, $handle, $append = false) { $ret = $this->parse($target, $handle, $append); if ($this->isError($ret)) return $ret; else echo($ret); } function &getError() { return array_pop($this->_errors); } function &raiseError($message, $method, $line) { $error = PEAR::raiseError(sprintf("%s.%s() line %d: %s", get_class($this), $method, $line, $message), PHPFRAME_TEMPLATE_ERROR); $this->_errors[] =& $error; return $error; } } ?>