/** <code>{% for %}</code> tag. */ public function handleTFor(TemplateCompilerEx $compiler, TemplateNodeEx $node, &$tag, array &$args) { if (count($args) == 3) { // {% for value in iterable %} $valueVariable =& $args[0]; $keyVariable = null; $inConstant =& $args[1]; $iterableVariable =& $args[2]; } elseif (count($args) == 4) { // {% for value in iterable %} $valueVariable =& $args[1]; $keyVariable =& $args[0]; $compiler->raiseIf(mb_substr($keyVariable, -1, 1) != ',', $node, 'Key variable definition invalid - it should end with a comma', TemplateError::E_INVALID_ARGUMENT); $keyVariable = mb_substr($keyVariable, 0, -1); $inConstant =& $args[2]; $iterableVariable =& $args[3]; } else { $compiler->raise($node, 'Invalid argument count - either 3 or 4 are required', TemplateError::E_INVALID_ARGUMENT); } $compiler->raiseIf($inConstant != 'in', $node, 'Invalid argument given - expected "in", found "' . $inConstant . '"', TemplateError::E_INVALID_ARGUMENT); // to avoid loop's block name collisions, and long function names at the same time $loopBlockName = $compiler->generateUniqueBlock($keyVariable . $valueVariable . $iterableVariable, 'loop:'); list($iterable, $filters) = TemplateUtils::split('|', $iterableVariable); list($iterable, $iterCheck) = $compiler->parseVariableExpression($node, $iterable); if (!isset($compiler->varInLoop)) { $compiler->varInLoop = array(); } $loopCall = sprintf('$b.=$this->_' . TemplateUtils::sanitize($loopBlockName) . '($e%s);', $compiler->varInLoop ? ',$f' : ''); // body of the loop list($loopBodyNodes, $emptyNodes) = $compiler->findAlternativeBranch($node, 'empty'); $compiler->varInLoop[] = $loopBlockName; $loopBody = $compiler->handleChildren($loopBodyNodes); array_pop($compiler->varInLoop); // and loop itself // // $k = value of the key // $v = value of the value // $kn = name of context variable holding key // $vn = name of context variable holding value // $ic = item count in iterable // $iv = iterable // $f = name of the forloop variable // $this->ctx[$kn] = reference to $k // $this->ctx[$vn] = reference to $v // $cf = reference to $this->ctx[$f] // sanity check $loopCheckCode = 'if(!is_array($iv)&&!(is_object($iv)&&' . 'TemplateUtils::doesImplement($iv,\'Traversable\')&&' . 'TemplateUtils::doesImplement($iv,\'Countable\'))){' . '$this->invalidVar(\'' . TemplateUtils::escape($iterableVariable) . '\',\'iterable expected\');}'; $loopCode = $iterCheck . '$iv=' . $compiler->parseFilterChain($node, $filters, '@' . $iterable) . ';' . '$f=\'forloop:' . TemplateUtils::escape($loopBlockName) . '\';' . $loopCheckCode; if ($keyVariable) { $loopCode .= TemplateUtils::strip(' $k = null; $kn = \'' . TemplateUtils::escape($keyVariable) . '\'; $this->ctx[$kn] = &$k; '); } $loopCode .= sprintf(TemplateUtils::strip(' $v = null; $vn = \'' . TemplateUtils::escape($valueVariable) . '\'; $this->ctx[$vn] = &$v; $ic = count($iv); $this->ctx[$f] = array( \'counter\' => 1, \'counter0\' => 0, \'revcounter\' => $ic, \'revcounter0\' => $ic - 1, \'first\' => true, \'last\' => ($ic - 1) == 0 ); $cf = &$this->ctx[$f]; if (func_num_args() == 2) { $cf[\'parentloop\'] = &$this->ctx[func_get_arg(1)]; } %s %s { %s ++$cf[\'counter\']; ++$cf[\'counter0\']; --$cf[\'revcounter\']; --$cf[\'revcounter0\']; $cf[\'first\'] = false; $cf[\'last\'] = ($cf[\'revcounter0\'] == 0); } '), $emptyNodes ? 'if($ic==0){$b=\'\';' . $compiler->handleChildren($emptyNodes) . 'return $b;}' : '', 'foreach($iv as ' . ($keyVariable ? '$k=>' : '') . '$v)', $loopBody); $compiler->blocks[$loopBlockName] = '$b=\'\';' . $loopCode . 'return $b;'; return $loopCall; }
/** Runs handlers associated with given hook-point. Every handler might return @c true boolean value, to break the chain and finish hook execution. @param[in] $hookPoint Hook-point to execute @param[in] $args Array of hook arguments @retval true Some handler has broken the chain @retval false All handlers have been executed, and none has broken the chain */ private function runHooks($hookPoint, array $args) { array_unshift($args, $this); $handlers = $this->plugins->get('hook', $hookPoint); foreach ($handlers as &$hookInfo) { $handler =& $hookInfo['handler']; if (!is_callable($handler)) { throw new TemplateError('Invalid handler [' . TemplateUtils::strip(var_export($hookInfo['handler'], true)) . '] hooked into "' . $hookPoint . '" point by plugin "' . $hookInfo['plugin'] . '"', TemplateError::E_INVALID_HANDLER); } if (call_user_func_array($handler, $args) === true) { return true; } } return false; }
/** Tests the behaviour of @ref TemplateUtils::strip. */ public function testUtilsStrip() { $this->assertEquals('abcdef', TemplateUtils::strip("abc\ndef")); }