mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Done tag option :raw and :escape
This commit is contained in:
parent
ac4ccd0fca
commit
783bf10b39
@ -1,5 +1,7 @@
|
||||
{var:escape $a}
|
||||
asdasd
|
||||
{/var}
|
||||
|
||||
|
||||
{Ts\Math::multi x=34 y=44}
|
||||
{$a + Ts\Math::multi(34, 44)}
|
||||
{34|Ts\Math::multi:44}
|
||||
{*{Ts\Math::multi x=34 y=44}*}
|
||||
{*{$a + Ts\Math::multi(34, 44)}*}
|
||||
{*{34|Ts\Math::multi:44}*}
|
@ -36,7 +36,7 @@ class Fenom
|
||||
const FORCE_VERIFY = 0x800;
|
||||
const AUTO_TRIM = 0x1000; // reserved
|
||||
const DENY_STATICS = 0x2000;
|
||||
const AUTO_STRIP = 0x4000; // reserved
|
||||
const AUTO_STRIP = 0x4000;
|
||||
|
||||
/* @deprecated */
|
||||
const DENY_INLINE_FUNCS = 0x20;
|
||||
|
@ -628,7 +628,7 @@ class Compiler
|
||||
*/
|
||||
public static function stdFuncParser(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
return $tag->escape($tag->callback . "(" . self::toArray($tag->tpl->parseParams($tokens)) . ', $tpl)');
|
||||
return $tag->out($tag->callback . "(" . self::toArray($tag->tpl->parseParams($tokens)) . ', $tpl)');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -658,7 +658,7 @@ class Compiler
|
||||
$args[] = var_export($param->getDefaultValue(), true);
|
||||
}
|
||||
}
|
||||
return $tag->escape($tag->callback . "(" . implode(", ", $args) . ')');
|
||||
return $tag->out($tag->callback . "(" . implode(", ", $args) . ')');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -672,6 +672,7 @@ class Compiler
|
||||
public static function stdFuncOpen(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
$tag["params"] = self::toArray($tag->tpl->parseParams($tokens));
|
||||
$tag->setOption(\Fenom::AUTO_ESCAPE, false);
|
||||
return 'ob_start();';
|
||||
}
|
||||
|
||||
@ -685,7 +686,8 @@ class Compiler
|
||||
*/
|
||||
public static function stdFuncClose($tokens, Tag $tag)
|
||||
{
|
||||
return $tag->escape($tag->callback . '(' . $tag["params"] . ', ob_get_clean(), $tpl)');
|
||||
$tag->restore(\Fenom::AUTO_ESCAPE);
|
||||
return $tag->out($tag->callback . '(' . $tag["params"] . ', ob_get_clean(), $tpl)');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -944,23 +946,19 @@ class Compiler
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @param Tag $tag
|
||||
*/
|
||||
public static function autoescapeOpen(Tokenizer $tokens, Tag $scope)
|
||||
public static function autoescapeOpen(Tokenizer $tokens, Tag $tag)
|
||||
{
|
||||
$boolean = ($tokens->get(T_STRING) == "true" ? true : false);
|
||||
$scope["escape"] = $scope->tpl->escape;
|
||||
$scope->tpl->escape = $boolean;
|
||||
$expected = ($tokens->get(T_STRING) == "true" ? true : false);
|
||||
$tokens->next();
|
||||
$tag->setOption(\Fenom::AUTO_ESCAPE, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokens
|
||||
* @param Tag $scope
|
||||
* @param Tag $tag
|
||||
*/
|
||||
public static function autoescapeClose(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$scope->tpl->escape = $scope["escape"];
|
||||
}
|
||||
public static function autoescapeClose(Tokenizer $tokens, Tag $tag) { }
|
||||
|
||||
}
|
||||
|
@ -16,15 +16,20 @@ class Tag extends \ArrayObject
|
||||
const FUNC = 2;
|
||||
const BLOCK = 4;
|
||||
|
||||
|
||||
const LTRIM = 1;
|
||||
const RTRIM = 2;
|
||||
|
||||
/**
|
||||
* @var Template
|
||||
*/
|
||||
public $tpl;
|
||||
public $name;
|
||||
public $options;
|
||||
public $options = array();
|
||||
public $line = 0;
|
||||
public $level = 0;
|
||||
public $callback;
|
||||
public $escape;
|
||||
|
||||
private $_offset = 0;
|
||||
private $_closed = true;
|
||||
@ -34,6 +39,7 @@ class Tag extends \ArrayObject
|
||||
private $_close;
|
||||
private $_tags = array();
|
||||
private $_floats = array();
|
||||
private $_changed = array();
|
||||
|
||||
/**
|
||||
* Create tag entity
|
||||
@ -51,6 +57,7 @@ class Tag extends \ArrayObject
|
||||
$this->_body = & $body;
|
||||
$this->_offset = strlen($body);
|
||||
$this->_type = $info["type"];
|
||||
$this->escape = $tpl->getOptions() & \Fenom::AUTO_ESCAPE;
|
||||
|
||||
if ($this->_type & self::BLOCK) {
|
||||
$this->_open = $info["open"];
|
||||
@ -70,10 +77,48 @@ class Tag extends \ArrayObject
|
||||
/**
|
||||
* Set tag option
|
||||
* @param string $option
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function setOption($option)
|
||||
public function tagOption($option)
|
||||
{
|
||||
if(method_exists($this, 'opt'.$option)) {
|
||||
$this->options[] = $option;
|
||||
} else {
|
||||
throw new \RuntimeException("Unknown tag option $option");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite template option for tag. When tag will be closed option will be reverted.
|
||||
* @param int $option option constant
|
||||
* @param bool $value true — add option, false — remove option
|
||||
*/
|
||||
public function setOption($option, $value) {
|
||||
$actual = (bool)($this->tpl->getOptions() & $option);
|
||||
if($actual != $value) {
|
||||
$this->_changed[$option] = $actual;
|
||||
$this->tpl->setOption(\Fenom::AUTO_ESCAPE, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the option
|
||||
* @param int $option
|
||||
*/
|
||||
public function restore($option)
|
||||
{
|
||||
if(isset($this->_changed[$option])) {
|
||||
$this->tpl->setOption($option, $this->_changed[$option]);
|
||||
unset($this->_changed[$option]);
|
||||
}
|
||||
}
|
||||
|
||||
public function restoreAll()
|
||||
{
|
||||
foreach($this->_changed as $option => $value) {
|
||||
$this->tpl->setOption($option, $this->_changed[$option]);
|
||||
unset($this->_changed[$option]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,6 +138,10 @@ class Tag extends \ArrayObject
|
||||
*/
|
||||
public function start($tokenizer)
|
||||
{
|
||||
foreach($this->options as $option) {
|
||||
$option = 'opt'.$option;
|
||||
$this->$option();
|
||||
}
|
||||
return call_user_func($this->_open, $tokenizer, $this);
|
||||
}
|
||||
|
||||
@ -146,7 +195,15 @@ class Tag extends \ArrayObject
|
||||
throw new \LogicException("Tag {$this->name} already closed");
|
||||
}
|
||||
if ($this->_close) {
|
||||
return call_user_func($this->_close, $tokenizer, $this);
|
||||
foreach($this->options as $option) {
|
||||
$option = 'opt'.$option.'end';
|
||||
if(method_exists($this, $option)) {
|
||||
$this->$option();
|
||||
}
|
||||
}
|
||||
$code = call_user_func($this->_close, $tokenizer, $this);
|
||||
$this->restoreAll();
|
||||
return $code;
|
||||
} else {
|
||||
throw new \LogicException("Can not use a inline tag {$this->name} as a block");
|
||||
}
|
||||
@ -195,33 +252,23 @@ class Tag extends \ArrayObject
|
||||
$this->_body .= $new_content;
|
||||
}
|
||||
|
||||
public function escape($code)
|
||||
/**
|
||||
* Generate output code
|
||||
* @param string $code
|
||||
* @return string
|
||||
*/
|
||||
public function out($code)
|
||||
{
|
||||
return $this->tpl->out($code);
|
||||
}
|
||||
|
||||
public function optLtrim()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function optRtrim()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function optTrim()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function optRaw()
|
||||
{
|
||||
|
||||
return $this->tpl->out($code, $this->escape);
|
||||
}
|
||||
|
||||
public function optEscape()
|
||||
{
|
||||
$this->escape = true;
|
||||
}
|
||||
|
||||
public function optRaw()
|
||||
{
|
||||
$this->escape = false;
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ class Template extends Render
|
||||
{
|
||||
const VAR_NAME = '$var';
|
||||
const TPL_NAME = '$tpl';
|
||||
|
||||
/**
|
||||
* Disable array parser.
|
||||
*/
|
||||
@ -287,6 +288,19 @@ class Template extends Render
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or unset the option
|
||||
* @param int $option
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setOption($option, $value) {
|
||||
if($value) {
|
||||
$this->_options |= $option;
|
||||
} else {
|
||||
$this->_options &= ~$option;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute some code at loading cache
|
||||
* @param $code
|
||||
@ -452,12 +466,16 @@ class Template extends Render
|
||||
/**
|
||||
* Output the value
|
||||
*
|
||||
* @param $data
|
||||
* @param string $data
|
||||
* @param null|bool $escape
|
||||
* @return string
|
||||
*/
|
||||
public function out($data)
|
||||
public function out($data, $escape = null)
|
||||
{
|
||||
if ($this->escape) {
|
||||
if($escape === null) {
|
||||
$escape = $this->_options & Fenom::AUTO_ESCAPE;
|
||||
}
|
||||
if ($escape) {
|
||||
return "echo htmlspecialchars($data, ENT_COMPAT, 'UTF-8');";
|
||||
} else {
|
||||
return "echo $data;";
|
||||
@ -590,11 +608,13 @@ class Template extends Render
|
||||
$tag = new Tag($action, $this, $info, $this->_body);
|
||||
if ($tokens->is(':')) { // parse tag options
|
||||
do {
|
||||
$tag->setOption($tokens->next()->need(T_STRING)->getAndNext());
|
||||
$tag->tagOption($tokens->next()->need(T_STRING)->getAndNext());
|
||||
} while ($tokens->is(':'));
|
||||
}
|
||||
$code = $tag->start($tokens);
|
||||
if (!$tag->isClosed()) {
|
||||
if ($tag->isClosed()) {
|
||||
$tag->restoreAll();
|
||||
} else {
|
||||
array_push($this->_stack, $tag);
|
||||
}
|
||||
return $code;
|
||||
|
@ -6,6 +6,7 @@ namespace Fenom;
|
||||
class AutoEscapeTest extends TestCase
|
||||
{
|
||||
|
||||
|
||||
public static function providerHTML()
|
||||
{
|
||||
$html = "<script>alert('injection');</script>";
|
||||
@ -30,32 +31,32 @@ class AutoEscapeTest extends TestCase
|
||||
array('{autoescape false}{raw $html}{/autoescape}, {$html}', "$html, $html", $vars, 0),
|
||||
|
||||
// inline function
|
||||
// array('{test_function text=$html}, {$html}', "$html, $html", $vars, 0),
|
||||
// array('{test_function text=$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{test_function:raw text=$html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{test_function:raw text="{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $html", $vars, 0),
|
||||
// array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
// array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
// array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
array('{test_function text=$html}, {$html}', "$html, $html", $vars, 0),
|
||||
array('{test_function text=$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{test_function:raw text=$html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{test_function:raw text="{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $html", $vars, 0),
|
||||
array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
||||
|
||||
// block function
|
||||
// array('{test_block_function}{$html}{/test_block_function}', $html, $vars, 0),
|
||||
// array('{test_block_function}{$html}{/test_block_function}', $escaped, $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{test_block_function:raw}{$html}{/test_block_function}', $html, $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{test_block_function:raw}{"{$html|up}"}{/test_block_function}', strtoupper($html), $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $html", $vars, 0),
|
||||
// array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
||||
// array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $html", $vars, 0),
|
||||
// array('{autoescape false}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
// array('{autoescape false}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
||||
array('{test_block_function}{$html}{/test_block_function}', $html, $vars, 0),
|
||||
array('{test_block_function}{$html}{/test_block_function}', $escaped, $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{test_block_function:raw}{$html}{/test_block_function}', $html, $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{test_block_function:raw}{"{$html|up}"}{/test_block_function}', strtoupper($html), $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $html", $vars, 0),
|
||||
array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
||||
array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
||||
array('{autoescape false}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}', "$escaped, $html", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
||||
);
|
||||
}
|
||||
|
||||
|
12
tests/cases/Fenom/TagOptionTest.php
Normal file
12
tests/cases/Fenom/TagOptionTest.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class TagOptionTest extends TestCase {
|
||||
|
||||
|
||||
public function testTrim() {
|
||||
|
||||
}
|
||||
}
|
@ -848,7 +848,7 @@ class TemplateTest extends TestCase
|
||||
public function _testSandbox()
|
||||
{
|
||||
try {
|
||||
var_dump($this->fenom->compileCode('{$a}')->getBody());
|
||||
var_dump($this->fenom->setOptions(0)->compileCode("{autoescape true}{test_block_function:raw}{\$html}{/test_block_function}{/autoescape}")->getBody());
|
||||
} catch (\Exception $e) {
|
||||
print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
while ($e->getPrevious()) {
|
||||
|
Loading…
Reference in New Issue
Block a user