2016-04-15 03:01:11 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
define('H2O_VERSION', '0.3');
|
|
|
|
defined('DS') or define('DS', DIRECTORY_SEPARATOR);
|
|
|
|
defined('H2O_ROOT') or define('H2O_ROOT', dirname(__FILE__) . DS);
|
|
|
|
|
|
|
|
require H2O_ROOT.'h2o/datatype.php';
|
|
|
|
require H2O_ROOT.'h2o/loaders.php';
|
|
|
|
require H2O_ROOT.'h2o/nodes.php';
|
|
|
|
require H2O_ROOT.'h2o/tags.php';
|
|
|
|
require H2O_ROOT.'h2o/errors.php';
|
|
|
|
require H2O_ROOT.'h2o/filters.php';
|
|
|
|
require H2O_ROOT.'h2o/context.php';
|
|
|
|
require H2O_ROOT.'h2o/parser.php';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Example:
|
|
|
|
* $h2o = new H2O('./template.html', array("loader"=>'file'));
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* $h2o = new H2O('template.html', array("loader"=>'hash'));
|
|
|
|
*/
|
|
|
|
class H2o {
|
|
|
|
var $searchpath;
|
|
|
|
var $context;
|
|
|
|
var $loader = false;
|
|
|
|
|
|
|
|
static $tags = array();
|
|
|
|
static $filters = array();
|
|
|
|
static $extensions = array();
|
|
|
|
|
|
|
|
static function getOptions($options = array()) {
|
|
|
|
return array_merge(array(
|
|
|
|
'loader' => 'file',
|
|
|
|
'cache' => 'file', // file | apc | memcache
|
|
|
|
'cache_prefix' => 'h2o_',
|
|
|
|
'cache_ttl' => 3600, // file | apc | memcache
|
|
|
|
'searchpath' => false,
|
|
|
|
'autoescape' => true,
|
|
|
|
|
|
|
|
// Enviroment setting
|
|
|
|
'BLOCK_START' => '{%',
|
|
|
|
'BLOCK_END' => '%}',
|
|
|
|
'VARIABLE_START' => '{{',
|
|
|
|
'VARIABLE_END' => '}}',
|
|
|
|
'COMMENT_START' => '{*',
|
|
|
|
'COMMENT_END' => '*}',
|
|
|
|
'TRIM_TAGS' => true
|
|
|
|
), $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
function __construct($file = null, $options = array()) {
|
|
|
|
# Init a environment
|
|
|
|
$this->options = $this->getOptions($options);
|
|
|
|
$loader = $this->options['loader'];
|
|
|
|
|
|
|
|
if (!$loader)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (is_object($loader)) {
|
|
|
|
$this->loader = $loader;
|
|
|
|
$this->loader->setOptions($this->options);
|
|
|
|
} else {
|
|
|
|
$loader = "H2o_{$loader}_Loader";
|
|
|
|
if (!class_exists($loader, false))
|
|
|
|
throw new Exception('Invalid template loader');
|
|
|
|
|
|
|
|
if (isset($options['searchpath'])){
|
|
|
|
$this->searchpath = $options['searchpath'];
|
|
|
|
} else if ($file) {
|
|
|
|
$this->searchpath = dirname(realpath($file)).DS;
|
|
|
|
} else {
|
|
|
|
$this->searchpath = getcwd().DS;
|
|
|
|
}
|
|
|
|
|
|
|
|
$loader_searchpath = is_array($this->searchpath) ? $this->searchpath : array($this->searchpath);
|
|
|
|
$this->loader = new $loader($loader_searchpath, $this->options);
|
|
|
|
}
|
|
|
|
$this->loader->runtime = $this;
|
|
|
|
|
|
|
|
if (isset($options['i18n'])) {
|
|
|
|
h2o::load('i18n');
|
|
|
|
$this->i18n = new H2o_I18n($this->searchpath, $options['i18n']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($file) {
|
|
|
|
$this->nodelist = $this->loadTemplate($file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadTemplate($file) {
|
|
|
|
return $this->nodelist = $this->loader->read_cache($file);
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadSubTemplate($file) {
|
|
|
|
return $this->loader->read($file);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Build a finalized nodelist from template ready to be cached
|
|
|
|
function parse($source, $filename = '', $env = null) {
|
|
|
|
if (!$env)
|
|
|
|
$env = $this->options;
|
|
|
|
|
|
|
|
if (!class_exists('H2o_Parser', false))
|
|
|
|
require H2O_ROOT.'h2o/parser.php';
|
|
|
|
|
|
|
|
$parser = new H2o_Parser($source, $filename, $this, $env);
|
|
|
|
$nodelist = $parser->parse();
|
|
|
|
return $nodelist;
|
|
|
|
}
|
|
|
|
|
|
|
|
function set($context, $value = null) {
|
|
|
|
# replace with new context object
|
|
|
|
if (is_object($context) && $context instanceof H2o_Context) {
|
|
|
|
return $this->context = $context;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Init context
|
|
|
|
if (!$this->context) {
|
|
|
|
$this->context = new H2o_Context($this->defaultContext(), $this->options);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Extend or set value
|
|
|
|
if (is_array($context)) {
|
|
|
|
return $this->context->extend($context);
|
|
|
|
}
|
|
|
|
elseif (is_string($context)) {
|
|
|
|
return $this->context[$context] = $value;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Render the nodelist
|
|
|
|
function render($context = array()) {
|
|
|
|
$this->set($context);
|
|
|
|
|
|
|
|
$this->stream = new StreamWriter;
|
|
|
|
$this->nodelist->render($this->context, $this->stream);
|
|
|
|
return $this->stream->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
static function parseString($source, $options = array()) {
|
|
|
|
$instance = new H2o(null, array_merge($options, array('loader' => false)));
|
|
|
|
$instance->nodelist = $instance->parse($source);
|
|
|
|
return $instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
static function &createTag($tag, $args = null, $parser, $position = 0) {
|
|
|
|
if (!isset(self::$tags[$tag])) {
|
|
|
|
throw new H2o_Error($tag . " tag doesn't exist");
|
|
|
|
}
|
|
|
|
$tagClass = self::$tags[$tag];
|
|
|
|
$tag = new $tagClass($args, $parser, $position);
|
|
|
|
return $tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a new tag
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* h2o::addTag('tag_name', 'ClassName');
|
|
|
|
*
|
|
|
|
* h2o::addTag(array(
|
|
|
|
* 'tag_name' => 'MagClass',
|
|
|
|
* 'tag_name2' => 'TagClass2'
|
|
|
|
* ));
|
|
|
|
*
|
|
|
|
* h2o::addTag('tag_name'); // Tag_name_Tag
|
|
|
|
*
|
|
|
|
* h2o::addTag(array('tag_name',
|
|
|
|
* @param unknown_type $tag
|
|
|
|
* @param unknown_type $class
|
|
|
|
*/
|
|
|
|
static function addTag($tag, $class = null) {
|
|
|
|
$tags = array();
|
|
|
|
if (is_string($tag)) {
|
|
|
|
if (is_null($class))
|
|
|
|
$class = ucwords("{$tag}_Tag");
|
|
|
|
$tags[$tag] = $class;
|
|
|
|
} elseif (is_array($tag)) {
|
|
|
|
$tags = $tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($tags as $tag => $tagClass) {
|
|
|
|
if (is_integer($tag)) {
|
|
|
|
unset($tags[$tag]);
|
|
|
|
$tag = $tagClass;
|
|
|
|
$tagClass = ucwords("{$tagClass}_Tag");
|
|
|
|
}
|
|
|
|
if (!class_exists($tagClass, false)) {
|
|
|
|
throw new H2o_Error("{$tagClass} tag is not found");
|
|
|
|
}
|
|
|
|
$tags[$tag] = $tagClass;
|
|
|
|
}
|
|
|
|
self::$tags = array_merge(self::$tags, $tags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a new filter to h2o runtime
|
|
|
|
*
|
|
|
|
* @param unknown_type $filter
|
|
|
|
* @param unknown_type $callback
|
|
|
|
* @return unknown
|
|
|
|
*/
|
|
|
|
static function addFilter($filter, $callback = null) {
|
|
|
|
if (is_array($filter)) {
|
|
|
|
$filters = $filter;
|
|
|
|
foreach($filters as $key => $filter) {
|
|
|
|
if (is_numeric($key))
|
|
|
|
$key = $filter;
|
|
|
|
self::addFilter($key, $filter);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} elseif (is_string($filter) && class_exists($filter, false) && is_subclass_of($filter, 'FilterCollection')) {
|
|
|
|
foreach (get_class_methods($filter) as $f) {
|
|
|
|
if (is_callable(array($filter, $f)))
|
|
|
|
self::$filters[$f] = array($filter, $f);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (is_null($callback))
|
|
|
|
$callback = $filter;
|
|
|
|
|
|
|
|
if (!is_callable($callback)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
self::$filters[$filter] = $callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
static function addLookup($callback) {
|
|
|
|
if (is_callable($callback)) {
|
|
|
|
H2o_Context::$lookupTable[] = $callback;
|
|
|
|
} else die('damm it');
|
|
|
|
}
|
|
|
|
|
|
|
|
static function load($extension, $file = null) {
|
|
|
|
if (!$file) {
|
|
|
|
$file = H2O_ROOT.'ext'.DS.$extension.'.php';
|
|
|
|
}
|
|
|
|
if (is_file($file)) {
|
|
|
|
include_once ($file);
|
|
|
|
self::$extensions[$extension] = $file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function defaultContext() {
|
|
|
|
return array('h2o' => new H2o_Info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenient wrapper for loading template file or string
|
|
|
|
* @param $name
|
|
|
|
* @param $options - H2o options
|
|
|
|
* @return Instance of H2o Template
|
|
|
|
*/
|
|
|
|
function h2o($name, $options = array()) {
|
|
|
|
$is_file = '/([^\s]*?)(\.[^.\s]*$)/';
|
|
|
|
|
|
|
|
if (!preg_match($is_file, $name)) {
|
|
|
|
return H2o::parseString($name, $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
$instance = new H2o($name, $options);
|
|
|
|
return $instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|