library/smarty/libs/sysplugins/smarty_internal_compile_block.php
changeset 46 f11c31f7fa3e
parent 45 a56e7f9a0463
child 47 03388ec805b4
equal deleted inserted replaced
45:a56e7f9a0463 46:f11c31f7fa3e
     1 <?php
       
     2 
       
     3 /**
       
     4  * Smarty Internal Plugin Compile Block
       
     5  * Compiles the {block}{/block} tags
       
     6  *
       
     7  * @package    Smarty
       
     8  * @subpackage Compiler
       
     9  * @author     Uwe Tews
       
    10  */
       
    11 
       
    12 /**
       
    13  * Smarty Internal Plugin Compile Block Class
       
    14  *
       
    15  * @package    Smarty
       
    16  * @subpackage Compiler
       
    17  */
       
    18 class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
       
    19 
       
    20     const parent = '____SMARTY_BLOCK_PARENT____';
       
    21     /**
       
    22      * Attribute definition: Overwrites base class.
       
    23      *
       
    24      * @var array
       
    25      * @see Smarty_Internal_CompileBase
       
    26      */
       
    27     public $required_attributes = array('name');
       
    28 
       
    29     /**
       
    30      * Attribute definition: Overwrites base class.
       
    31      *
       
    32      * @var array
       
    33      * @see Smarty_Internal_CompileBase
       
    34      */
       
    35     public $shorttag_order = array('name');
       
    36 
       
    37     /**
       
    38      * Attribute definition: Overwrites base class.
       
    39      *
       
    40      * @var array
       
    41      * @see Smarty_Internal_CompileBase
       
    42      */
       
    43     public $option_flags = array('hide', 'append', 'prepend', 'nocache');
       
    44 
       
    45     /**
       
    46      * Attribute definition: Overwrites base class.
       
    47      *
       
    48      * @var array
       
    49      * @see Smarty_Internal_CompileBase
       
    50      */
       
    51     public $optional_attributes = array('internal_file', 'internal_uid', 'internal_line');
       
    52     /**
       
    53      * nested child block names
       
    54      *
       
    55      * @var array
       
    56      */
       
    57     public static $nested_block_names = array();
       
    58 
       
    59     /**
       
    60      * child block source buffer
       
    61      *
       
    62      * @var array
       
    63      */
       
    64     public static $block_data = array();
       
    65 
       
    66     /**
       
    67      * Compiles code for the {block} tag
       
    68      *
       
    69      * @param array $args array with attributes from parser
       
    70      * @param object $compiler compiler object
       
    71      *
       
    72      * @return boolean true
       
    73      */
       
    74     public function compile($args, $compiler) {
       
    75         // check and get attributes
       
    76         $_attr = $this->getAttributes($compiler, $args);
       
    77         $_name = trim($_attr['name'], "\"'");
       
    78 
       
    79         // existing child must override parent settings
       
    80         if (isset($compiler->template->block_data[$_name]) && $compiler->template->block_data[$_name]['mode'] == 'replace') {
       
    81             $_attr['append'] = false;
       
    82             $_attr['prepend'] = false;
       
    83         }
       
    84 
       
    85         // check if we process an inheritance child template
       
    86         if ($compiler->inheritance_child) {
       
    87             array_unshift(self::$nested_block_names, $_name);
       
    88             // build {block} for child block
       
    89             self::$block_data[$_name]['source'] =
       
    90                 "{$compiler->smarty->left_delimiter}private_child_block name={$_attr['name']} file='{$compiler->template->source->filepath}' type='{$compiler->template->source->type}' resource='{$compiler->template->template_resource}'" .
       
    91                 " uid='{$compiler->template->source->uid}' line={$compiler->lex->line}";
       
    92             if ($_attr['nocache']) {
       
    93                 self::$block_data[$_name]['source'] .= ' nocache';
       
    94             }
       
    95             self::$block_data[$_name]['source'] .= $compiler->smarty->right_delimiter;
       
    96 
       
    97             $save = array($_attr, $compiler->inheritance);
       
    98             $this->openTag($compiler, 'block', $save);
       
    99             // set flag for {block} tag
       
   100             $compiler->inheritance = true;
       
   101             $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
       
   102             $compiler->has_code = false;
       
   103             return;
       
   104         }
       
   105         // must merge includes
       
   106         if ($_attr['nocache'] == true) {
       
   107             $compiler->tag_nocache = true;
       
   108         }
       
   109         $save = array($_attr, $compiler->inheritance, $compiler->parser->current_buffer, $compiler->nocache);
       
   110         $this->openTag($compiler, 'block', $save);
       
   111         $compiler->inheritance = true;
       
   112         $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
       
   113 
       
   114         $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser);
       
   115         $compiler->has_code = false;
       
   116 
       
   117         return true;
       
   118     }
       
   119 
       
   120     /**
       
   121      * Compile saved child block source
       
   122      *
       
   123      * @param object $compiler compiler object
       
   124      * @param string $_name optional name of child block
       
   125      *
       
   126      * @return string   compiled code of child block
       
   127      */
       
   128     static function compileChildBlock($compiler, $_name = null) {
       
   129         if ($compiler->inheritance_child) {
       
   130             $name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
       
   131             if (isset($compiler->template->block_data[$name1])) {
       
   132                 //  replace inner block name with generic
       
   133                 Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= $compiler->template->block_data[$name1]['source'];
       
   134                 Smarty_Internal_Compile_Block::$block_data[$name1]['child'] = true;
       
   135             }
       
   136             $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
       
   137             $compiler->has_code = false;
       
   138             return;
       
   139         }
       
   140         // if called by {$smarty.block.child} we must search the name of enclosing {block}
       
   141         if ($_name == null) {
       
   142             $stack_count = count($compiler->_tag_stack);
       
   143             while (--$stack_count >= 0) {
       
   144                 if ($compiler->_tag_stack[$stack_count][0] == 'block') {
       
   145                     $_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
       
   146                     break;
       
   147                 }
       
   148             }
       
   149         }
       
   150         if ($_name == null) {
       
   151             $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->lex->taglineno);
       
   152         }
       
   153         // undefined child?
       
   154         if (!isset($compiler->template->block_data[$_name]['source'])) {
       
   155             $compiler->popTrace();
       
   156             return '';
       
   157         }
       
   158         // flag that child is already compile by {$smarty.block.child} inclusion
       
   159         $compiler->template->block_data[$_name]['compiled'] = true;
       
   160         $_tpl = new Smarty_Internal_template('string:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id,
       
   161             $compiler->template->compile_id, $compiler->template->caching, $compiler->template->cache_lifetime);
       
   162         if ($compiler->smarty->debugging) {
       
   163             Smarty_Internal_Debug::ignore($_tpl);
       
   164         }
       
   165         $_tpl->tpl_vars = $compiler->template->tpl_vars;
       
   166         $_tpl->variable_filters = $compiler->template->variable_filters;
       
   167         $_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
       
   168         $_tpl->allow_relative_path = true;
       
   169         $_tpl->compiler->inheritance = true;
       
   170         $_tpl->compiler->suppressHeader = true;
       
   171         $_tpl->compiler->suppressFilter = true;
       
   172         $_tpl->compiler->suppressTemplatePropertyHeader = true;
       
   173         $nocache = $compiler->nocache || $compiler->tag_nocache;
       
   174         if (strpos($compiler->template->block_data[$_name]['source'], self::parent) !== false) {
       
   175             $_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php(), $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler));
       
   176         } elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') {
       
   177             $_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler) . $compiler->parser->current_buffer->to_smarty_php();
       
   178         } elseif ($compiler->template->block_data[$_name]['mode'] == 'append') {
       
   179             $_output = $compiler->parser->current_buffer->to_smarty_php() . $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
       
   180         } elseif (!empty($compiler->template->block_data[$_name])) {
       
   181             $_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
       
   182         }
       
   183         $compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $_tpl->properties['file_dependency']);
       
   184         $compiler->template->properties['tpl_function'] = array_merge($compiler->template->properties['tpl_function'], $_tpl->properties['tpl_function']);
       
   185         $compiler->template->variable_filters = $_tpl->variable_filters;
       
   186         if ($_tpl->has_nocache_code) {
       
   187             $compiler->template->has_nocache_code = true;
       
   188         }
       
   189         foreach ($_tpl->required_plugins as $key => $tmp1) {
       
   190             if ($compiler->nocache && $compiler->template->caching) {
       
   191                 $code = 'nocache';
       
   192             } else {
       
   193                 $code = $key;
       
   194             }
       
   195             foreach ($tmp1 as $name => $tmp) {
       
   196                 foreach ($tmp as $type => $data) {
       
   197                     $compiler->template->required_plugins[$code][$name][$type] = $data;
       
   198                 }
       
   199             }
       
   200         }
       
   201         unset($_tpl);
       
   202         $compiler->has_code = true;
       
   203         return $_output;
       
   204     }
       
   205 
       
   206     /**
       
   207      * Compile $smarty.block.parent
       
   208      *
       
   209      * @param object $compiler compiler object
       
   210      * @param string $_name optional name of child block
       
   211      *
       
   212      * @return string   compiled code of child block
       
   213      */
       
   214     static function compileParentBlock($compiler, $_name = null) {
       
   215         // if called by {$smarty.block.parent} we must search the name of enclosing {block}
       
   216         if ($_name == null) {
       
   217             $stack_count = count($compiler->_tag_stack);
       
   218             while (--$stack_count >= 0) {
       
   219                 if ($compiler->_tag_stack[$stack_count][0] == 'block') {
       
   220                     $_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
       
   221                     break;
       
   222                 }
       
   223             }
       
   224         }
       
   225         if ($_name == null) {
       
   226             $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex->taglineno);
       
   227         }
       
   228         if (empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
       
   229             $compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', $compiler->lex->taglineno);
       
   230         }
       
   231         Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block::parent;
       
   232         $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
       
   233         $compiler->has_code = false;
       
   234         return;
       
   235     }
       
   236 
       
   237     /**
       
   238      * Process block source
       
   239      *
       
   240      * @param        $compiler
       
   241      * @param string $source source text
       
   242      */
       
   243     static function blockSource($compiler, $source) {
       
   244         Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= $source;
       
   245     }
       
   246 }
       
   247 
       
   248 /**
       
   249  * Smarty Internal Plugin Compile BlockClose Class
       
   250  *
       
   251  * @package    Smarty
       
   252  * @subpackage Compiler
       
   253  */
       
   254 class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase {
       
   255     /**
       
   256      * Compiles code for the {/block} tag
       
   257      *
       
   258      * @param array $args array with attributes from parser
       
   259      * @param object $compiler compiler object
       
   260      *
       
   261      * @return string compiled code
       
   262      */
       
   263     public function compile($args, $compiler) {
       
   264         $compiler->has_code = true;
       
   265         // check and get attributes
       
   266         $_attr = $this->getAttributes($compiler, $args);
       
   267         $saved_data = $this->closeTag($compiler, array('block'));
       
   268         $_name = trim($saved_data[0]['name'], "\"'");
       
   269         // reset flag for {block} tag
       
   270         $compiler->inheritance = $saved_data[1];
       
   271         // check if we process an inheritance child template
       
   272         if ($compiler->inheritance_child) {
       
   273             $name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
       
   274             Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}";
       
   275             array_shift(Smarty_Internal_Compile_Block::$nested_block_names);
       
   276             if (!empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
       
   277                 $name2 = Smarty_Internal_Compile_Block::$nested_block_names[0];
       
   278                 if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
       
   279                     if (isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child']) || !isset($compiler->template->block_data[$name1])) {
       
   280                         Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
       
   281                     } else {
       
   282                         if ($compiler->template->block_data[$name1]['mode'] == 'append') {
       
   283                             Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source'];
       
   284                         } elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
       
   285                             Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'] . Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
       
   286                         } else {
       
   287                             Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'];
       
   288                         }
       
   289                     }
       
   290                 }
       
   291                 unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
       
   292                 $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
       
   293             } else {
       
   294                 if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
       
   295                     if (isset($compiler->template->block_data[$name1]) && !isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child'])) {
       
   296                         if (strpos($compiler->template->block_data[$name1]['source'], Smarty_Internal_Compile_Block::parent) !== false) {
       
   297                             $compiler->template->block_data[$name1]['source'] =
       
   298                                 str_replace(Smarty_Internal_Compile_Block::parent, Smarty_Internal_Compile_Block::$block_data[$name1]['source'], $compiler->template->block_data[$name1]['source']);
       
   299                         } elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
       
   300                             $compiler->template->block_data[$name1]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
       
   301                         } elseif ($compiler->template->block_data[$name1]['mode'] == 'append') {
       
   302                             $compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source'];
       
   303                         }
       
   304                     } else {
       
   305                         $compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
       
   306                     }
       
   307                     $compiler->template->block_data[$name1]['mode'] = 'replace';
       
   308                     if ($saved_data[0]['append']) {
       
   309                         $compiler->template->block_data[$name1]['mode'] = 'append';
       
   310                     }
       
   311                     if ($saved_data[0]['prepend']) {
       
   312                         $compiler->template->block_data[$name1]['mode'] = 'prepend';
       
   313                     }
       
   314                 }
       
   315                 unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
       
   316                 $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
       
   317             }
       
   318             $compiler->has_code = false;
       
   319             return;
       
   320         }
       
   321         if (isset($compiler->template->block_data[$_name]) && !isset($compiler->template->block_data[$_name]['compiled'])) {
       
   322             $_output = Smarty_Internal_Compile_Block::compileChildBlock($compiler, $_name);
       
   323         } else {
       
   324             if ($saved_data[0]['hide'] && !isset($compiler->template->block_data[$_name]['source'])) {
       
   325                 $_output = '';
       
   326             } else {
       
   327                 $_output = $compiler->parser->current_buffer->to_smarty_php();
       
   328             }
       
   329         }
       
   330         if (isset($compiler->template->block_data[$_name]['compiled'])) {
       
   331             unset($compiler->template->block_data[$_name]['compiled']);
       
   332         }
       
   333         // reset flags
       
   334         $compiler->parser->current_buffer = $saved_data[2];
       
   335         if ($compiler->nocache) {
       
   336             $compiler->tag_nocache = true;
       
   337         }
       
   338         $compiler->nocache = $saved_data[3];
       
   339         // $_output content has already nocache code processed
       
   340         $compiler->suppressNocacheProcessing = true;
       
   341 
       
   342         return $_output;
       
   343     }
       
   344 }
       
   345 
       
   346 /**
       
   347  * Smarty Internal Plugin Compile Child Block Class
       
   348  *
       
   349  * @package    Smarty
       
   350  * @subpackage Compiler
       
   351  */
       
   352 class Smarty_Internal_Compile_Private_Child_Block extends Smarty_Internal_CompileBase {
       
   353 
       
   354     /**
       
   355      * Attribute definition: Overwrites base class.
       
   356      *
       
   357      * @var array
       
   358      * @see Smarty_Internal_CompileBase
       
   359      */
       
   360     public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
       
   361 
       
   362     /**
       
   363      * Compiles code for the {private_child_block} tag
       
   364      *
       
   365      * @param array $args array with attributes from parser
       
   366      * @param object $compiler compiler object
       
   367      *
       
   368      * @return boolean true
       
   369      */
       
   370     public function compile($args, $compiler) {
       
   371         // check and get attributes
       
   372         $_attr = $this->getAttributes($compiler, $args);
       
   373 
       
   374         // update template with original template resource of {block}
       
   375         if (trim($_attr['type'], "'") == 'file') {
       
   376             $compiler->template->template_resource = 'file:' . realpath(trim($_attr['file'], "'"));
       
   377         } else {
       
   378             $compiler->template->template_resource = trim($_attr['resource'], "'");
       
   379         }
       
   380         // source object
       
   381         unset ($compiler->template->source);
       
   382         $exists = $compiler->template->source->exists;
       
   383 
       
   384         // must merge includes
       
   385         if ($_attr['nocache'] == true) {
       
   386             $compiler->tag_nocache = true;
       
   387         }
       
   388         $save = array($_attr, $compiler->nocache);
       
   389 
       
   390         // set trace back to child block
       
   391         $compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex->line);
       
   392 
       
   393         $this->openTag($compiler, 'private_child_block', $save);
       
   394 
       
   395         $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
       
   396         $compiler->has_code = false;
       
   397 
       
   398         return true;
       
   399     }
       
   400 }
       
   401 
       
   402 /**
       
   403  * Smarty Internal Plugin Compile Child Block Close Class
       
   404  *
       
   405  * @package    Smarty
       
   406  * @subpackage Compiler
       
   407  */
       
   408 class Smarty_Internal_Compile_Private_Child_Blockclose extends Smarty_Internal_CompileBase {
       
   409 
       
   410     /**
       
   411      * Compiles code for the {/private_child_block} tag
       
   412      *
       
   413      * @param array $args array with attributes from parser
       
   414      * @param object $compiler compiler object
       
   415      *
       
   416      * @return boolean true
       
   417      */
       
   418     public function compile($args, $compiler) {
       
   419         // check and get attributes
       
   420         $_attr = $this->getAttributes($compiler, $args);
       
   421 
       
   422         $saved_data = $this->closeTag($compiler, array('private_child_block'));
       
   423 
       
   424         // end of child block
       
   425         $compiler->popTrace();
       
   426 
       
   427         $compiler->nocache = $saved_data[1];
       
   428         $compiler->has_code = false;
       
   429 
       
   430         return true;
       
   431     }
       
   432 }