blockNesting || $this->state == 3)) { $tpl->ext->_inheritance = new Smarty_Internal_Runtime_Inheritance(); $tpl->ext->_inheritance->init($tpl, $initChild, $blockNames); return; } // start of child sub template(s) if ($initChild) { $this->state = 1; if (!$this->inheritanceLevel) { //grab any output of child templates ob_start(); } $this->inheritanceLevel ++; } // in parent state {include} will not increment template index if ($this->state != 3) { $this->tplIndex ++; } // 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_Internal_Template $tpl template object of caller */ public function endChild(Smarty_Internal_Template $tpl) { $this->inheritanceLevel --; if (!$this->inheritanceLevel) { ob_end_clean(); $this->state = 2; } } /** * Process inheritance {block} tag * * $type 0 = {block}: * - search in inheritance template hierarchy for child blocks * if found call it, otherwise call current block * - ignored for outer level blocks in child templates * * $type 1 = {block}: * - nested {block} * - search in inheritance template hierarchy for child blocks * if found call it, otherwise call current block * * $type 2 = {$smarty.block.child}: * - search in inheritance template hierarchy for child blocks * if found call it, otherwise ignore * * $type 3 = {$smarty.block.parent}: * - get block id from parent stack and call parent block * * @param \Smarty_Internal_Template $tpl template object of caller * @param int $type call type see above * @param string $name block name * @param array $block block parameter * @param array $callStack call stack with block parameters * * @throws \SmartyException */ public function processBlock(Smarty_Internal_Template $tpl, $type = 0, $name, $block, $callStack = array()) { if (!isset($this->blockParameter[$name])) { $this->blockParameter[$name] = array(); } if ($this->state == 1) { $block[2] = count($this->blockParameter[$name]); $block[3] = $this->tplIndex; $this->blockParameter[$name][] = $block; return; } if ($type == 3) { if (!empty($callStack)) { array_shift($callStack); if (empty($callStack)) { throw new SmartyException("inheritance: tag {\$smarty.block.parent} used in parent template block '{$name}'"); } $block = array_shift($callStack); } else { return; } } else { $blockParameter = &$this->blockParameter[$name]; if ($type == 0) { $index = $block[2] = count($blockParameter); $block[3] = $this->tplIndex; $callStack = array(&$block); } elseif ($type == 1) { $block[3] = $callStack[0][3]; $index = 0; for ($i = 0; $i < count($blockParameter); $i ++) { if ($blockParameter[$i][3] <= $block[3]) { $index = $blockParameter[$i][2]; } } $block[2] = $index; $callStack = array(&$block); } else { $index = $callStack[0][2]; if ($index == 0) { return; } $callStack = $block = array(1 => false); } $index --; // find lowest level child block while ($index >= 0 && ($type || !$block[1])) { $block = &$blockParameter[$index]; array_unshift($callStack, $block); if ($block[1]) { break; } $index --; } if (isset($block['hide']) && $index <= 0) { return; } } $this->blockNesting ++; if (isset($block['append'])) { $this->processBlock($tpl, 3, $name, null, $callStack); } if (isset($block[6])) { $block[6]($tpl, $callStack); } else { $block[0]($tpl, $callStack); } if (isset($block['prepend'])) { $this->processBlock($tpl, 3, $name, null, $callStack); } $this->blockNesting --; } }