mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-02 01:14:27 +02:00
Mark text sections as to be stripped, but do not strip them right away. Combine equivalent sections in chunks at the template level and strip combined chunks where possible.
- simplified Smarty_Internal_TemplateCompilerBase::processText along the way Fixes !447
This commit is contained in:
@@ -85,45 +85,85 @@ class Smarty_Internal_ParseTree_Template extends Smarty_Internal_ParseTree
|
|||||||
public function to_smarty_php(Smarty_Internal_Templateparser $parser)
|
public function to_smarty_php(Smarty_Internal_Templateparser $parser)
|
||||||
{
|
{
|
||||||
$code = '';
|
$code = '';
|
||||||
for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) {
|
|
||||||
if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text) {
|
foreach ($this->getChunkedSubtrees() as $chunk) {
|
||||||
$subtree = $this->subtrees[ $key ]->to_smarty_php($parser);
|
$text = '';
|
||||||
while ($key + 1 < $cnt && ($this->subtrees[ $key + 1 ] instanceof Smarty_Internal_ParseTree_Text ||
|
switch ($chunk['mode']) {
|
||||||
$this->subtrees[ $key + 1 ]->data === '')) {
|
case 'textstripped':
|
||||||
$key++;
|
foreach ($chunk['subtrees'] as $subtree) {
|
||||||
if ($this->subtrees[ $key ]->data === '') {
|
$text .= $subtree->to_smarty_php($parser);
|
||||||
continue;
|
}
|
||||||
}
|
$code .= preg_replace(
|
||||||
$subtree .= $this->subtrees[ $key ]->to_smarty_php($parser);
|
'/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/',
|
||||||
}
|
"<?php echo '\$1'; ?>\n",
|
||||||
if ($subtree === '') {
|
$parser->compiler->processText($text)
|
||||||
continue;
|
);
|
||||||
}
|
break;
|
||||||
$code .= preg_replace(
|
case 'text':
|
||||||
'/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/',
|
foreach ($chunk['subtrees'] as $subtree) {
|
||||||
"<?php echo '\$1'; ?>\n",
|
$text .= $subtree->to_smarty_php($parser);
|
||||||
$subtree
|
}
|
||||||
);
|
$code .= preg_replace(
|
||||||
continue;
|
'/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/',
|
||||||
}
|
"<?php echo '\$1'; ?>\n",
|
||||||
if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Tag) {
|
$text
|
||||||
$subtree = $this->subtrees[ $key ]->to_smarty_php($parser);
|
);
|
||||||
while ($key + 1 < $cnt && ($this->subtrees[ $key + 1 ] instanceof Smarty_Internal_ParseTree_Tag ||
|
break;
|
||||||
$this->subtrees[ $key + 1 ]->data === '')) {
|
case 'tag':
|
||||||
$key++;
|
foreach ($chunk['subtrees'] as $subtree) {
|
||||||
if ($this->subtrees[ $key ]->data === '') {
|
$text = $parser->compiler->appendCode($text, $subtree->to_smarty_php($parser));
|
||||||
continue;
|
}
|
||||||
}
|
$code .= $text;
|
||||||
$subtree = $parser->compiler->appendCode($subtree, $this->subtrees[ $key ]->to_smarty_php($parser));
|
break;
|
||||||
}
|
default:
|
||||||
if ($subtree === '') {
|
foreach ($chunk['subtrees'] as $subtree) {
|
||||||
continue;
|
$text = $subtree->to_smarty_php($parser);
|
||||||
}
|
}
|
||||||
$code .= $subtree;
|
$code .= $text;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
$code .= $this->subtrees[ $key ]->to_smarty_php($parser);
|
|
||||||
}
|
}
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getChunkedSubtrees() {
|
||||||
|
$chunks = [];
|
||||||
|
$currentMode = null;
|
||||||
|
$currentChunk = [];
|
||||||
|
for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) {
|
||||||
|
|
||||||
|
if ($this->subtrees[ $key ]->data === '' && in_array($currentMode, ['textstripped', 'text', 'tag'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text
|
||||||
|
&& $this->subtrees[ $key ]->isToBeStripped()) {
|
||||||
|
$newMode = 'textstripped';
|
||||||
|
} elseif ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text) {
|
||||||
|
$newMode = 'text';
|
||||||
|
} elseif ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Tag) {
|
||||||
|
$newMode = 'tag';
|
||||||
|
} else {
|
||||||
|
$newMode = 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newMode == $currentMode) {
|
||||||
|
$currentChunk[] = $this->subtrees[ $key ];
|
||||||
|
} else {
|
||||||
|
$chunks[] = [
|
||||||
|
'mode' => $currentMode,
|
||||||
|
'subtrees' => $currentChunk
|
||||||
|
];
|
||||||
|
$currentMode = $newMode;
|
||||||
|
$currentChunk = [$this->subtrees[ $key ]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($currentMode && $currentChunk) {
|
||||||
|
$chunks[] = [
|
||||||
|
'mode' => $currentMode,
|
||||||
|
'subtrees' => $currentChunk
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $chunks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,14 +16,31 @@
|
|||||||
*/
|
*/
|
||||||
class Smarty_Internal_ParseTree_Text extends Smarty_Internal_ParseTree
|
class Smarty_Internal_ParseTree_Text extends Smarty_Internal_ParseTree
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Create template text buffer
|
/**
|
||||||
*
|
* Wether this section should be stripped on output to smarty php
|
||||||
* @param string $data text
|
* @var bool
|
||||||
*/
|
*/
|
||||||
public function __construct($data)
|
private $toBeStripped = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create template text buffer
|
||||||
|
*
|
||||||
|
* @param string $data text
|
||||||
|
* @param bool $toBeStripped wether this section should be stripped on output to smarty php
|
||||||
|
*/
|
||||||
|
public function __construct($data, $toBeStripped = false)
|
||||||
{
|
{
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
|
$this->toBeStripped = $toBeStripped;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wether this section should be stripped on output to smarty php
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isToBeStripped() {
|
||||||
|
return $this->toBeStripped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -672,73 +672,69 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from parser to process a text content section
|
* This method is called from parser to process a text content section if strip is enabled
|
||||||
* - remove text from inheritance child templates as they may generate output
|
* - remove text from inheritance child templates as they may generate output
|
||||||
* - strip text if strip is enabled
|
|
||||||
*
|
*
|
||||||
* @param string $text
|
* @param string $text
|
||||||
*
|
*
|
||||||
* @return null|\Smarty_Internal_ParseTree_Text
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function processText($text)
|
public function processText($text)
|
||||||
{
|
{
|
||||||
if ((string)$text != '') {
|
|
||||||
$store = array();
|
if (strpos($text, '<') === false) {
|
||||||
$_store = 0;
|
return preg_replace($this->stripRegEx, '', $text);
|
||||||
if ($this->parser->strip) {
|
|
||||||
if (strpos($text, '<') !== false) {
|
|
||||||
// capture html elements not to be messed with
|
|
||||||
$_offset = 0;
|
|
||||||
if (preg_match_all(
|
|
||||||
'#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is',
|
|
||||||
$text,
|
|
||||||
$matches,
|
|
||||||
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
foreach ($matches as $match) {
|
|
||||||
$store[] = $match[ 0 ][ 0 ];
|
|
||||||
$_length = strlen($match[ 0 ][ 0 ]);
|
|
||||||
$replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
|
|
||||||
$text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
|
|
||||||
$_offset += $_length - strlen($replace);
|
|
||||||
$_store++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$expressions = array(// replace multiple spaces between tags by a single space
|
|
||||||
'#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2',
|
|
||||||
// remove newline between tags
|
|
||||||
'#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2',
|
|
||||||
// remove multiple spaces between attributes (but not in attribute values!)
|
|
||||||
'#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
|
|
||||||
'#>[\040\011]+$#Ss' => '> ',
|
|
||||||
'#>[\040\011]*[\n]\s*$#Ss' => '>',
|
|
||||||
$this->stripRegEx => '',
|
|
||||||
);
|
|
||||||
$text = preg_replace(array_keys($expressions), array_values($expressions), $text);
|
|
||||||
$_offset = 0;
|
|
||||||
if (preg_match_all(
|
|
||||||
'#@!@SMARTY:([0-9]+):SMARTY@!@#is',
|
|
||||||
$text,
|
|
||||||
$matches,
|
|
||||||
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
foreach ($matches as $match) {
|
|
||||||
$_length = strlen($match[ 0 ][ 0 ]);
|
|
||||||
$replace = $store[ $match[ 1 ][ 0 ] ];
|
|
||||||
$text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length);
|
|
||||||
$_offset += strlen($replace) - $_length;
|
|
||||||
$_store++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$text = preg_replace($this->stripRegEx, '', $text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Smarty_Internal_ParseTree_Text($text);
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
$store = array();
|
||||||
|
$_store = 0;
|
||||||
|
|
||||||
|
// capture html elements not to be messed with
|
||||||
|
$_offset = 0;
|
||||||
|
if (preg_match_all(
|
||||||
|
'#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is',
|
||||||
|
$text,
|
||||||
|
$matches,
|
||||||
|
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
$store[] = $match[ 0 ][ 0 ];
|
||||||
|
$_length = strlen($match[ 0 ][ 0 ]);
|
||||||
|
$replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
|
||||||
|
$text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
|
||||||
|
$_offset += $_length - strlen($replace);
|
||||||
|
$_store++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$expressions = array(// replace multiple spaces between tags by a single space
|
||||||
|
'#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2',
|
||||||
|
// remove newline between tags
|
||||||
|
'#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2',
|
||||||
|
// remove multiple spaces between attributes (but not in attribute values!)
|
||||||
|
'#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
|
||||||
|
'#>[\040\011]+$#Ss' => '> ',
|
||||||
|
'#>[\040\011]*[\n]\s*$#Ss' => '>',
|
||||||
|
$this->stripRegEx => '',
|
||||||
|
);
|
||||||
|
$text = preg_replace(array_keys($expressions), array_values($expressions), $text);
|
||||||
|
$_offset = 0;
|
||||||
|
if (preg_match_all(
|
||||||
|
'#@!@SMARTY:([0-9]+):SMARTY@!@#is',
|
||||||
|
$text,
|
||||||
|
$matches,
|
||||||
|
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
$_length = strlen($match[ 0 ][ 0 ]);
|
||||||
|
$replace = $store[ $match[ 1 ][ 0 ] ];
|
||||||
|
$text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length);
|
||||||
|
$_offset += strlen($replace) - $_length;
|
||||||
|
$_store++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2169,8 +2169,13 @@ class Smarty_Internal_Templateparser
|
|||||||
// line 255 "../smarty/lexer/smarty_internal_templateparser.y"
|
// line 255 "../smarty/lexer/smarty_internal_templateparser.y"
|
||||||
public function yy_r2()
|
public function yy_r2()
|
||||||
{
|
{
|
||||||
$this->current_buffer->append_subtree($this,
|
$text = $this->yystack[ $this->yyidx + 0 ]->minor;
|
||||||
$this->compiler->processText($this->yystack[ $this->yyidx + 0 ]->minor));
|
|
||||||
|
if ((string)$text == '') {
|
||||||
|
$this->current_buffer->append_subtree($this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text($text, $this->strip));
|
||||||
}
|
}
|
||||||
|
|
||||||
// line 259 "../smarty/lexer/smarty_internal_templateparser.y"
|
// line 259 "../smarty/lexer/smarty_internal_templateparser.y"
|
||||||
|
Reference in New Issue
Block a user