Exemplo n.º 1
0
 /**
  * Render a set of tokens with view substitutions
  *
  * @param  array $tokens
  * @param  mixed $view
  * @param  array|null $partials
  * @return string
  */
 public function render(array $tokens, $view, array $partials = null)
 {
     // Do some pre-initialization of variables used later in the routine
     $renderer = $this;
     $inLoop = false;
     if (is_scalar($view)) {
         // Iteration over lists will sometimes involve scalars
         $inLoop = true;
     }
     if (null === $partials) {
         $partials = [];
     }
     $rendered = '';
     foreach ($tokens as $token) {
         list($type, $data) = $token;
         if ($value = $this->handlePragmas($token, $view)) {
             $rendered .= $value;
             continue;
         }
         switch ($type) {
             case Lexer::TOKEN_CONTENT:
                 $rendered .= $data;
                 break;
             case Lexer::TOKEN_VARIABLE:
                 $value = $this->getValue($data, $view);
                 if (is_scalar($value)) {
                     if ($test = $this->handlePragmas($token, $value)) {
                         $rendered .= $test;
                         break;
                     }
                     $rendered .= '' === $value ? '' : $this->escape($value);
                     break;
                 }
                 $pragmaView = [$data => $value];
                 if ($test = $this->handlePragmas($token, $pragmaView)) {
                     $rendered .= $test;
                     break;
                 }
                 $rendered .= (string) $value;
                 break;
             case Lexer::TOKEN_VARIABLE_RAW:
                 $value = $this->getValue($data, $view);
                 $rendered .= $value;
                 break;
             case Lexer::TOKEN_SECTION:
                 if ($inLoop) {
                     // In a loop, with scalar values; skip
                     break;
                 }
                 $section = $this->getValue($data['name'], $view);
                 if (!$section) {
                     // Section is not a true value; skip
                     break;
                 }
                 // Build the section view
                 $sectionView = $section;
                 if (is_bool($section)) {
                     // For a boolean true, pass the current view
                     $sectionView = $view;
                 }
                 if (is_array($section) || $section instanceof Traversable) {
                     if (is_array($section) && $this->isAssocArray($section)) {
                         // Nested view; pass it as the view
                         $sectionView = $section;
                     } else {
                         // Iteration
                         $renderedSection = '';
                         foreach ($section as $sectionView) {
                             $renderedSection .= $this->render($data['content'], $sectionView);
                         }
                         $rendered .= $renderedSection;
                         break;
                     }
                 } elseif (is_callable($section) && $this->isValidCallback($section)) {
                     // Higher order section
                     // Execute the callback, passing it the section's template
                     // string, as well as a renderer lambda.
                     $mustache = $this->mustache;
                     $invokedPragmas = $this->invokedPragmas;
                     $rendered .= call_user_func($section, $data['template'], function ($text) use($renderer, $mustache, $view, $partials) {
                         $tokens = $mustache->tokenize($text);
                         return $renderer->render($tokens, $view, $partials);
                     });
                     $this->registerPragmas($invokedPragmas);
                     break;
                 } elseif (is_object($section)) {
                     // In this case, the child object is the view.
                     $sectionView = $section;
                 } else {
                     // All other types, simply pass the current view
                     $sectionView = $view;
                 }
                 // Render the section
                 $invokedPragmas = $this->invokedPragmas;
                 $rendered .= $this->render($data['content'], $sectionView);
                 $this->registerPragmas($invokedPragmas);
                 break;
             case Lexer::TOKEN_SECTION_INVERT:
                 if ($inLoop) {
                     // In a loop, with scalar values; skip
                     break;
                 }
                 $section = $this->getValue($data['name'], $view);
                 if ($section) {
                     // If a value exists for the section, we skip it
                     $rendered .= '';
                     break;
                 }
                 // Otherwise, we render it
                 $invokedPragmas = $this->invokedPragmas;
                 $rendered .= $this->render($data['content'], $view);
                 $this->registerPragmas($invokedPragmas);
                 break;
             case Lexer::TOKEN_PLACEHOLDER:
                 if ($inLoop) {
                     // In a loop, with scalar values; skip
                     break;
                 }
                 $rendered .= $this->render($data['content'], $view);
                 break;
             case Lexer::TOKEN_PARTIAL:
                 if ($inLoop) {
                     // In a loop, with scalar values; skip
                     break;
                 }
                 $invokedPragmas = $this->invokedPragmas;
                 $this->clearInvokedPragmas();
                 if (!isset($data['tokens'])) {
                     $name = $data['partial'];
                     if (isset($partials[$data['partial']])) {
                         // Partial invoked is an aliased partial
                         $rendered .= $this->render($partials[$data['partial']], $view);
                     } else {
                         $partialTokens = $this->mustache->tokenize($data['partial']);
                         $rendered .= $this->render($partialTokens, $view);
                     }
                     $this->registerPragmas($invokedPragmas);
                     break;
                 }
                 $rendered .= $this->render($data['tokens'], $view);
                 $this->registerPragmas($invokedPragmas);
                 break;
             case Lexer::TOKEN_PRAGMA:
                 $this->registerPragma($data);
                 break;
             case Lexer::TOKEN_DELIM_SET:
             case Lexer::TOKEN_COMMENT:
             default:
                 // do nothing; only necessary for tokenization/parsing
                 break;
         }
     }
     return $rendered;
 }