4 * Inheritance Runtime Methods processBlock, endChild, init
7 * @subpackage PluginsInternal
11 class Smarty_Internal_Runtime_Inheritance
16 * - 0 idle next extends will create a new inheritance tree
17 * - 1 processing child template
18 * - 2 wait for next inheritance template
19 * - 3 assume parent template, if child will loaded goto state 1
20 * a call to a sub template resets the state to 0
27 * Array of root child {block} objects
29 * @var Smarty_Internal_Block[]
31 public $childRoot = array();
34 * inheritance template nesting level
38 public $inheritanceLevel = 0;
41 * inheritance template index
45 public $tplIndex = - 1;
48 * Array of template source objects
49 * - key template index
51 * @var Smarty_Template_Source[]
53 public $sources = array();
56 * Stack of source objects while executing block code
58 * @var Smarty_Template_Source[]
60 public $sourceStack = array();
63 * Initialize inheritance
65 * @param \Smarty_Internal_Template $tpl template object of caller
66 * @param bool $initChild if true init for child template
67 * @param array $blockNames outer level block name
70 public function init(Smarty_Internal_Template $tpl, $initChild, $blockNames = array())
72 // if called while executing parent template it must be a sub-template with new inheritance root
73 if ($initChild && $this->state == 3 && (strpos($tpl->template_resource, 'extendsall') === false)) {
74 $tpl->inheritance = new Smarty_Internal_Runtime_Inheritance();
75 $tpl->inheritance->init($tpl, $initChild, $blockNames);
79 $this->sources[ $this->tplIndex ] = $tpl->source;
81 // start of child sub template(s)
84 if (!$this->inheritanceLevel) {
85 //grab any output of child templates
88 $this->inheritanceLevel ++;
89 // $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart');
90 // $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd');
92 // if state was waiting for parent change state to parent
93 if ($this->state == 2) {
99 * End of child template(s)
100 * - if outer level is reached flush output buffer and switch to wait for parent template state
102 * @param \Smarty_Internal_Template $tpl
103 * @param null|string $template optinal name of inheritance parent template
104 * @param null|string $uid uid of inline template
105 * @param null|string $func function call name of inline template
107 public function endChild(Smarty_Internal_Template $tpl, $template = null, $uid = null, $func = null)
109 $this->inheritanceLevel --;
110 if (!$this->inheritanceLevel) {
114 if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') || $tpl->smarty->extends_recursion)) {
115 $tpl->_subTemplateRender($template, $tpl->cache_id, $tpl->compile_id, $tpl->caching ? 9999 : 0,
116 $tpl->cache_lifetime, array(), 2, false, $uid, $func);
121 * Smarty_Internal_Block constructor.
122 * - if outer level {block} of child template ($state == 1) save it as child root block
123 * - otherwise process inheritance and render
125 * @param \Smarty_Internal_Template $tpl
127 * @param string $name
128 * @param int|null $tplIndex index of outer level {block} if nested
130 public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null)
132 $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex);
133 if (isset($this->childRoot[ $name ])) {
134 $block->child = $this->childRoot[ $name ];
136 if ($this->state == 1) {
137 $this->childRoot[ $name ] = $block;
140 // make sure we got child block of child template of current block
141 while ($block->child && $block->tplIndex <= $block->child->tplIndex) {
142 $block->child = $block->child->child;
144 $this->process($tpl, $block);
148 * Goto child block or render this
150 * @param \Smarty_Internal_Template $tpl
151 * @param \Smarty_Internal_Block $block
152 * @param \Smarty_Internal_Block|null $parent
154 * @throws \SmartyException
156 public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block,
157 Smarty_Internal_Block $parent = null)
159 if ($block->hide && !isset($block->child)) {
162 if (isset($block->child) && $block->child->hide && !isset($block->child->child)) {
163 $block->child = null;
165 $block->parent = $parent;
166 if ($block->append && !$block->prepend && isset($parent)) {
167 $this->callParent($tpl, $block);
169 if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) {
170 $this->callBlock($block, $tpl);
172 $this->process($tpl, $block->child, $block);
174 if ($block->prepend && isset($parent)) {
175 $this->callParent($tpl, $block);
176 if ($block->append) {
177 if ($block->callsChild || !isset($block->child) ||
178 ($block->child->hide && !isset($block->child->child))
180 $this->callBlock($block, $tpl);
182 $this->process($tpl, $block->child, $block);
186 $block->parent = null;
190 * Render child on {$smarty.block.child}
192 * @param \Smarty_Internal_Template $tpl
193 * @param \Smarty_Internal_Block $block
195 public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block)
197 if (isset($block->child)) {
198 $this->process($tpl, $block->child, $block);
203 * Render parent on {$smarty.block.parent} or {block append/prepend} *
205 * @param \Smarty_Internal_Template $tpl
206 * @param \Smarty_Internal_Block $block
210 * @throws \SmartyException
212 public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $name = null)
215 $block = $block->parent;
216 while (isset($block)) {
217 if (isset($block->subBlocks[ $name ])) {
219 $block = $block->parent;
223 } else if (isset($block->parent)) {
224 $this->callBlock($block->parent, $tpl);
226 throw new SmartyException("inheritance: illegal {\$smarty.block.parent} or {block append/prepend} used in parent template '{$tpl->inheritance->sources[$block->tplIndex]->filepath}' block '{$block->name}'");
231 * @param \Smarty_Internal_Block $block
232 * @param \Smarty_Internal_Template $tpl
234 public function callBlock(Smarty_Internal_Block $block, Smarty_Internal_Template $tpl)
236 $this->sourceStack[] = $tpl->source;
237 $tpl->source = $this->sources[ $block->tplIndex ];
238 $block->callBlock($tpl);
239 $tpl->source = array_pop($this->sourceStack);