- improvement convert template inheritance into runtime processing

- bugfix {$smarty.block.parent} did always reference the root parent block https://github.com/smarty-php/smarty/issues/68
This commit is contained in:
uwetews
2015-09-01 01:54:28 +02:00
parent 54d54e5000
commit 620e52405b
17 changed files with 1415 additions and 1911 deletions

View File

@@ -1,3 +1,39 @@
Starting with version 3.1.28 template inheritance is no longer a compile time process.
All {block} tag parent/child relations are resolved at run time.
This does resolve all known existing restrictions (see below).
The $smarty::$inheritance_merge_compiled_includes property has been removed.
Any access to it is ignored.
This does enable some new features:
Any code outside root {block} tags in child templates is now executed but any output will be ignored.
{extends 'foo.tpl}
{$bar = 'on'} // assigns variable $bar seen in parent templates
{block 'buh'}{/block}
{extends 'foo.tpl}
{$bar} // the output of variable bar is ignored
{block 'buh'}{/block}
{block} tags can be dynamically en/disabled by conditions.
{block 'root}
{if $foo}
{block 'v1}
....
{/block}
{else}
{block 'v1}
....
{/block}
{/if}
{/block}
THE FOLLOWING RESTRICTIONS ARE NO LONGER EXISTING:
In Smarty 3.1 template inheritance is a compile time process. All the extending of {block} tags
is done at compile time and the parent and child templates are compiled in a single compiled template.
{include} subtemplate could also {block} tags. Such subtemplate could not compiled by it's own because
@@ -29,7 +65,3 @@ You must now manually merge all {include} subtemplate which do contain {block} t
3. If call templates with different template_dir configurations and a parent could same named child template from different folders
you must make the folder name part of the compile_id.
In the upcomming major release Smarty 3.2 inheritance will no longer be a compile time process.
All restrictions will be then removed.

View File

@@ -4,13 +4,18 @@ This file contains a brief description of new features which have been added to
Smarty 3.1.28
Template inheritance
====================
Template inheritance is now processed in run time.
See the INHERITANCE_RELEASE_NOTES
Modifier regex_replace
======================
An optional limit parameter was added
fetch() and display()
=====================
The fetch() and display() methods of the template object accept now optionally the same paramter
The fetch() and display() methods of the template object accept now optionally the same parameter
as the corresponding Smarty methods the get tne content of another template.
File: resource

View File

@@ -1,8 +1,10 @@
#Smarty 3 template engine
##Distribution repository
*Read the NEW_FEATURES file for recent extensions to Smarty 3.1 functionality*
```
* Smarty 3.1.28 introduces run time template inheritance *
*Read the NEW_FEATURES and INHERITANCE_RELEASE_NOTES file for recent extensions to Smarty 3.1 functionality*
```
Smarty versions 3.1.11 or later are now on github and can be installed with Composer.

View File

@@ -1,4 +1,8 @@
 ===== 3.1.28-dev===== (xx.xx.2015)
01.09.2015
- improvement convert template inheritance into runtime processing
- bugfix {$smarty.block.parent} did always reference the root parent block https://github.com/smarty-php/smarty/issues/68
23.08.2015
- introduce Smarty::$resource_cache_mode and cache template object of {include} inside loop
- load seldom used Smarty API methods dynamically to reduce memory footprint

View File

@@ -1,11 +1,11 @@
<?php
/**
* Smarty Internal Plugin Templatelexer
* This is the lexer to break the template source into tokens
/*
* This file is part of Smarty.
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
@@ -13,9 +13,8 @@
* This is the template file lexer.
* It is generated from the smarty_internal_templatelexer.plex file
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Templatelexer
{
@@ -25,84 +24,98 @@ class Smarty_Internal_Templatelexer
* @var string
*/
public $data;
/**
* byte counter
*
* @var int
*/
public $counter;
/**
* token number
*
* @var int
*/
public $token;
/**
* token value
*
* @var string
*/
public $value;
/**
* current line
*
* @var int
*/
public $line;
/**
* tag start line
*
* @var
*/
public $taglineno;
/**
* php code type
*
* @var string
*/
public $phpType = '';
/**
* escaped left delimiter
*
* @var string
*/
public $ldel = '';
/**
* escaped left delimiter length
*
* @var int
*/
public $ldel_length = 0;
/**
* escaped right delimiter
*
* @var string
*/
public $rdel = '';
/**
* escaped right delimiter length
*
* @var int
*/
public $rdel_length = 0;
/**
* state number
*
* @var int
*/
public $state = 1;
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* compiler object
*
* @var Smarty_Internal_TemplateCompilerBase
*/
public $compiler = null;
/**
* literal tag nesting level
*
@@ -142,8 +155,7 @@ class Smarty_Internal_Templatelexer
*
* @var array
*/
public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',
6 => 'CHILDBODY', 7 => 'CHILDBLOCK', 8 => 'CHILDLITERAL');
public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',);
/**
* storage for assembled token patterns
@@ -160,12 +172,6 @@ class Smarty_Internal_Templatelexer
private $yy_global_pattern5 = null;
private $yy_global_pattern6 = null;
private $yy_global_pattern7 = null;
private $yy_global_pattern8 = null;
/**
* token names
*
@@ -404,7 +410,7 @@ class Smarty_Internal_Templatelexer
ldel dollar id nocacherdel {
if ($this->_yy_stack[count($this->_yy_stack)-1] == self::TEXT) {
$this->yypopstate();
$this->token = Smarty_Internal_Templateparser::TP_SIMPLEOUTPUT;
$this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT;
$this->taglineno = $this->line;
} else {
$this->value = $this->smarty->left_delimiter;
@@ -661,115 +667,6 @@ class Smarty_Internal_Templatelexer
$this->token = Smarty_Internal_Templateparser::TP_TEXT;
}
*/
/*!lex2php
%statename CHILDBODY
ldel strip rdel {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
return false;
} else {
$this->token = Smarty_Internal_Templateparser::TP_STRIPON;
}
}
ldel slash strip rdel {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
return false;
} else {
$this->token = Smarty_Internal_Templateparser::TP_STRIPOFF;
}
}
ldel block {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
return false;
} else {
$this->yypopstate();
return true;
}
}
text {
$to = strlen($this->data);
preg_match("~SMARTYldel\s*(([/])?strip\s*SMARTYrdel|block\s+)~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
return false;
}
*/
/*!lex2php
%statename CHILDBLOCK
ldel literal rdel {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypushstate(self::CHILDLITERAL);
}
}
ldel block {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
ldel slash block {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
ldel smartyblockchildparent {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
text {
$to = strlen($this->data);
preg_match("~SMARTYldel\s*(literal\s*SMARTYrdel|([/])?block(\s|SMARTYrdel)|[\$]smarty\.block\.(child|parent))~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
}
*/
/*!lex2php
%statename CHILDLITERAL
ldel literal rdel {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypushstate(self::CHILDLITERAL);
}
}
ldel slash literal rdel {
if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypopstate();
}
}
text {
$to = strlen($this->data);
preg_match("~{$this->ldel}[/]?literal\s*{$this->rdel}~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
} else {
$this->compiler->trigger_template_error ("missing or misspelled literal closing tag");
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
}
*/
}

View File

@@ -1,24 +1,21 @@
/**
* Smarty Internal Plugin Templateparser
*
* This is the template parser
*
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/*
* This file is part of Smarty.
*
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
%stack_size 500
%name TP_
%declare_class {
/**
* Smarty Internal Plugin Templateparser
* Smarty Template Parser Class
*
* This is the template parser.
* It is generated from the smarty_internal_templateparser.y file
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Templateparser
}
@@ -161,10 +158,10 @@ class Smarty_Internal_Templateparser
{
$tmp ='';
foreach ($this->compiler->prefix_code as $preCode) {
$tmp = empty($tmp) ? $preCode : $this->compiler->appendCode($tmp, $preCode);
$tmp .= $preCode;
}
$this->compiler->prefix_code=array();
$tmp = empty($tmp) ? $code : $this->compiler->appendCode($tmp, $code);
$tmp .= $code;
return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp,true));
}
@@ -199,6 +196,7 @@ class Smarty_Internal_Templateparser
// complete template
//
start(res) ::= template. {
$this->compiler->processInheritance($this);
res = $this->root_buffer->to_smarty_php($this);
}
@@ -255,9 +253,9 @@ template_element(res)::= PHP(o). {
// nocache code
template_element(res)::= NOCACHE(c). {
$this->compiler->tag_nocache = true;
$save = $this->template->has_nocache_code;
$save = $this->template->compiled->has_nocache_code;
res = new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode("<?php echo '{c}';?>\n", $this->compiler, true));
$this->template->has_nocache_code = $save;
$this->template->compiled->has_nocache_code = $save;
}
// template text
template_element(res)::= text_content(t). {
@@ -280,14 +278,6 @@ template_element ::= STRIPON(d). {
template_element ::= STRIPOFF(d). {
$this->strip = false;
}
// process source of inheritance child block
template_element ::= BLOCKSOURCE(s). {
if ($this->strip) {
SMARTY_INTERNAL_COMPILE_BLOCK::blockSource($this->compiler, preg_replace('![\t ]*[\r\n]+[\t ]*!', '', s));
} else {
SMARTY_INTERNAL_COMPILE_BLOCK::blockSource($this->compiler, s);
}
}
// Litteral
literal(res) ::= LITERALSTART LITERALEND. {
@@ -320,7 +310,7 @@ smartytag(res) ::= tag(t) RDEL. {
//
// output tags start here
//
smartytag(res) ::= SIMPLEOUTPUT(i). {
smartytag(res) ::= SIMPELOUTPUT(i). {
$var = trim(substr(i, $this->lex->ldel_length, -$this->lex->rdel_length), ' $');
if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) {
res = $this->compiler->compileTag('private_print_expression',array('nocache'),array('value'=>$this->compiler->compileVariable('\''.$match[1].'\'')));
@@ -334,18 +324,26 @@ tag(res) ::= LDEL variable(e). {
res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e));
}
tag(res) ::= LDEL variable(e) modifierlist(l) attributes(a). {
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e, 'modifierlist'=>l));
}
tag(res) ::= LDEL variable(e) attributes(a). {
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e));
}
tag(res) ::= LDEL value(e). {
res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e));
}
tag(res) ::= LDEL value(e) modifierlist(l) attributes(a). {
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e, 'modifierlist'=>l));
}
tag(res) ::= LDEL value(e) attributes(a). {
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e));
}
tag(res) ::= LDEL expr(e). {
res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e));
tag(res) ::= LDEL expr(e) modifierlist(l) attributes(a). {
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e,'modifierlist'=>l));
}
tag(res) ::= LDEL expr(e) attributes(a). {
@@ -940,6 +938,7 @@ indexdef(res) ::= DOT INTEGER(n). {
res = '['. n .']';
}
indexdef(res) ::= DOT LDEL expr(e) RDEL. {
res = '['. e .']';
}
@@ -1001,6 +1000,10 @@ varvar(res) ::= varvar(v1) varvarele(v2). {
varvarele(res) ::= ID(s). {
res = '\''.s.'\'';
}
varvarele(res) ::= SIMPELOUTPUT(i). {
$var = trim(substr(i, $this->lex->ldel_length, -$this->lex->rdel_length), ' $');
res = $this->compiler->compileVariable('\''.$var.'\'');
}
// variable sections of element
varvarele(res) ::= LDEL expr(e) RDEL. {

View File

@@ -1,25 +1,20 @@
<?php
/**
* Smarty Internal Plugin Compile Block
* Compiles the {block}{/block} tags
/*
* This file is part of Smarty.
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Smarty Internal Plugin Compile Block Class
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
{
const parent = '____SMARTY_BLOCK_PARENT____';
/**
* Attribute definition: Overwrites base class.
*
@@ -42,173 +37,76 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array('hide', 'append', 'prepend', 'nocache');
public $option_flags = array('hide', 'nocache');
/**
* nested child block names
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public static $nested_block_names = array();
public $optional_attributes = array();
/**
* child block source buffer
* nesting level of block tags
*
* @var array
* @var int
*/
public static $block_data = array();
public static $blockTagNestingLevel = 0;
/**
* Compiles code for the {block} tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
if ($compiler->blockTagNestingLevel == 0 && $compiler->template->isChild) {
$this->option_flags = array('hide', 'nocache', 'append', 'prepend');
} else {
$this->option_flags = array('hide', 'nocache');
}
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$_name = trim($_attr['name'], "\"'");
// existing child must override parent settings
if (isset($compiler->template->block_data[$_name]) &&
$compiler->template->block_data[$_name]['mode'] == 'replace'
) {
$_attr['append'] = false;
$_attr['prepend'] = false;
$compiler->blockTagNestingLevel ++;
$this->openTag($compiler, 'block', array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
$compiler->template->compiled->has_nocache_code,
$compiler->template->caching));
// must whole block be nocache ?
if ($compiler->tag_nocache) {
$i = 0;
}
// check if we process an inheritance child template
if ($compiler->inheritance_child) {
array_unshift(self::$nested_block_names, $_name);
// build {block} for child block
self::$block_data[$_name]['source'] = "{$compiler->smarty->left_delimiter}private_child_block name={$_attr['name']} uid='{$compiler->template->source->uid}' line={$compiler->parser->lex->line}";
if ($_attr['nocache']) {
self::$block_data[$_name]['source'] .= ' nocache';
}
self::$block_data[$_name]['source'] .= $compiler->smarty->right_delimiter;
// save source object
$compiler->cache["source_{$compiler->template->source->uid}"] = $compiler->template->source;
$save = array($_attr, $compiler->inheritance);
$this->openTag($compiler, 'block', $save);
// set flag for {block} tag
$compiler->inheritance = true;
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return null;
}
// must merge includes
if ($_attr['nocache'] == true) {
$compiler->tag_nocache = true;
}
$save = array($_attr, $compiler->inheritance, $compiler->parser->current_buffer, $compiler->nocache);
$this->openTag($compiler, 'block', $save);
$compiler->inheritance = true;
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
// $compiler->suppressNocacheProcessing = true;
if ($_attr['nocache'] === true) {
//$compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->taglineno);
}
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->has_code = false;
return true;
$compiler->template->compiled->has_nocache_code = false;
$compiler->suppressNocacheProcessing = true;
}
/**
* Compile saved child block source
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param \Smarty_Internal_TemplateCompilerBase compiler object
* @param string $_name optional name of child block
*
* @return string compiled code of child block
* @throws \SmartyCompilerException
*/
static function compileChildBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
{
if ($compiler->inheritance_child) {
$name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
if (isset($compiler->template->block_data[$name1])) {
// replace inner block name with generic
Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= $compiler->template->block_data[$name1]['source'];
Smarty_Internal_Compile_Block::$block_data[$name1]['child'] = true;
if (!$compiler->blockTagNestingLevel) {
$compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->parser->lex->taglineno);
}
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return null;
}
// if called by {$smarty.block.child} we must search the name of enclosing {block}
if ($_name == null) {
$stack_count = count($compiler->_tag_stack);
while (-- $stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
}
}
}
if ($_name == null) {
$compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', null, true);
}
// undefined child?
if (!isset($compiler->template->block_data[$_name]['source'])) {
$compiler->popTrace();
return '';
}
// flag that child is already compile by {$smarty.block.child} inclusion
$compiler->template->block_data[$_name]['compiled'] = true;
$_tpl = new Smarty_Internal_template('string:' .
$compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id, $compiler->template->compile_id, $compiler->template->caching, $compiler->template->cache_lifetime);
if ($compiler->smarty->debugging) {
$compiler->smarty->_debug->ignore($_tpl);
}
$_tpl->tpl_vars = $compiler->template->tpl_vars;
$_tpl->compiled = new Smarty_Template_Compiled();
$_tpl->compiled->nocache_hash = $compiler->template->compiled->nocache_hash;
$_tpl->_cache['allow_relative_path'] = true;
$_tpl->loadCompiler();
$_tpl->compiler->variable_filters = $compiler->variable_filters;
$_tpl->compiler->parent_compiler = $compiler;
$_tpl->compiler->_tag_objects = $compiler->_tag_objects;
$_tpl->compiler->inheritance = true;
$_tpl->compiler->suppressHeader = true;
$_tpl->compiler->suppressFilter = true;
$_tpl->compiler->suppressTemplatePropertyHeader = true;
$nocache = $compiler->nocache || $compiler->tag_nocache;
$_output = '';
if (strpos($compiler->template->block_data[$_name]['source'], self::parent) !== false) {
$_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php($compiler->parser), $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler));
} elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler) .
$compiler->parser->current_buffer->to_smarty_php($compiler->parser);
} elseif ($compiler->template->block_data[$_name]['mode'] == 'append') {
$_output = $compiler->parser->current_buffer->to_smarty_php($compiler->parser) .
$_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
} elseif (!empty($compiler->template->block_data[$_name])) {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
}
$compiler->template->compiled->file_dependency = array_merge($compiler->template->compiled->file_dependency, $_tpl->compiled->file_dependency);
unset($compiler->template->compiled->file_dependency[$_tpl->source->uid]);
$compiler->template->tpl_function = array_merge($compiler->template->tpl_function, $_tpl->tpl_function);
$compiler->variable_filters = $_tpl->compiler->variable_filters;
if ($_tpl->compiled->has_nocache_code) {
$compiler->template->compiled->has_nocache_code = true;
}
foreach ($_tpl->compiled->required_plugins as $key => $tmp1) {
if ($compiler->nocache && $compiler->template->caching) {
$code = 'nocache';
} else {
$code = $key;
}
foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins[$code][$name][$type] = $data;
}
}
}
$compiler->_tag_objects = $_tpl->compiler->_tag_objects;
unset($_tpl);
$compiler->has_code = true;
$compiler->suppressNocacheProcessing = true;
$compiler->callChildBlock[$compiler->blockTagNestingLevel] = true;
$_output = "<?php \n\$_smarty_tpl->_Block->callChildBlock(\$_smarty_tpl, \$block);?>";
return $_output;
}
@@ -219,49 +117,25 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
* @param string $_name optional name of child block
*
* @return string compiled code of child block
* @throws \SmartyCompilerException
*/
static function compileParentBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
{
// if called by {$smarty.block.parent} we must search the name of enclosing {block}
if ($_name == null) {
$stack_count = count($compiler->_tag_stack);
while (-- $stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
if (!$compiler->template->isChild) {
$compiler->trigger_template_error(' tag {$smarty.block.parent} used in parent template ', $compiler->parser->lex->taglineno);
}
if (!$compiler->blockTagNestingLevel) {
$compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->parser->lex->taglineno);
}
}
if ($_name == null) {
$compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', null, true);
}
if (empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
$compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', null, true);
}
Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block::parent;
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return;
}
/**
* Process block source
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param string $source source text
*/
static function blockSource(Smarty_Internal_TemplateCompilerBase $compiler, $source)
{
Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= $source;
$compiler->suppressNocacheProcessing = true;
$compiler->has_code = true;
$_output = "<?php \n\$_smarty_tpl->_Block->callParentBlock(\$_smarty_tpl, \$block);?>";
return $_output;
}
}
/**
* Smarty Internal Plugin Compile BlockClose Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase
{
@@ -270,180 +144,105 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
$this->compiler = $compiler;
list($_attr, $_nocache, $_buffer, $_has_nocache_code, $_caching) = $this->closeTag($compiler, array('block'));
$_name = trim($_attr['name'], "'\"");
$_functionCode = $compiler->parser->current_buffer;
// setup buffer for template function code
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$_funcNameCaching = $_funcName = preg_replace('![^\w]+!', '_', "block_function_{$_name}_" .
uniqid(rand(), true));
if ($compiler->template->compiled->has_nocache_code) {
// $compiler->parent_compiler->template->tpl_function[$_name]['call_name_caching'] = $_funcNameCaching;
$_funcNameCaching .= '_nocache';
$output = "<?php\n";
$output .= "/* {$_funcNameCaching} {$compiler->template->source->type}:{$compiler->template->source->name} */\n";
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
$output .= "function {$_funcNameCaching} (\$_smarty_tpl, \$block) {\n";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
$output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php /*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
$output .= "\n}\n}\n";
$output .= "/*/ {$_funcName}_nocache */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parent_compiler->templateFunctionCode .= $f = $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser, preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", array($this,
'removeNocache'), $_functionCode->to_smarty_php($compiler->parser)));
}
$output = "<?php\n";
$output .= "/* {$_funcName} {$compiler->template->source->type}:{$compiler->template->source->name} */\n";
$output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(\$_smarty_tpl, \$block) {?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php\n}\n}\n";
$output .= "/*/ {$_funcName} */\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parent_compiler->templateFunctionCode .= $f = $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
// nocache plugins must be copied
if (!empty($compiler->template->compiled->required_plugins['nocache'])) {
foreach ($compiler->template->compiled->required_plugins['nocache'] as $plugin => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins['compiled'][$plugin][$type] = $data;
}
}
}
// restore old status
$compiler->template->compiled->has_nocache_code = $_has_nocache_code;
$compiler->tag_nocache = $compiler->nocache;
$compiler->nocache = $_nocache;
$compiler->parser->current_buffer = $_buffer;
$_parameter = $_attr;
foreach ($_parameter as $name => $stat) {
if ($stat === false) {
unset($_parameter[$name]);
}
}
if (isset($compiler->callChildBlock[$compiler->blockTagNestingLevel])) {
$_parameter['callChildBlock'] = 'true';
unset($compiler->callChildBlock[$compiler->blockTagNestingLevel]);
}
$compiler->blockTagNestingLevel --;
if ($compiler->blockTagNestingLevel == 0 && $compiler->template->isChild) {
$_function = 'register';
} else {
$_function = 'call';
}
$cm = $compiler->template->caching ? 'true' : 'false';
$output = "<?php \n\$_smarty_tpl->_Block->{$_function}Block(\$_smarty_tpl, array('caching' => {$cm}, 'function' => '{$_funcNameCaching}'";
foreach ($_parameter as $name => $stat) {
if ($stat !== false) {
$output .= ", '{$name}' => {$stat}";
}
}
$output .= "));\n?>\n";
$compiler->has_code = true;
$saved_data = $this->closeTag($compiler, array('block'));
$_name = trim($saved_data[0]['name'], "\"'");
// reset flag for {block} tag
$compiler->inheritance = $saved_data[1];
// check if we process an inheritance child template
if ($compiler->inheritance_child) {
$name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}";
array_shift(Smarty_Internal_Compile_Block::$nested_block_names);
if (!empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
$name2 = Smarty_Internal_Compile_Block::$nested_block_names[0];
if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
if (isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child']) ||
!isset($compiler->template->block_data[$name1])
) {
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
} else {
if ($compiler->template->block_data[$name1]['mode'] == 'append') {
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .
$compiler->template->block_data[$name1]['source'];
} elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'] .
Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
} else {
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'];
}
}
}
unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
} else {
if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
if (isset($compiler->template->block_data[$name1]) &&
!isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child'])
) {
if (strpos($compiler->template->block_data[$name1]['source'], Smarty_Internal_Compile_Block::parent) !==
false
) {
$compiler->template->block_data[$name1]['source'] = str_replace(Smarty_Internal_Compile_Block::parent, Smarty_Internal_Compile_Block::$block_data[$name1]['source'], $compiler->template->block_data[$name1]['source']);
} elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
$compiler->template->block_data[$name1]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
} elseif ($compiler->template->block_data[$name1]['mode'] == 'append') {
$compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .
$compiler->template->block_data[$name1]['source'];
}
} else {
$compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
}
$compiler->template->block_data[$name1]['mode'] = 'replace';
if ($saved_data[0]['append']) {
$compiler->template->block_data[$name1]['mode'] = 'append';
}
if ($saved_data[0]['prepend']) {
$compiler->template->block_data[$name1]['mode'] = 'prepend';
}
}
unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
}
$compiler->has_code = false;
return null;
}
if (isset($compiler->template->block_data[$_name]) &&
!isset($compiler->template->block_data[$_name]['compiled'])
) {
$_output = Smarty_Internal_Compile_Block::compileChildBlock($compiler, $_name);
} else {
if ($saved_data[0]['hide'] && !isset($compiler->template->block_data[$_name]['source'])) {
$_output = '';
} else {
$_output = $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
}
}
if (isset($compiler->template->block_data[$_name]['compiled'])) {
unset($compiler->template->block_data[$_name]['compiled']);
}
// reset flags
$compiler->parser->current_buffer = $saved_data[2];
if ($compiler->nocache) {
$compiler->tag_nocache = true;
}
$compiler->nocache = $saved_data[3];
// $_output content has already nocache code processed
$compiler->suppressNocacheProcessing = true;
return $_output;
return $output;
}
}
/**
* Smarty Internal Plugin Compile Child Block Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_Child_Block extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
* @param $match
*
* @var array
* @see Smarty_Internal_CompileBase
* @return mixed
*/
public $required_attributes = array('name', 'uid', 'line');
/**
* Compiles code for the {private_child_block} tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
*
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
function removeNocache($match)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$uid = trim($_attr['uid'], "\"'");
// update template with original template source of {block}
$compiler->template->source = $compiler->parent_compiler->cache["source_{$uid}"];
// must merge includes
if ($_attr['nocache'] == true) {
$compiler->tag_nocache = true;
}
$save = array($_attr, $compiler->nocache);
// set trace back to child block
$compiler->pushTrace($compiler->template->source->filepath, $uid, $_attr['line'] -
$compiler->parser->lex->line);
$this->openTag($compiler, 'private_child_block', $save);
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$compiler->has_code = false;
return true;
}
}
/**
* Smarty Internal Plugin Compile Child Block Close Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_Child_Blockclose extends Smarty_Internal_CompileBase
{
/**
* Compiles code for the {/private_child_block} tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
*
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{
$saved_data = $this->closeTag($compiler, array('private_child_block'));
// end of child block
$compiler->popTrace();
$compiler->nocache = $saved_data[1];
$compiler->has_code = false;
return true;
$code = preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", '', $match[0]);
$code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code);
return $code;
}
}

View File

@@ -48,48 +48,14 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', null, true);
$compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1);
}
if (strpos($_attr['file'], '$_tmp') !== false) {
$compiler->trigger_template_error('illegal value for file attribute', null, true);
$compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1);
}
$name = $_attr['file'];
if ($compiler->has_variable_string || !((substr_count($name, '"') == 2 || substr_count($name, "'") == 2)) ||
substr_count($name, '(') != 0 || substr_count($name, '$_smarty_tpl->') != 0
) {
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = @{$name};");
} else {
$tpl_name = trim($name, '\'"');
}
// create source object
$_source = Smarty_Template_Source::load(null, $compiler->smarty, $tpl_name);
// check for recursion
$uid = $_source->uid;
if (isset($compiler->extends_uid[$uid])) {
$compiler->trigger_template_error("illegal recursive call of \"{$_source->filepath}\"", $compiler->parser->lex->line -
1);
}
$compiler->extends_uid[$uid] = true;
if (empty($_source->components)) {
array_unshift($compiler->sources, $_source);
} else {
foreach ($_source->components as $source) {
array_unshift($compiler->sources, $source);
$uid = $source->uid;
if (isset($compiler->extends_uid[$uid])) {
$compiler->trigger_template_error("illegal recursive call of \"{$source->filepath}\"", $compiler->parser->lex->line -
1);
}
$compiler->extends_uid[$uid] = true;
}
}
$compiler->inheritance_child = true;
$compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
$compiler->extendsFileName = $_attr['file'];
$compiler->template->isChild = true;
$compiler->has_code = false;
return '';
}
}

View File

@@ -65,6 +65,9 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
*/
public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter)
{
if (!isset($parameter['isChild'])) {
$parameter['isChild'] = false;
}
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
@@ -117,9 +120,8 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
// flag if included template code should be merged into caller
$merge_compiled_includes = ($compiler->smarty->merge_compiled_includes ||
($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) ||
$_attr['inline'] === true) && !$compiler->template->source->handler->recompiled;
$merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr['inline'] === true) &&
!$compiler->template->source->handler->recompiled;
if ($merge_compiled_includes && $_attr['inline'] !== true) {
// variable template name ?
@@ -129,11 +131,6 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
// must use individual cache file
//$_attr['caching'] = 1;
}
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes &&
$_attr['inline'] !== true
) {
$compiler->trigger_template_error(' variable template file names not allow within {block} tags');
}
}
// variable compile_id?
if (isset($_attr['compile_id'])) {
@@ -146,11 +143,6 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
// must use individual cache file
//$_attr['caching'] = 1;
}
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes &&
$_attr['inline'] !== true
) {
$compiler->trigger_template_error(' variable compile_id not allow within {block} tags');
}
}
}
}
@@ -194,17 +186,9 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$has_compiled_template = false;
if ($merge_compiled_includes) {
if ($compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache) &&
$_caching != self::CACHING_NOCACHE_CODE
) {
// $merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) {
$compiler->trigger_template_error(' invalid caching mode of subtemplate within {block} tags');
}
}
$c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id;
// we must observe different compile_id and caching
$uid = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$tpl_name = null;
/** @var Smarty_Internal_Template $_smarty_tpl
@@ -212,32 +196,40 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = @$include_file;");
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid])) {
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash])) {
$compiler->smarty->allow_ambiguous_resources = true;
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $c_id, $_caching);
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template,
$compiler->template->cache_id, $c_id, $_caching);
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['uid'] = $tpl->source->uid;
if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) {
$tpl->compiled = new Smarty_Template_Compiled();
$tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash;
$tpl->loadCompiler();
$tpl->isChild = $parameter['isChild'];
// save unique function name
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func'] = $tpl->compiled->unifunc = 'content_' .
str_replace(array('.', ','), '_', uniqid('', true));
if ($compiler->inheritance) {
$tpl->compiler->inheritance = true;
}
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func'] =
$tpl->compiled->unifunc = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
// make sure whole chain gets compiled
$tpl->mustCompile = true;
$tpl->compiler->suppressTemplatePropertyHeader = true;
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash'] = $tpl->compiled->nocache_hash;
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['nocache_hash'] =
$tpl->compiled->nocache_hash;
// get compiled code
$compiled_code = Smarty_Internal_Extension_CodeFrame::createFunctionFrame($tpl, $tpl->compiler->compileTemplate($tpl, null, $compiler->parent_compiler));
$compiled_code = Smarty_Internal_Extension_CodeFrame::createFunctionFrame($tpl,
$tpl->compiler->compileTemplate($tpl,
null,
$compiler->parent_compiler));
unset($tpl->compiler);
// remove header code
$compiled_code = preg_replace("/(<\?php \/\*%%SmartyHeaderCode:{$tpl->compiled->nocache_hash}%%\*\/(.+?)\/\*\/%%SmartyHeaderCode%%\*\/\?>\n)/s", '', $compiled_code);
$compiled_code =
preg_replace("/(<\?php \/\*%%SmartyHeaderCode:{$tpl->compiled->nocache_hash}%%\*\/(.+?)\/\*\/%%SmartyHeaderCode%%\*\/\?>\n)/s",
'', $compiled_code);
if ($tpl->compiled->has_nocache_code) {
// replace nocache_hash
$compiled_code = str_replace("{$tpl->compiled->nocache_hash}", $compiler->template->compiled->nocache_hash, $compiled_code);
$compiled_code =
str_replace("{$tpl->compiled->nocache_hash}", $compiler->template->compiled->nocache_hash,
$compiled_code);
$compiler->template->compiled->has_nocache_code = true;
}
$compiler->parent_compiler->mergedSubTemplatesCode[$tpl->compiled->unifunc] = $compiled_code;
@@ -268,7 +260,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$_vars = 'array()';
}
$this->logInclude($compiler, $include_file, $variable_template);
$_isChild = var_export($parameter['isChild'], true);
$update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
$_compile_id != '$_smarty_tpl->compile_id';
if ($has_compiled_template && !$call_nocache) {
@@ -283,10 +275,10 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
if (isset($_assign)) {
$_output .= "ob_start();\n";
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, {$_isChild}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func']}');\n";
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
} else {
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, {$_isChild}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func']}');\n";
}
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
@@ -330,13 +322,14 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
if ($variable_template) {
return;
}
list($name, $type) = Smarty_Resource::parseResourceName(trim($include_file, '\'"'), $compiler->template->smarty->default_resource_type);
list($name, $type) = Smarty_Resource::parseResourceName(trim($include_file, '\'"'),
$compiler->template->smarty->default_resource_type);
if (in_array($type, array('eval', 'string'))) {
return;
}
$include_name = $type . ':' . $name;
$compiled = $compiler->parent_compiler->template->compiled;
$compiled->includes[$include_name] = isset($compiled->includes[$include_name]) ? $compiled->includes[$include_name] +
1 : 1;
$compiled->includes[$include_name] =
isset($compiled->includes[$include_name]) ? $compiled->includes[$include_name] + 1 : 1;
}
}

View File

@@ -192,20 +192,7 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
*/
public function matchBlockSource(Smarty_Internal_TemplateCompilerBase $compiler)
{
foreach ($compiler->template->block_data as $b) {
if (isset($b['source'])) {
$this->matchProperty($b['source']);
}
}
if (class_exists('Smarty_Internal_Compile_Block', false)) {
foreach (Smarty_Internal_Compile_Block::$block_data as $b) {
if (isset($b['source'])) {
$this->matchProperty($b['source']);
}
}
}
$this->matchProperty($compiler->parser->lex->data);
}
/**

View File

@@ -35,6 +35,7 @@ class Smarty_Internal_Extension_CodeFrame
if (!$cache) {
$properties['file_dependency'] = $_template->compiled->file_dependency;
$properties['includes'] = $_template->compiled->includes;
$properties['isChild'] = $_template->isChild;
} else {
$properties['file_dependency'] = $_template->cached->file_dependency;
$properties['cache_lifetime'] = $_template->cache_lifetime;

View File

@@ -73,10 +73,6 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom
if ($isTemplateSource) {
$this->parser->insertPhpCode("<?php\n\$_smarty_tpl->compiled->nocache_hash = '{$this->nocache_hash}';\n?>\n");
}
if ($this->inheritance_child) {
// start state on child templates
$this->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
}
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('ASCII');

View File

@@ -77,6 +77,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public $tpl_function = array();
/**
* Template is inheritance child template
*
* @var bool
*/
public $isChild = false;
/**
* Create template data object
* Some of the global Smarty settings copied to template scope
@@ -292,10 +299,16 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
* @return string template content
* @throws \SmartyException
*/
public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj)
public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $isChild)
{
$tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj);
$tpl->isChild = $isChild;
$tpl->render();
if ($tpl->isChild && !isset($this->_Block) && isset($tpl->_Block) &&
($this->isChild || !empty($this->source->components))
) {
$this->_Block = $tpl->_Block;
}
}
/**
@@ -309,6 +322,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
* @param array $data passed parameter template variables
* @param int $parent_scope scope in which {include} should execute
* @param bool $cache_tpl_obj cache template object
* @param bool $isChild flag if subtemplate is an inheritance child
*
* @return \Smarty_Internal_Template template object
*/
@@ -332,6 +346,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
} else {
$tpl = clone $this;
$tpl->parent = $this;
$tpl->isChild = false;
if ($tpl->templateId !== $_templateId) {
$tpl->templateId = $_templateId;
$tpl->template_resource = $template;
@@ -383,12 +398,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
* @param array $data passed parameter template variables
* @param int $parent_scope scope in which {include} should execute
* @param bool $cache_tpl_obj cache template object
* @param bool $isChild flag if subtemplate is an inheritance child
* @param string $content_func name of content function
*
* @return string template content
* @throws \Exception
*/
public function getInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $content_func)
public function getInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $isChild, $content_func)
{
$tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj);
if (!isset($tpl->compiled)) {
@@ -397,6 +413,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$tpl->cacheTpl(true);
}
}
$tpl->isChild = $isChild;
if ($this->smarty->debugging) {
$this->smarty->_debug->start_template($tpl);
$this->smarty->_debug->start_render($tpl);
@@ -409,6 +426,11 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if ($caching == 9999 && $tpl->compiled->has_nocache_code) {
$this->cached->hashes[$tpl->compiled->nocache_hash] = true;
}
if (!isset($this->_Block) && $isChild && isset($tpl->_Block) &&
($this->isChild || !empty($this->source->components))
) {
$this->_Block = $tpl->_Block;
}
}
/**
@@ -516,6 +538,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$resource = $this->cached;
} else {
$this->mustCompile = !$is_valid;
$this->isChild = $properties['isChild'];
$resource = $this->compiled;
$resource->includes = isset($properties['includes']) ? $properties['includes'] : array();
}

View File

@@ -95,13 +95,6 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public $sources = array();
/**
* flag that we are inside {block}
*
* @var bool
*/
public $inheritance = false;
/**
* flag when compiling inheritance child template
*
@@ -327,12 +320,26 @@ abstract class Smarty_Internal_TemplateCompilerBase
public $variable_filters = array();
/**
* Loop nesting count
* Nesting count of looping tags like {foreach}, {for}, {section}, {while}
*
* @var int
*/
public $loopNesting = 0;
/**
* nesting level of block tags
*
* @var int
*/
public $blockTagNestingLevel = 0;
/**
* Flag if {$smarty.block.child} was called at $blockTagNestingLevel
*
* @var array
*/
public $callChildBlock = array();
/**
* Strip preg pattern
*
@@ -347,7 +354,6 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public $plugin_search_order = array('function', 'block', 'compiler', 'class');
/**
* method to compile a Smarty template
*
@@ -384,6 +390,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
// save template object in compiler class
$this->template = $template;
$this->savedSource = $this->template->source;
try {
if (isset($this->template->smarty->security_policy)) {
$this->php_handling = $this->template->smarty->security_policy->php_handling;
@@ -405,30 +412,16 @@ abstract class Smarty_Internal_TemplateCompilerBase
$template_header .= " compiled from \"" . $this->template->source->filepath . "\" */ ?>\n";
}
if (empty($this->template->source->components)) {
$this->sources = array($template->source);
} else {
// we have array of inheritance templates by extends: resource
$this->sources = array_reverse($template->source->components);
}
$loop = 0;
$_compiled_code = '';
// the $this->sources array can get additional elements while compiling by the {extends} tag
while ($this->template->source = array_shift($this->sources)) {
$this->smarty->_current_file = $this->template->source->filepath;
if ($this->smarty->debugging) {
$this->smarty->_debug->start_compile($this->template);
}
$no_sources = count($this->sources);
$this->parent_compiler->template->compiled->file_dependency[$this->template->source->uid] = array($this->template->source->filepath,
$this->template->source->getTimeStamp(),
$this->parent_compiler->template->compiled->file_dependency[$this->template->source->uid] =
array($this->template->source->filepath, $this->template->source->getTimeStamp(),
$this->template->source->type);
$loop ++;
if ($no_sources) {
$this->inheritance_child = true;
} else {
$this->inheritance_child = false;
}
// compile for child template?
$this->inheritance_child = $this->template->isChild;
// flag for nochache sections
$this->nocache = $nocache;
$this->tag_nocache = false;
@@ -436,24 +429,30 @@ abstract class Smarty_Internal_TemplateCompilerBase
$this->template->compiled->has_nocache_code = false;
$this->has_variable_string = false;
$this->prefix_code = array();
// get template source
if (!empty($this->template->source->components)) {
// we have array of inheritance templates by extends: resource
$this->sources = array_reverse($template->source->components);
$_content = '';
} else {
// get template source
$_content = $this->template->source->getContent();
}
if ($_content != '') {
// run pre filter if required
if ((isset($this->smarty->autoload_filters['pre']) ||
isset($this->smarty->registered_filters['pre'])) && !$this->suppressFilter
if ($_content != '' && ((isset($this->smarty->autoload_filters['pre']) ||
isset($this->smarty->registered_filters['pre'])) && !$this->suppressFilter)
) {
$_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template);
}
}
// call compiler
$_compiled_code = $this->doCompile($_content, true);
}
if ($this->smarty->debugging) {
$this->smarty->_debug->end_compile($this->template);
}
// free memory
$this->parser = null;
}
// restore source
$this->template->source = $this->savedSource;
$this->savedSource = null;
@@ -474,15 +473,17 @@ abstract class Smarty_Internal_TemplateCompilerBase
if ($this->suppressTemplatePropertyHeader) {
$_compiled_code .= $merged_code;
} else {
$_compiled_code = $template_header .
Smarty_Internal_Extension_CodeFrame::create($template, $_compiled_code) . $merged_code;
$_compiled_code =
$template_header . Smarty_Internal_Extension_CodeFrame::create($template, $_compiled_code) .
$merged_code;
}
if (!empty($this->templateFunctionCode)) {
// run post filter if required on compiled template code
if ((isset($this->smarty->autoload_filters['post']) ||
isset($this->smarty->registered_filters['post'])) && !$this->suppressFilter
) {
$_compiled_code .= Smarty_Internal_Filter_Handler::runFilter('post', $this->templateFunctionCode, $template);
$_compiled_code .= Smarty_Internal_Filter_Handler::runFilter('post', $this->templateFunctionCode,
$template);
} else {
$_compiled_code .= $this->templateFunctionCode;
}
@@ -507,6 +508,59 @@ abstract class Smarty_Internal_TemplateCompilerBase
return $_compiled_code;
}
/**
* Add code to call parent template on inheritance child templates
*
* @param $parser
*
* @throws \Smarty_Exception
*/
public function processInheritance($parser)
{
if (isset($this->extendsFileName)) {
// child did use {extends}
$name = $this->extendsFileName;
$this->extendsFileName = null;
if (!$this->inheritance_child) {
// drop any output of child templates
array_unshift($parser->current_buffer->subtrees,
new Smarty_Internal_ParseTree_Tag($parser, "<?php ob_start();?>\n"));
$parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser,
"<?php ob_end_clean();?>\n"));
}
$parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser,
$this->compileTag('include',
array($name,
array('scope' => 'parent'),
array('inline' => true)),
array('isChild' => $this->inheritance_child))));
return;
}
// template list of extends: resource ?
if (!empty($this->sources)) {
if (!$this->inheritance_child) {
// drop any output of child templates
$parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser,
"<?php ob_start();?>\n"));
}
while (!empty($this->sources)) {
$source = array_shift($this->sources);
if (!$this->inheritance_child && empty($this->sources)) {
// drop any output of child templates
$parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser,
"<?php ob_end_clean();?>\n"));
}
$parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser,
$this->compileTag('include',
array("'{$source->resource}'",
array('scope' => 'parent'),
array('inline' => true)),
array('isChild' => $this->inheritance_child ||
!empty($this->sources)))));
}
}
}
/**
* Compile Tag
* This is a call back from the lexer/parser
@@ -603,7 +657,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
) {
return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method);
} elseif (in_array($method, $this->smarty->registered_objects[$tag][3])) {
return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $method);
return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag,
$method);
} else {
// throw exception
$this->trigger_template_error('not allowed method "' . $method . '" in registered object "' .
@@ -631,15 +686,16 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (!is_array($function)) {
return $function($new_args, $this);
} elseif (is_object($function[0])) {
return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->{$function[1]}($new_args, $this);
return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->{$function[1]}($new_args,
$this);
} else {
return call_user_func_array($function, array($new_args, $this));
}
}
// compile registered function or block function
if ($plugin_type == Smarty::PLUGIN_FUNCTION || $plugin_type == Smarty::PLUGIN_BLOCK) {
return $this->callTagCompiler('private_registered_' .
$plugin_type, $args, $parameter, $tag);
return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter,
$tag);
}
}
}
@@ -676,8 +732,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (!isset($this->smarty->security_policy) ||
$this->smarty->security_policy->isTrustedTag($tag, $this)
) {
return $this->callTagCompiler('private_' . $plugin_type .
'_plugin', $args, $parameter, $tag, $function);
return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter,
$tag, $function);
}
}
}
@@ -711,13 +767,14 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (!is_array($function)) {
return $function($new_args, $this);
} elseif (is_object($function[0])) {
return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this);
return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args,
$this);
} else {
return call_user_func_array($function, array($new_args, $this));
}
} else {
return $this->callTagCompiler('private_registered_' .
$plugin_type, $args, $parameter, $tag);
return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter,
$tag);
}
}
}
@@ -728,7 +785,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_method'])) {
$method = $parameter['object_method'];
if (in_array($method, $this->smarty->registered_objects[$base_tag][3])) {
return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $method);
return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag,
$method);
} else {
// throw exception
$this->trigger_template_error('not allowed closing tag method "' . $method .
@@ -768,7 +826,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (!is_array($function)) {
return $function($args, $this);
} elseif (is_object($function[0])) {
return $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0][0]->$function[1]($args, $this);
return $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0][0]->$function[1]($args,
$this);
} else {
return call_user_func_array($function, array($args, $this));
}
@@ -859,8 +918,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
}
}
// compile this tag
return $this->_tag_objects[$tag] ===
false ? false : $this->_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);
return $this->_tag_objects[$tag] === false ? false :
$this->_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);
}
/**
@@ -876,17 +935,23 @@ abstract class Smarty_Internal_TemplateCompilerBase
$function = null;
if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
if (isset($this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type])) {
$function = $this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];
$function =
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];
} elseif (isset($this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type])) {
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type] = $this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type];
$function = $this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type] =
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type];
$function =
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];
}
} else {
if (isset($this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type])) {
$function = $this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];
$function =
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];
} elseif (isset($this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type])) {
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type] = $this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type];
$function = $this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type] =
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type];
$function =
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];
}
}
if (isset($function)) {
@@ -902,11 +967,15 @@ abstract class Smarty_Internal_TemplateCompilerBase
if (is_string($file)) {
if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['file'] = $file;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'] = $function;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['file'] =
$file;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name][$plugin_type]['function'] =
$function;
} else {
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['file'] = $file;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'] = $function;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['file'] =
$file;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name][$plugin_type]['function'] =
$function;
}
if ($plugin_type == 'modifier') {
$this->modifier_plugins[$plugin_name] = true;
@@ -935,19 +1004,22 @@ abstract class Smarty_Internal_TemplateCompilerBase
$callback = null;
$script = null;
$cacheable = true;
$result = call_user_func_array($this->smarty->default_plugin_handler_func, array($tag, $plugin_type,
$this->template, &$callback,
&$script, &$cacheable));
$result = call_user_func_array($this->smarty->default_plugin_handler_func,
array($tag, $plugin_type, $this->template, &$callback, &$script, &$cacheable));
if ($result) {
$this->tag_nocache = $this->tag_nocache || !$cacheable;
if ($script !== null) {
if (is_file($script)) {
if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {
$this->parent_compiler->template->compiled->required_plugins['nocache'][$tag][$plugin_type]['file'] = $script;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$tag][$plugin_type]['function'] = $callback;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$tag][$plugin_type]['file'] =
$script;
$this->parent_compiler->template->compiled->required_plugins['nocache'][$tag][$plugin_type]['function'] =
$callback;
} else {
$this->parent_compiler->template->compiled->required_plugins['compiled'][$tag][$plugin_type]['file'] = $script;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$tag][$plugin_type]['function'] = $callback;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$tag][$plugin_type]['file'] =
$script;
$this->parent_compiler->template->compiled->required_plugins['compiled'][$tag][$plugin_type]['function'] =
$callback;
}
require_once $script;
} else {
@@ -1015,7 +1087,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
// make sure we include modifier plugins for nocache code
foreach ($this->modifier_plugins as $plugin_name => $dummy) {
if (isset($this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name]['modifier'])) {
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name]['modifier'] = $this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name]['modifier'];
$this->parent_compiler->template->compiled->required_plugins['nocache'][$plugin_name]['modifier'] =
$this->parent_compiler->template->compiled->required_plugins['compiled'][$plugin_name]['modifier'];
}
}
} else {
@@ -1141,8 +1214,9 @@ abstract class Smarty_Internal_TemplateCompilerBase
}
if (in_array($this->template->source->type, array('eval', 'string'))) {
$templateName = $this->template->source->type . ':' .
trim(preg_replace('![\t\r\n]+!', ' ', strlen($lex->data) > 40 ? substr($lex->data, 0, 40) .
$templateName = $this->template->source->type . ':' . trim(preg_replace('![\t\r\n]+!', ' ',
strlen($lex->data) > 40 ?
substr($lex->data, 0, 40) .
'...' : $lex->data));
} else {
$templateName = $this->template->source->type . ':' . $this->template->source->filepath;
@@ -1150,10 +1224,10 @@ abstract class Smarty_Internal_TemplateCompilerBase
// $line += $this->trace_line_offset;
$match = preg_split("/\n/", $lex->data);
$error_text = 'Syntax error in template "' .
(empty($this->trace_filepath) ? $templateName : $this->trace_filepath) . '" on line ' .
($line + $this->trace_line_offset) . ' "' . trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) .
'" ';
$error_text =
'Syntax error in template "' . (empty($this->trace_filepath) ? $templateName : $this->trace_filepath) .
'" on line ' . ($line + $this->trace_line_offset) . ' "' .
trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" ';
if (isset($args)) {
// individual error message
$error_text .= $args;

View File

@@ -1,11 +1,11 @@
<?php
/**
* Smarty Internal Plugin Templatelexer
* This is the lexer to break the template source into tokens
/*
* This file is part of Smarty.
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
@@ -13,9 +13,8 @@
* This is the template file lexer.
* It is generated from the smarty_internal_templatelexer.plex file
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Templatelexer
{
@@ -156,8 +155,7 @@ class Smarty_Internal_Templatelexer
*
* @var array
*/
public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',
6 => 'CHILDBODY', 7 => 'CHILDBLOCK', 8 => 'CHILDLITERAL');
public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',);
/**
* storage for assembled token patterns
@@ -174,12 +172,6 @@ class Smarty_Internal_Templatelexer
private $yy_global_pattern5 = null;
private $yy_global_pattern6 = null;
private $yy_global_pattern7 = null;
private $yy_global_pattern8 = null;
/**
* token names
*
@@ -523,7 +515,7 @@ class Smarty_Internal_Templatelexer
if ($this->_yy_stack[count($this->_yy_stack) - 1] == self::TEXT) {
$this->yypopstate();
$this->token = Smarty_Internal_Templateparser::TP_SIMPLEOUTPUT;
$this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT;
$this->taglineno = $this->line;
} else {
$this->value = $this->smarty->left_delimiter;
@@ -570,7 +562,7 @@ class Smarty_Internal_Templatelexer
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' .
substr($this->data, $this->counter, 5) . '... state TAGBODY ');
substr($this->data, $this->counter, 5) . '... state TAGBODY');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -1123,321 +1115,6 @@ class Smarty_Internal_Templatelexer
$this->token = Smarty_Internal_Templateparser::TP_TEXT;
}
public function yylex6()
{
if (!isset($this->yy_global_pattern6)) {
$this->yy_global_pattern6 = "/\G(" . $this->ldel . "\\s*strip\\s*" . $this->rdel . ")|\G(" . $this->ldel .
"\\s*[\/]strip\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*block)|\G([\S\s])/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
do {
if (preg_match($this->yy_global_pattern6, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' .
substr($this->data, $this->counter, 5) . '... state CHILDBODY');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
$this->value = current($yymatches); // token value
$r = $this->{'yy_r6_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
// skip this token
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
} // end function
const CHILDBODY = 6;
function yy_r6_1()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
return false;
} else {
$this->token = Smarty_Internal_Templateparser::TP_STRIPON;
}
}
function yy_r6_2()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
return false;
} else {
$this->token = Smarty_Internal_Templateparser::TP_STRIPOFF;
}
}
function yy_r6_3()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
return false;
} else {
$this->yypopstate();
return true;
}
}
function yy_r6_4()
{
$to = strlen($this->data);
preg_match("~" . $this->ldel . "\s*(([/])?strip\s*" . $this->rdel .
"|block\s+)~i", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
}
$this->value = substr($this->data, $this->counter, $to - $this->counter);
return false;
}
public function yylex7()
{
if (!isset($this->yy_global_pattern7)) {
$this->yy_global_pattern7 = "/\G(" . $this->ldel . "\\s*literal\\s*" . $this->rdel . ")|\G(" . $this->ldel .
"\\s*block)|\G(" . $this->ldel . "\\s*[\/]block)|\G(" . $this->ldel .
"\\s*[$]smarty\\.block\\.(child|parent))|\G([\S\s])/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
do {
if (preg_match($this->yy_global_pattern7, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' .
substr($this->data, $this->counter, 5) . '... state CHILDBLOCK');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
$this->value = current($yymatches); // token value
$r = $this->{'yy_r7_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
// skip this token
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
} // end function
const CHILDBLOCK = 7;
function yy_r7_1()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypushstate(self::CHILDLITERAL);
}
}
function yy_r7_2()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
function yy_r7_3()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
function yy_r7_4()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->yypopstate();
return true;
}
}
function yy_r7_6()
{
$to = strlen($this->data);
preg_match("~" . $this->ldel . "\s*(literal\s*" . $this->rdel . "|([/])?block(\s|" . $this->rdel .
")|[\$]smarty\.block\.(child|parent))~i", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
}
$this->value = substr($this->data, $this->counter, $to - $this->counter);
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
}
public function yylex8()
{
if (!isset($this->yy_global_pattern8)) {
$this->yy_global_pattern8 = "/\G(" . $this->ldel . "\\s*literal\\s*" . $this->rdel . ")|\G(" . $this->ldel .
"\\s*[\/]literal\\s*" . $this->rdel . ")|\G([\S\s])/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
do {
if (preg_match($this->yy_global_pattern8, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' .
substr($this->data, $this->counter, 5) . '... state CHILDLITERAL');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
$this->value = current($yymatches); // token value
$r = $this->{'yy_r8_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
// skip this token
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
} // end function
const CHILDLITERAL = 8;
function yy_r8_1()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypushstate(self::CHILDLITERAL);
}
}
function yy_r8_2()
{
if ($this->smarty->auto_literal &&
isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false
) {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
$this->yypopstate();
}
}
function yy_r8_3()
{
$to = strlen($this->data);
preg_match("~{$this->ldel}[/]?literal\s*{$this->rdel}~i", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
if (isset($match[0][1])) {
$to = $match[0][1];
} else {
$this->compiler->trigger_template_error("missing or misspelled literal closing tag");
}
$this->value = substr($this->data, $this->counter, $to - $this->counter);
$this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -233,6 +233,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
public function compileTemplateSource(Smarty_Internal_Template $_template)
{
$_template->source->compileds = array();
$_template->isChild = false;
$this->file_dependency = array();
$this->tpl_function = array();
$this->includes = array();