state === 3 && (strpos($tpl->template_resource, 'extendsall') === false)) { $tpl->setInheritance(clone $tpl->getSmarty()->getRuntime('Inheritance')); $tpl->getInheritance()->init($tpl, $initChild, $blockNames); return; } ++$this->tplIndex; $this->sources[$this->tplIndex] = $tpl->getSource(); // start of child sub template(s) if ($initChild) { $this->state = 1; if (!$this->inheritanceLevel) { //grab any output of child templates ob_start(); } ++$this->inheritanceLevel; } // if state was waiting for parent change state to parent if ($this->state === 2) { $this->state = 3; } } /** * End of child template(s) * - if outer level is reached flush output buffer and switch to wait for parent template state * * @param \Smarty\Template $tpl * @param null|string $template optional name of inheritance parent template * * @throws \Exception * @throws \Smarty\Exception */ public function endChild(Template $tpl, $template = null, ?string $currentDir = null) { --$this->inheritanceLevel; if (!$this->inheritanceLevel) { ob_end_clean(); $this->state = 2; } if (isset($template)) { $tpl->renderSubTemplate( $template, $tpl->cache_id, $tpl->compile_id, $tpl->caching ? \Smarty\Template::CACHING_NOCACHE_CODE : 0, $tpl->cache_lifetime, [], null, $currentDir ); } } /** * \Smarty\Runtime\Block constructor. * - if outer level {block} of child template ($state === 1) save it as child root block * - otherwise process inheritance and render * * @param \Smarty\Template $tpl * @param $className * @param string $name * @param int|null $tplIndex index of outer level {block} if nested * * @throws \Smarty\Exception */ public function instanceBlock(Template $tpl, $className, $name, $tplIndex = null) { $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex); if (isset($this->childRoot[$name])) { $block->child = $this->childRoot[$name]; } if ($this->state === 1) { $this->childRoot[$name] = $block; return; } // make sure we got child block of child template of current block while ($block->child && $block->child->child && $block->tplIndex <= $block->child->tplIndex) { $block->child = $block->child->child; } $this->processBlock($tpl, $block); } /** * Goto child block or render this * * @param Template $tpl * @param \Smarty\Runtime\Block $block * @param \Smarty\Runtime\Block|null $parent * * @throws Exception */ private function processBlock( Template $tpl, \Smarty\Runtime\Block $block, \Smarty\Runtime\Block $parent = null ) { if ($block->hide && !isset($block->child)) { return; } if (isset($block->child) && $block->child->hide && !isset($block->child->child)) { $block->child = null; } $block->parent = $parent; if ($block->append && !$block->prepend && isset($parent)) { $this->callParent($tpl, $block, '\'{block append}\''); } if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) { $this->callBlock($block, $tpl); } else { $this->processBlock($tpl, $block->child, $block); } if ($block->prepend && isset($parent)) { $this->callParent($tpl, $block, '{block prepend}'); if ($block->append) { if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child)) ) { $this->callBlock($block, $tpl); } else { $this->processBlock($tpl, $block->child, $block); } } } $block->parent = null; } /** * Render child on \$smarty.block.child * * @param Template $tpl * @param \Smarty\Runtime\Block $block * * @return null|string block content * @throws Exception */ public function callChild(Template $tpl, \Smarty\Runtime\Block $block) { if (isset($block->child)) { $this->processBlock($tpl, $block->child, $block); } } /** * Render parent block on \$smarty.block.parent or {block append/prepend} * * @param Template $tpl * @param \Smarty\Runtime\Block $block * @param string $tag * * @return null|string block content * @throws Exception */ public function callParent(Template $tpl, \Smarty\Runtime\Block $block) { if (isset($block->parent)) { $this->callBlock($block->parent, $tpl); } else { throw new Exception("inheritance: illegal '{\$smarty.block.parent}' used in child template '" . "{$tpl->getInheritance()->sources[$block->tplIndex]->getResourceName()}' block '{$block->name}'"); } } /** * render block * * @param \Smarty\Runtime\Block $block * @param Template $tpl */ public function callBlock(\Smarty\Runtime\Block $block, Template $tpl) { $this->sourceStack[] = $tpl->getSource(); $tpl->setSource($this->sources[$block->tplIndex]); $block->callBlock($tpl); $tpl->setSource(array_pop($this->sourceStack)); } }