mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-28 06:08:52 +00:00
[feature/twig] Fixing DEFINE statements
PHPBB3-11598
This commit is contained in:
parent
abb7901edb
commit
64963b5962
5 changed files with 196 additions and 33 deletions
50
phpBB/includes/template/twig/definition.php
Normal file
50
phpBB/includes/template/twig/definition.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* @package phpBB3
|
||||
* @copyright (c) 2013 phpBB Group
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class holds all DEFINE variables from the current page load
|
||||
*/
|
||||
class phpbb_template_twig_definition
|
||||
{
|
||||
/** @var array **/
|
||||
protected $definitions = array();
|
||||
|
||||
/**
|
||||
* Get a DEFINE'd variable
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed Null if not found
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
return (isset($this->definitions[$name])) ? $this->definitions[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEFINE a variable
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return phpbb_template_twig_definition
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
$this->definitions[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ class phpbb_template_twig_lexer extends Twig_Lexer
|
|||
public function tokenize($code, $filename = null)
|
||||
{
|
||||
$valid_starting_tokens = array(
|
||||
// Commented out tokens are handled separately from the main replace
|
||||
/*'BEGIN',
|
||||
'BEGINELSE',
|
||||
'END',*/
|
||||
|
@ -27,9 +28,8 @@ class phpbb_template_twig_lexer extends Twig_Lexer
|
|||
'ELSE',
|
||||
'ELSEIF',
|
||||
'ENDIF',
|
||||
'DEFINE',
|
||||
'DEFINE',
|
||||
'UNDEFINE',
|
||||
/*'DEFINE',
|
||||
'UNDEFINE',*/
|
||||
'ENDDEFINE',
|
||||
/*'INCLUDE',
|
||||
'INCLUDEPHP',*/
|
||||
|
@ -42,22 +42,21 @@ class phpbb_template_twig_lexer extends Twig_Lexer
|
|||
// Fix our BEGIN statements
|
||||
$code = $this->fix_begin_tokens($code);
|
||||
|
||||
// Fix our IF tokens
|
||||
$code = $this->fix_if_tokens($code);
|
||||
|
||||
// Fix our DEFINE tokens
|
||||
$code = $this->fix_define_tokens($code);
|
||||
|
||||
// Replace <!-- INCLUDE blah.html --> with {% include 'blah.html' %}
|
||||
$code = preg_replace('#<!-- INCLUDE(PHP)? (.*?) -->#', "{% INCLUDE$1 '$2' %}", $code);
|
||||
|
||||
// This strips the $ inside of a tag directly after the token, which was used in <!-- DEFINE $NAME
|
||||
$code = preg_replace('#<!-- DEFINE \$(.*)-->#', '<!-- DEFINE $1-->', $code);
|
||||
|
||||
// This strips the . or $ inside of a tag directly before a variable name, which was used in <!-- IF .blah and <!-- IF $BLAH
|
||||
// In case of .varname, it replaces it with varname|length (as this is how it was treated before)
|
||||
$code = preg_replace_callback('#<!-- IF((.*)[\s][\$|\.]([^\s]+)(.*))-->#', array($this, 'tag_if_cleanup'), $code);
|
||||
|
||||
// Replace all of our starting tokens, <!-- TOKEN --> with Twig style, {% TOKEN %}
|
||||
// This also strips outer parenthesis, <!-- IF (blah) --> becomes <!-- IF blah -->
|
||||
$code = preg_replace('#<!-- (' . implode('|', $valid_starting_tokens) . ')(?: (.*?) ?)?-->#', '{% $1 $2 %}', $code);
|
||||
|
||||
// Replace all of our variables, {VARNAME} or {$VARNAME}, with Twig style, {{ VARNAME }}
|
||||
$code = preg_replace('#{\$?([a-zA-Z0-9_\.]+)}#', '{{ $1 }}', $code);
|
||||
// Replace all of our variables, {VARNAME}, with Twig style, {{ VARNAME }}
|
||||
$code = preg_replace('#{([a-zA-Z0-9_\.]+)}#', '{{ $1 }}', $code);
|
||||
|
||||
return parent::tokenize($code, $filename);
|
||||
}
|
||||
|
@ -68,7 +67,7 @@ class phpbb_template_twig_lexer extends Twig_Lexer
|
|||
* Not meant to be used outside of this context, public because the anonymous function calls this
|
||||
*
|
||||
* @param string $code
|
||||
* @param array $parent_nodes
|
||||
* @param array $parent_nodes (used in recursion)
|
||||
* @return string
|
||||
*/
|
||||
public function fix_begin_tokens($code, $parent_nodes = array())
|
||||
|
@ -134,19 +133,56 @@ class phpbb_template_twig_lexer extends Twig_Lexer
|
|||
}
|
||||
|
||||
/**
|
||||
* preg_replace_callback to clean up IF statements
|
||||
* Fix IF statements
|
||||
*
|
||||
* This strips the . or $ inside of a tag directly before a variable name.
|
||||
* Was used in <!-- IF .blah or <!-- IF $BLAH
|
||||
*
|
||||
* @param mixed $matches
|
||||
* @param string $code
|
||||
* @return string
|
||||
*/
|
||||
protected function tag_if_cleanup($matches)
|
||||
protected function fix_if_tokens($code)
|
||||
{
|
||||
// Replace $TEST with TEST
|
||||
$matches[1] = preg_replace('#\s\$([a-zA-Z_0-9]+)#', ' $1', $matches[1]);
|
||||
$matches[1] = preg_replace('#\s\.([a-zA-Z_0-9]+)#', ' $1|length', $matches[1]);
|
||||
$callback = function($matches)
|
||||
{
|
||||
// Replace $TEST with definition.TEST
|
||||
$matches[1] = preg_replace('#\s\$([a-zA-Z_0-9]+)#', ' definition.$1', $matches[1]);
|
||||
|
||||
return '<!-- IF ' . $matches[1] . ' -->';
|
||||
// Replace .test with test|length
|
||||
$matches[1] = preg_replace('#\s\.([a-zA-Z_0-9]+)#', ' $1|length', $matches[1]);
|
||||
|
||||
return '<!-- IF ' . $matches[1] . ' -->';
|
||||
};
|
||||
|
||||
return preg_replace_callback('#<!-- IF((.*)[\s][\$|\.]([^\s]+)(.*))-->#', $callback, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix DEFINE statements and {$VARNAME} variables
|
||||
*
|
||||
* @param string $code
|
||||
* @return string
|
||||
*/
|
||||
protected function fix_define_tokens($code)
|
||||
{
|
||||
/**
|
||||
* Changing $VARNAME to definition.varname because set is only local
|
||||
* context (e.g. DEFINE $TEST will only make $TEST available in current
|
||||
* template and any child templates, but not any parent templates).
|
||||
*
|
||||
* DEFINE handles setting it properly to definition in its node, but the
|
||||
* variables reading FROM it need to be altered to definition.VARNAME
|
||||
*
|
||||
* Setting up definition as a class in the array passed to Twig
|
||||
* ($context) makes set definition.TEST available in the global context
|
||||
*/
|
||||
|
||||
// Replace <!-- DEFINE $NAME with {% DEFINE definition.NAME
|
||||
$code = preg_replace('#<!-- DEFINE \$(.*)-->#', '{% DEFINE $1 %}', $code);
|
||||
|
||||
// Changing UNDEFINE NAME to DEFINE NAME = null to save from creating an extra token parser/node
|
||||
$code = preg_replace('#<!-- UNDEFINE \$(.*)-->#', '{% DEFINE $1= null %}', $code);
|
||||
|
||||
// Replace all of our variables, {$VARNAME}, with Twig style, {{ definition.VARNAME }}
|
||||
$code = preg_replace('#{\$([a-zA-Z0-9_\.]+)}#', '{{ definition.$1 }}', $code);
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
|
49
phpBB/includes/template/twig/node/define.php
Normal file
49
phpBB/includes/template/twig/node/define.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* @package phpBB3
|
||||
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier, Armin Ronacher
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
class phpbb_template_twig_node_define extends Twig_Node
|
||||
{
|
||||
public function __construct($capture, Twig_NodeInterface $name, Twig_NodeInterface $value, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('name' => $name, 'value' => $value), array('capture' => $capture, 'safe' => false), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
if ($this->getAttribute('capture')) {
|
||||
$compiler
|
||||
->write("ob_start();\n")
|
||||
->subcompile($this->getNode('value'))
|
||||
;
|
||||
|
||||
$compiler->raw(" = ('' === \$value = ob_get_clean()) ? '' : new Twig_Markup(\$value, \$this->env->getCharset())");
|
||||
}
|
||||
else
|
||||
{
|
||||
$compiler
|
||||
->write("\$value = '")
|
||||
->raw($this->getNode('value')->getAttribute('value'))
|
||||
->raw("';\n")
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw("\$context['definition']->set('")
|
||||
->raw($this->getNode('name')->getAttribute('name'))
|
||||
->raw("', \$value);\n")
|
||||
;
|
||||
}
|
||||
}
|
|
@ -7,8 +7,39 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class phpbb_template_twig_tokenparser_define extends Twig_TokenParser_Set
|
||||
class phpbb_template_twig_tokenparser_define extends Twig_TokenParser
|
||||
{
|
||||
/**
|
||||
* Parses a token and returns a node.
|
||||
*
|
||||
* @param Twig_Token $token A Twig_Token instance
|
||||
*
|
||||
* @return Twig_NodeInterface A Twig_NodeInterface instance
|
||||
*/
|
||||
public function parse(Twig_Token $token)
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
$stream = $this->parser->getStream();
|
||||
$name = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
$capture = false;
|
||||
if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
|
||||
$stream->next();
|
||||
$value = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
||||
} else {
|
||||
$capture = true;
|
||||
|
||||
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
||||
|
||||
$value = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
|
||||
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
||||
}
|
||||
|
||||
return new phpbb_template_twig_node_define($capture, $name, $value, $lineno, $this->getTag());
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Twig_Token $token)
|
||||
{
|
||||
return $token->test('ENDDEFINE');
|
||||
|
|
|
@ -261,14 +261,8 @@ class phpbb_template_twig implements phpbb_template
|
|||
return $result[0];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->twig->display($this->filenames[$handle], $this->get_template_vars());
|
||||
}
|
||||
catch (Twig_Error $e)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
$context = &$this->get_template_vars();
|
||||
$this->twig->display($this->filenames[$handle], $context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -454,7 +448,10 @@ class phpbb_template_twig implements phpbb_template
|
|||
$vars = array_merge(
|
||||
$vars,
|
||||
$this->context->get_rootref(),
|
||||
$this->context->get_tpldata()
|
||||
$this->context->get_tpldata(),
|
||||
array(
|
||||
'definition' => new phpbb_template_twig_definition(),
|
||||
)
|
||||
);
|
||||
|
||||
// cleanup
|
||||
|
|
Loading…
Add table
Reference in a new issue