/** * @param Tokenizer $tokens * @param Template $tpl * @return string */ public static function php(Tokenizer $tokens, Template $tpl) { $callable = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()); while ($tokens->is('.')) { $callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext(); } $callable = implode('\\', $callable); if ($tokens->is(T_DOUBLE_COLON)) { $callable .= '::' . $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext(); } $call_filter = $tpl->getStorage()->call_filters; if ($call_filter) { foreach ($call_filter as $filter) { if (!fnmatch(addslashes($filter), $callable)) { throw new \LogicException("Callback " . str_replace('\\', '.', $callable) . " is not available by settings"); } } } if (!is_callable($callable)) { throw new \RuntimeException("PHP method " . str_replace('\\', '.', $callable) . ' does not exists.'); } if ($tokens->is('(')) { $arguments = 'array' . $tpl->parseArgs($tokens) . ''; } else { $arguments = 'array()'; } return 'call_user_func_array(' . var_export($callable, true) . ', ' . $arguments . ')'; }
/** * Output value as is, without escaping * * @param Tokenizer $tokens * @param Template $tpl * @throws InvalidUsageException * @return string */ public static function tagRaw(Tokenizer $tokens, Template $tpl) { $escape = (bool) $tpl->escape; $tpl->escape = false; if ($tokens->is(':')) { $func = $tokens->getNext(Tokenizer::MACRO_STRING); $tag = $tpl->getStorage()->getTag($func, $tpl); if ($tag["type"] == \Fenom::INLINE_FUNCTION) { $code = $tpl->parseAct($tokens); // } elseif ($tag["type"] == \Fenom::BLOCK_FUNCTION) { // $code = $tpl->parseAct($tokens); // $tpl->getLastScope()->escape = false; // return $code; } else { throw new InvalidUsageException("Raw mode allow for expressions or functions"); } } else { $code = $tpl->out($tpl->parseExpr($tokens)); } $tpl->escape = $escape; return $code; }
/** * Accessor {$.block.NAME} * @param Tokenizer $tokens * @param Template $tpl * @return mixed */ public static function block(Tokenizer $tokens, Template $tpl) { if ($tokens->is('.')) { $name = $tokens->next()->get(Tokenizer::MACRO_STRING); $tokens->next(); return isset($tpl->blocks[$name]) ? 'true' : 'false'; } else { return "array(" . implode(",", array_keys($tpl->blocks)) . ")"; } }
/** * Parse parameters as $key=$value * param1=$var param2=3 ... * * @static * @param Tokenizer $tokens * @param array $defaults * @throws \Exception * @return array */ public function parseParams(Tokenizer $tokens, array $defaults = null) { $params = array(); while ($tokens->valid()) { if ($tokens->is(Tokenizer::MACRO_STRING)) { $key = $tokens->getAndNext(); if ($defaults && !isset($defaults[$key])) { throw new InvalidUsageException("Unknown parameter '{$key}'"); } if ($tokens->is("=")) { $tokens->next(); $params[$key] = $this->parseExpr($tokens); } else { throw new InvalidUsageException("Invalid value for parameter '{$key}'"); } } elseif ($tokens->is(Tokenizer::MACRO_SCALAR, '"', T_VARIABLE, "[", '(')) { $params[] = $this->parseExpr($tokens); } else { break; } } if ($defaults) { $params += $defaults; } return $params; }
/** * Define macro * * @param Tokenizer $tokens * @param Tag $scope * @throws InvalidUsageException */ public static function macroOpen(Tokenizer $tokens, Tag $scope) { $scope["name"] = $tokens->get(Tokenizer::MACRO_STRING); $scope["recursive"] = false; $args = array(); $defaults = array(); if (!$tokens->valid()) { return; } $tokens->next(); if ($tokens->is('(') || !$tokens->isNext(')')) { $tokens->next(); while ($tokens->is(Tokenizer::MACRO_STRING, T_VARIABLE)) { $param = $tokens->current(); if ($tokens->is(T_VARIABLE)) { $param = ltrim($param, '$'); } $tokens->next(); $args[] = $param; if ($tokens->is('=')) { $tokens->next(); if ($tokens->is(T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_DNUMBER) || $tokens->isSpecialVal()) { $defaults[$param] = $tokens->getAndNext(); } else { throw new InvalidUsageException("Macro parameters may have only scalar defaults"); } } $tokens->skipIf(','); } $tokens->skipIf(')'); } $scope["macro"] = array("name" => $scope["name"], "args" => $args, "defaults" => $defaults, "body" => "", "recursive" => false); return; }
public function testFixFloats() { $text = "1..3"; $tokens = new Tokenizer($text); $this->assertTrue($tokens->is(T_LNUMBER)); $this->assertTrue($tokens->next()->is('.')); $this->assertTrue($tokens->next()->is('.')); $this->assertTrue($tokens->next()->is(T_LNUMBER)); }