<?php
class Template
{
private $_template = '';
private $_assigns = array();
/** Variables with leading __ are reserved for internal using */
const VALID_VARIABLE = '(?!__)[a-zA-Z0-9_\x7f-\xff]*';
const TAG_SIGN_OPEN = '{';
const TAG_SIGN_CLOSE = '}';
public function __construct($template)
{
$this->_template = $template;
}
public function assign($name, $value)
{
if (!preg_match('/^' . self::VALID_VARIABLE . '$/', $name))
throw new Exception('Invalid name: "' . $name . '"');
if (is_array($value))
foreach ($value as $key_name => $val)
if (!preg_match('/^' . self::VALID_VARIABLE . '$/', $key_name))
throw new Exception('Invalid key name: "' . $key_name . '"');
$this->_assigns[$name] = $value;
}
private function _getToken($string, $sign, $pos, &$token)
{
$position = strpos($string, $sign, $pos);
if ($position === false)
{
$token = substr($string, $pos);
$pos = false;
}
else
{
$token = substr($string, $pos, $position - $pos);
$pos = $position + strlen($sign);
}
return $pos;
}
/**
* To avoid the existence of extra variables
* and overwriting assigns params
* @param type $prepared_code
* @param array $assigns
* @return type
*/
private static function _execute($prepared_code, array $assigns)
{
$__prepared_code = $prepared_code;
unset($prepared_code);
$__assigns = $assigns;
unset($assigns);
extract($__assigns);
unset($__assigns);
ob_start();
eval($__prepared_code);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public function parse()
{
$prepared_code = '?' . '>';
$pos = 0;
while ($pos !== false)
{
$pos = $this->_getToken($this->_template, self::TAG_SIGN_OPEN, $pos, $token);
$prepared_code .= $token;
if ($pos !== false)
{
$pos = $this->_getToken($this->_template, self::TAG_SIGN_CLOSE, $pos, $token);
if ($pos === false)
throw new Exception('Template syntax error. Expected "}"');
switch (true)
{
case preg_match('/^' . self::VALID_VARIABLE . '$/', $token):
$prepared_code .= '<?php echo ${\'' . $token . '\'} ?' . '>';
break;
case preg_match('/^loop +(' . self::VALID_VARIABLE . ')$/', $token, $match):
$prepared_code .= '<?php foreach (${\'' . $match[1] . '\'} as $__index => $__tmp)' .
'{extract($__tmp); unset($__tmp); ?' . '>';
break;
case preg_match('/^end +loop$/', $token):
$prepared_code .= '<?php } ?>';
break;
case preg_match('/^\%index\%$/', $token):
$prepared_code .= '<?php echo $__index ?' . '>';
break;
default:
throw new Exception('Template syntax error. Unexpected token "' . $token . '"');
break;
}
}
}
echo $prepared_code;
return self::_execute($prepared_code, $this->_assigns);
}
}
$templateHtml = <<<END_HTML
<div>{my_var}</div>
{loop items}
<div>{%index%}. {name}</div>
{end loop}
END_HTML;
$template = new Template($templateHtml);
$template->assign('my_var', 'test');
$template->assign('items', array(
array('name' => 'First'),
array('name' => 'Second')
)); echo $template->parse();
- Output for git.master, git.master_jit, rfc.property-hooks
- ?><div><?php echo ${'my_var'} ?></div>
<?php foreach (${'items'} as $__index => $__tmp){extract($__tmp); unset($__tmp); ?>
<div><?php echo $__index ?>. <?php echo ${'name'} ?></div>
<?php } ?><div>test</div>
<div>0. First</div>
<div>1. Second</div>
This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.
Active branches
Archived branches
Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page
preferences:
44.63 ms | 402 KiB | 8 Q