|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
rudiedirkx Smarty Rookie
Joined: 12 Aug 2010 Posts: 5
|
Posted: Sat Dec 22, 2012 3:14 pm Post subject: [2.6.27] With or without block/compiler end tag possible? |
|
|
Maybe what I want is a custom block compiler? Like foreach and if. Not once, but with end tag (sometimes).
I have a function that's a block sometimes and a function other times, depending on tag attributes. It's called title.
Currently I've added 'title' and '/title' cases in Smarty_Compiler::_compile_tag. I can use _push_tag and _pop_tag to keep track of whether it's a block or a function.
The block returns code to start ob and end it in /title.
The function returns code to assign the tags to a custom function (in the plugins folder).
If a /title is encountered while no ob started, an empty string is returned, so ob is always ended.
I don't think this is possible without hacking Smarty. A custom block would require an end tag even before evaluating the tag attributes. A function would never check for end tag, so I can't handle the /title. Same for a compiler: no end tag and I can't handle /title with a compiler.
The solution IMO is simple: allow smarty_core_assemble_plugin_filepath so handle end tags: have /title include the title plugin. The custom compiler itself can see if it's a start or end tag.
Current code in Smarty_Compiler::_compile_tag:
Code: |
case 'title':
$attrs = $this->_parse_attrs($tag_args);
if ( isset($attrs['key']) ) {
$export = $this->_var_export($attrs);
return '<?php $this->assign("title", smarty_function_translate(' . $export . ', $this)); ?>';
}
$this->_push_tag('title');
$this->_opened_title_tag = true;
return '<?php ob_start(); ?>';
break;
case '/title':
if ( $this->_opened_title_tag ) {
$this->_opened_title_tag = false;
return '<?php $this->assign("title", trim(preg_replace("#\s+#", " ", ob_get_clean()))); ?>';
}
return '';
break;
|
Is this possible without hacking Smarty_Compiler?
(How can this form not have markup for inline code??) |
|
Back to top |
|
rudiedirkx Smarty Rookie
Joined: 12 Aug 2010 Posts: 5
|
Posted: Sat Dec 22, 2012 3:59 pm Post subject: |
|
|
I can add dynamic compile blocks to Smarty with only 3 small adjustments (or 'hacks'):
Change Smarty::_get_plugin_filepath:
Code: | function _get_plugin_filepath($type, &$name)
{
if ($type == 'compiler') {
$name = ltrim($name, '/');
} |
(added & before $name and the if-statement)
Change Smarty_Compiler::_compile_compiler_tag:
Code: | $have_function = true;
$end_tag = substr($tag_command, 0, 1) == '/'; |
(added $end_tag variable to use later on)
Change Smarty_Compiler::_compile_compiler_tag some more:
Code: | if ($found) {
if ($have_function) {
$output = call_user_func_array($plugin_func, array($tag_args, &$this, $end_tag)); |
(added $end_tag to the plugin function arguments list)
With those adjustments, I can make a custom compiler function that handles the start and end tag and knows which is parsed:
Code: | function smarty_compiler_title($tag_attrs, &$compiler, $end_tag) {
$start_tag = !$end_tag;
// Open tag
if ( $start_tag ) {
$attrs = $compiler->_parse_attrs($tag_attrs);
if ( isset($attrs['key']) ) {
$export = _smarty_compiler_title_var_export($attrs);
return '$this->assign("title", smarty_function_translate(' . $export . ', $this));';
}
$compiler->_push_tag('title');
$compiler->_opened_title_tag = true;
return 'ob_start();';
}
// Close tag
if ( !empty($compiler->_opened_title_tag) ) {
unset($compiler->_opened_title_tag);
$_open_tag = $compiler->_pop_tag('title');
return '$this->assign("title", trim(preg_replace("#\s+#", " ", ob_get_clean())));';
}
return '';
}
function _smarty_compiler_title_var_export($attrs) {
$items = array();
foreach ( $attrs AS $key => $value ) {
$items[] = "'" . $key . "' => " . $value;
}
return 'array(' . implode(', ', $items) . ')';
} |
Is this an idea to add in a next release? It's completely 100% backward compatible and harmless. |
|
Back to top |
|
rudiedirkx Smarty Rookie
Joined: 12 Aug 2010 Posts: 5
|
Posted: Sat Dec 22, 2012 4:09 pm Post subject: |
|
|
Nope. Scratch that. Making $name in Smarty::_get_plugin_filepath by-reference is a baaad idea. |
|
Back to top |
|
rudiedirkx Smarty Rookie
Joined: 12 Aug 2010 Posts: 5
|
Posted: Sat Dec 22, 2012 4:16 pm Post subject: |
|
|
Even better. Only for custom compilers.
No changes to Smarty::_get_plugin_filepath.
Add below $end_tag in Smarty_Compiler::_compile_compiler_tag:
Code: | $tag_command = ltrim($tag_command, '/'); |
Now it really is backward compatible, because it doesn't change any function headers/definitions.
The only thing that changes now is parse errors in block end tags aren't caught as block end tags, but as custom compilers. |
|
Back to top |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|