1<?php 2/** 3 * Smarty Internal Plugin Compile Break 4 * Compiles the {break} tag 5 * 6 * @package Smarty 7 * @subpackage Compiler 8 * @author Uwe Tews 9 */ 10 11/** 12 * Smarty Internal Plugin Compile Break Class 13 * 14 * @package Smarty 15 * @subpackage Compiler 16 */ 17class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase 18{ 19 /** 20 * Attribute definition: Overwrites base class. 21 * 22 * @var array 23 * @see Smarty_Internal_CompileBase 24 */ 25 public $optional_attributes = array('levels'); 26 27 /** 28 * Attribute definition: Overwrites base class. 29 * 30 * @var array 31 * @see Smarty_Internal_CompileBase 32 */ 33 public $shorttag_order = array('levels'); 34 35 /** 36 * Tag name may be overloaded by Smarty_Internal_Compile_Continue 37 * 38 * @var string 39 */ 40 public $tag = 'break'; 41 42 /** 43 * Compiles code for the {break} tag 44 * 45 * @param array $args array with attributes from parser 46 * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object 47 * 48 * @return string compiled code 49 * @throws \SmartyCompilerException 50 */ 51 public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) 52 { 53 list($levels, $foreachLevels) = $this->checkLevels($args, $compiler); 54 $output = "<?php "; 55 if ($foreachLevels > 0 && $this->tag === 'continue') { 56 $foreachLevels--; 57 } 58 if ($foreachLevels > 0) { 59 /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */ 60 $foreachCompiler = $compiler->getTagCompiler('foreach'); 61 $output .= $foreachCompiler->compileRestore($foreachLevels); 62 } 63 $output .= "{$this->tag} {$levels};?>"; 64 return $output; 65 } 66 67 /** 68 * check attributes and return array of break and foreach levels 69 * 70 * @param array $args array with attributes from parser 71 * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object 72 * 73 * @return array 74 * @throws \SmartyCompilerException 75 */ 76 public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler) 77 { 78 static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true); 79 // check and get attributes 80 $_attr = $this->getAttributes($compiler, $args); 81 if ($_attr[ 'nocache' ] === true) { 82 $compiler->trigger_template_error('nocache option not allowed', null, true); 83 } 84 if (isset($_attr[ 'levels' ])) { 85 if (!is_numeric($_attr[ 'levels' ])) { 86 $compiler->trigger_template_error('level attribute must be a numeric constant', null, true); 87 } 88 $levels = $_attr[ 'levels' ]; 89 } else { 90 $levels = 1; 91 } 92 $level_count = $levels; 93 $stack_count = count($compiler->_tag_stack) - 1; 94 $foreachLevels = 0; 95 $lastTag = ''; 96 while ($level_count > 0 && $stack_count >= 0) { 97 if (isset($_is_loopy[ $compiler->_tag_stack[ $stack_count ][ 0 ] ])) { 98 $lastTag = $compiler->_tag_stack[ $stack_count ][ 0 ]; 99 if ($level_count === 0) { 100 break; 101 } 102 $level_count--; 103 if ($compiler->_tag_stack[ $stack_count ][ 0 ] === 'foreach') { 104 $foreachLevels++; 105 } 106 } 107 $stack_count--; 108 } 109 if ($level_count !== 0) { 110 $compiler->trigger_template_error("cannot {$this->tag} {$levels} level(s)", null, true); 111 } 112 if ($lastTag === 'foreach' && $this->tag === 'break' && $foreachLevels > 0) { 113 $foreachLevels--; 114 } 115 return array($levels, $foreachLevels); 116 } 117} 118