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: */
17: class 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: