3 * Smarty Internal Plugin Compile ForeachSection
4 * Shared methods for {foreach} {section} tags
12 * Smarty Internal Plugin Compile ForeachSection Class
15 * @subpackage Compiler
17 class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_CompileBase
25 private $propertyPreg = '';
28 * Offsets in preg match result
32 private $resultOffsets = array();
39 private $startOffset = 0;
49 * Valid properties of $smarty.xxx variable
53 public $nameProperties = array();
56 * {section} tag has no item properties
60 public $itemProperties = null;
63 * {section} tag has always name attribute
67 public $isNamed = true;
72 public $matchResults = array();
75 * Scan sources for used tag attributes
77 * @param array $attributes
78 * @param \Smarty_Internal_TemplateCompilerBase $compiler
80 public function scanForProperties($attributes, Smarty_Internal_TemplateCompilerBase $compiler)
82 $this->propertyPreg = '~(';
83 $this->startOffset = 0;
84 $this->resultOffsets = array();
85 $this->matchResults = array('named' => array(), 'item' => array());
87 $this->buildPropertyPreg(true, $attributes);
89 if (isset($this->itemProperties)) {
91 $this->propertyPreg .= '|';
93 $this->buildPropertyPreg(false, $attributes);
95 $this->propertyPreg .= ')\W~i';
97 $this->matchTemplateSource($compiler);
98 // Parent template source
99 $this->matchParentTemplateSource($compiler);
101 $this->matchBlockSource($compiler);
105 * Build property preg string
108 * @param array $attributes
110 public function buildPropertyPreg($named, $attributes)
113 $this->resultOffsets[ 'named' ] = $this->startOffset + 3;
114 $this->propertyPreg .= "([\$]smarty[.]{$this->tagName}[.]{$attributes['name']}[.](";
115 $properties = $this->nameProperties;
117 $this->resultOffsets[ 'item' ] = $this->startOffset + 3;
118 $this->propertyPreg .= "([\$]{$attributes['item']}[@](";
119 $properties = $this->itemProperties;
121 $this->startOffset += count($properties) + 2;
122 $propName = reset($properties);
124 $this->propertyPreg .= "({$propName})";
125 $propName = next($properties);
127 $this->propertyPreg .= '|';
130 $this->propertyPreg .= '))';
134 * Find matches in source string
136 * @param string $source
138 public function matchProperty($source)
140 preg_match_all($this->propertyPreg, $source, $match, PREG_SET_ORDER);
141 foreach ($this->resultOffsets as $key => $offset) {
142 foreach ($match as $m) {
143 if (isset($m[ $offset ]) && !empty($m[ $offset ])) {
144 $this->matchResults[ $key ][ strtolower($m[ $offset ]) ] = true;
151 * Find matches in template source
153 * @param \Smarty_Internal_TemplateCompilerBase $compiler
155 public function matchTemplateSource(Smarty_Internal_TemplateCompilerBase $compiler)
157 $this->matchProperty($compiler->parser->lex->data);
161 * Find matches in all parent template source
163 * @param \Smarty_Internal_TemplateCompilerBase $compiler
165 public function matchParentTemplateSource(Smarty_Internal_TemplateCompilerBase $compiler)
167 // search parent compiler template source
168 $nextCompiler = $compiler;
169 while ($nextCompiler !== $nextCompiler->parent_compiler) {
170 $nextCompiler = $nextCompiler->parent_compiler;
171 if ($compiler !== $nextCompiler) {
172 // get template source
173 $_content = $nextCompiler->template->source->getContent();
174 if ($_content != '') {
175 // run pre filter if required
176 if ((isset($nextCompiler->smarty->autoload_filters[ 'pre' ]) ||
177 isset($nextCompiler->smarty->registered_filters[ 'pre' ]))
179 $_content = $nextCompiler->smarty->ext->_filterHandler->runFilter('pre', $_content,
180 $nextCompiler->template);
182 $this->matchProperty($_content);
189 * Find matches in {block} tag source
191 * @param \Smarty_Internal_TemplateCompilerBase $compiler
193 public function matchBlockSource(Smarty_Internal_TemplateCompilerBase $compiler)
198 * Compiles code for the {$smarty.foreach.xxx} or {$smarty.section.xxx}tag
200 * @param array $args array with attributes from parser
201 * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
202 * @param array $parameter array with compilation parameter
204 * @return string compiled code
205 * @throws \SmartyCompilerException
207 public function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
209 $tag = strtolower(trim($parameter[ 0 ], '"\''));
210 $name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false;
212 $compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
214 $property = isset($parameter[ 2 ]) ? strtolower($compiler->getId($parameter[ 2 ])) : false;
215 if (!$property || !in_array($property, $this->nameProperties)) {
216 $compiler->trigger_template_error("missing or illegal \$smarty.{$tag} property attribute", null, true);
218 $tagVar = "'__smarty_{$tag}_{$name}'";
219 return "(isset(\$_smarty_tpl->tpl_vars[{$tagVar}]->value['{$property}']) ? \$_smarty_tpl->tpl_vars[{$tagVar}]->value['{$property}'] : null)";