/** * Process handlebars section style * * @param Context $context current context * @param array $current section node data * * @return mixed|string */ private function _handlebarsStyleSection(Context $context, $current) { $helpers = $this->handlebars->getHelpers(); $sectionName = $current[Tokenizer::NAME]; if (isset($current[Tokenizer::END])) { $source = substr($this->getSource(), $current[Tokenizer::INDEX], $current[Tokenizer::END] - $current[Tokenizer::INDEX]); } else { $source = ''; } // subexpression parsing loop $subexprs = array(); // will contain all subexpressions inside outermost brackets $insideOf = array('single' => false, 'double' => false); $lvl = 0; $cur_start = 0; for ($i = 0; $i < strlen($current[Tokenizer::ARGS]); $i++) { $cur = substr($current[Tokenizer::ARGS], $i, 1); if ($cur == "'") { $insideOf['single'] = !$insideOf['single']; } if ($cur == '"') { $insideOf['double'] = !$insideOf['double']; } if ($cur == '(' && !$insideOf['single'] && !$insideOf['double']) { if ($lvl == 0) { $cur_start = $i + 1; } $lvl++; continue; } if ($cur == ')' && !$insideOf['single'] && !$insideOf['double']) { $lvl--; if ($lvl == 0) { $subexprs[] = substr($current[Tokenizer::ARGS], $cur_start, $i - $cur_start); } } } if (!empty($subexprs)) { foreach ($subexprs as $expr) { $cmd = explode(" ", $expr); $name = trim($cmd[0]); // construct artificial section node $section_node = array(Tokenizer::TYPE => Tokenizer::T_ESCAPED, Tokenizer::NAME => $name, Tokenizer::OTAG => $current[Tokenizer::OTAG], Tokenizer::CTAG => $current[Tokenizer::CTAG], Tokenizer::INDEX => $current[Tokenizer::INDEX], Tokenizer::ARGS => implode(" ", array_slice($cmd, 1))); // resolve the node recursively $resolved = addcslashes($this->_handlebarsStyleSection($context, $section_node), '"'); // replace original subexpression with result $current[Tokenizer::ARGS] = str_replace('(' . $expr . ')', '"' . $resolved . '"', $current[Tokenizer::ARGS]); } } $return = $helpers->call($sectionName, $this, $context, $current[Tokenizer::ARGS], $source); if ($return instanceof String) { return $this->handlebars->loadString($return)->render($context); } else { return $return; } }
/** * Process section nodes * * @param Context $context current context * @param array $current section node data * * @throws \RuntimeException * @return string the result */ private function _section(Context $context, $current) { $helpers = $this->handlebars->getHelpers(); $sectionName = $current[Tokenizer::NAME]; if ($helpers->has($sectionName)) { if (isset($current[Tokenizer::END])) { $source = substr($this->getSource(), $current[Tokenizer::INDEX], $current[Tokenizer::END] - $current[Tokenizer::INDEX]); } else { $source = ''; } $params = array($this, $context, $current[Tokenizer::ARGS], $source); $return = call_user_func_array($helpers->{$sectionName}, $params); if ($return instanceof String) { return $this->handlebars->loadString($return)->render($context); } else { return $return; } } elseif (trim($current[Tokenizer::ARGS]) == '') { // fallback to mustache style each/with/for just if there is // no argument at all. try { $sectionVar = $context->get($sectionName, true); } catch (\InvalidArgumentException $e) { throw new \RuntimeException($sectionName . ' is not registered as a helper'); } $buffer = ''; if (is_array($sectionVar) || $sectionVar instanceof \Traversable) { foreach ($sectionVar as $index => $d) { $context->pushIndex($index); $context->push($d); $buffer .= $this->render($context); $context->pop(); $context->popIndex(); } } elseif (is_object($sectionVar)) { //Act like with $context->push($sectionVar); $buffer = $this->render($context); $context->pop(); } elseif ($sectionVar) { $buffer = $this->render($context); } return $buffer; } else { throw new \RuntimeException($sectionName . ' is not registered as a helper'); } }
/** * Process handlebars section style * * @param Handlebars_Context $context current context * @param array $current section node data * * @return {mixed|string} */ private function _handlebarsStyleSection(Handlebars_Context $context, $current) { $helpers = $this->handlebars->getHelpers(); $sectionName = $current[Handlebars_Tokenizer::NAME]; if (isset($current[Handlebars_Tokenizer::END])) { $source = substr($this->getSource(), $current[Handlebars_Tokenizer::INDEX], $current[Handlebars_Tokenizer::END] - $current[Handlebars_Tokenizer::INDEX]); } else { $source = ''; } // subexpression parsing loop $subexprs = array(); // will contain all subexpressions inside outermost brackets $insideOf = array('single' => false, 'double' => false); $lvl = 0; $cur_start = 0; for ($i = 0; $i < strlen($current[Handlebars_Tokenizer::ARGS]); $i++) { $cur = substr($current[Handlebars_Tokenizer::ARGS], $i, 1); if ($cur == "'") { $insideOf['single'] = !$insideOf['single']; } if ($cur == '"') { $insideOf['double'] = !$insideOf['double']; } if ($cur == '(' && !$insideOf['single'] && !$insideOf['double']) { if ($lvl == 0) { $cur_start = $i + 1; } $lvl++; continue; } if ($cur == ')' && !$insideOf['single'] && !$insideOf['double']) { $lvl--; if ($lvl == 0) { $subexprs[] = substr($current[Handlebars_Tokenizer::ARGS], $cur_start, $i - $cur_start); } } } if (!empty($subexprs)) { foreach ($subexprs as $expr) { $cmd = explode(" ", $expr); $name = trim($cmd[0]); // construct artificial section node $section_node = array(Handlebars_Tokenizer::TYPE => Handlebars_Tokenizer::T_ESCAPED, Handlebars_Tokenizer::NAME => $name, Handlebars_Tokenizer::OTAG => $current[Handlebars_Tokenizer::OTAG], Handlebars_Tokenizer::CTAG => $current[Handlebars_Tokenizer::CTAG], Handlebars_Tokenizer::INDEX => $current[Handlebars_Tokenizer::INDEX], Handlebars_Tokenizer::ARGS => implode(" ", array_slice($cmd, 1))); // resolve the node recursively $resolved = addcslashes($this->_handlebarsStyleSection($context, $section_node), '"'); // replace original subexpression with result $current[Handlebars_Tokenizer::ARGS] = str_replace('(' . $expr . ')', '"' . $resolved . '"', $current[Handlebars_Tokenizer::ARGS]); } } $pattern = '/(([A-Z][A-Z0-9]*)=)|(true|false|([0-9\\.]+)|(["]).*?([^\\\\]["]))/i'; preg_match_all($pattern, $current[Handlebars_Tokenizer::ARGS], $matches); $args = array(); $m = $matches[0]; $c = count($m); for ($i = 0; $i < $c; ++$i) { if (substr($m[$i], -1) === '=') { $key = substr($m[$i], 0, strlen($m[$i]) - 1); $args['hash'][$key] = json_decode($m[$i + 1], true); ++$i; } else { $args[] = json_decode($m[$i], true); } } $return = $helpers->call($sectionName, $this, $context, $args, $source); if ($return instanceof Handlebars_String) { return $this->handlebars->loadString($return)->render($context); } else { return $return; } }