Subversion Repositories ALCASAR

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
2809 rexy 1
<?php
2
 
3
/**
4
 * Inheritance Runtime Methods processBlock, endChild, init
5
 *
6
 * @package    Smarty
7
 * @subpackage PluginsInternal
8
 * @author     Uwe Tews
9
 **/
10
class Smarty_Internal_Runtime_Inheritance
11
{
12
    /**
13
     * State machine
14
     * - 0 idle next extends will create a new inheritance tree
15
     * - 1 processing child template
16
     * - 2 wait for next inheritance template
17
     * - 3 assume parent template, if child will loaded goto state 1
18
     *     a call to a sub template resets the state to 0
19
     *
20
     * @var int
21
     */
22
    public $state = 0;
23
 
24
    /**
25
     * Array of root child {block} objects
26
     *
27
     * @var Smarty_Internal_Block[]
28
     */
29
    public $childRoot = array();
30
 
31
    /**
32
     * inheritance template nesting level
33
     *
34
     * @var int
35
     */
36
    public $inheritanceLevel = 0;
37
 
38
    /**
39
     * inheritance template index
40
     *
41
     * @var int
42
     */
43
    public $tplIndex = -1;
44
 
45
    /**
46
     * Array of template source objects
47
     *
48
     * @var Smarty_Template_Source[]
49
     */
50
    public $sources = array();
51
 
52
    /**
53
     * Stack of source objects while executing block code
54
     *
55
     * @var Smarty_Template_Source[]
56
     */
57
    public $sourceStack = array();
58
 
59
    /**
60
     * Initialize inheritance
61
     *
62
     * @param \Smarty_Internal_Template $tpl        template object of caller
63
     * @param bool                      $initChild  if true init for child template
64
     * @param array                     $blockNames outer level block name
65
     */
66
    public function init(Smarty_Internal_Template $tpl, $initChild, $blockNames = array())
67
    {
68
        // if called while executing parent template it must be a sub-template with new inheritance root
69
        if ($initChild && $this->state === 3 && (strpos($tpl->template_resource, 'extendsall') === false)) {
70
            $tpl->inheritance = new Smarty_Internal_Runtime_Inheritance();
71
            $tpl->inheritance->init($tpl, $initChild, $blockNames);
72
            return;
73
        }
74
        ++$this->tplIndex;
75
        $this->sources[ $this->tplIndex ] = $tpl->source;
76
        // start of child sub template(s)
77
        if ($initChild) {
78
            $this->state = 1;
79
            if (!$this->inheritanceLevel) {
80
                //grab any output of child templates
81
                ob_start();
82
            }
83
            ++$this->inheritanceLevel;
84
            //           $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart');
85
            //           $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd');
86
        }
87
        // if state was waiting for parent change state to parent
88
        if ($this->state === 2) {
89
            $this->state = 3;
90
        }
91
    }
92
 
93
    /**
94
     * End of child template(s)
95
     * - if outer level is reached flush output buffer and switch to wait for parent template state
96
     *
97
     * @param \Smarty_Internal_Template $tpl
98
     * @param null|string               $template optional name of inheritance parent template
99
     * @param null|string               $uid      uid of inline template
100
     * @param null|string               $func     function call name of inline template
101
     *
102
     * @throws \Exception
103
     * @throws \SmartyException
104
     */
105
    public function endChild(Smarty_Internal_Template $tpl, $template = null, $uid = null, $func = null)
106
    {
107
        --$this->inheritanceLevel;
108
        if (!$this->inheritanceLevel) {
109
            ob_end_clean();
110
            $this->state = 2;
111
        }
112
        if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends')
113
                                 || $tpl->smarty->extends_recursion)
114
        ) {
115
            $tpl->_subTemplateRender(
116
                $template,
117
                $tpl->cache_id,
118
                $tpl->compile_id,
119
                $tpl->caching ? 9999 : 0,
120
                $tpl->cache_lifetime,
121
                array(),
122
                2,
123
                false,
124
                $uid,
125
                $func
126
            );
127
        }
128
    }
129
 
130
    /**
131
     * Smarty_Internal_Block constructor.
132
     * - if outer level {block} of child template ($state === 1) save it as child root block
133
     * - otherwise process inheritance and render
134
     *
135
     * @param \Smarty_Internal_Template $tpl
136
     * @param                           $className
137
     * @param string                    $name
138
     * @param int|null                  $tplIndex index of outer level {block} if nested
139
     *
140
     * @throws \SmartyException
141
     */
142
    public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null)
143
    {
144
        $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex);
145
        if (isset($this->childRoot[ $name ])) {
146
            $block->child = $this->childRoot[ $name ];
147
        }
148
        if ($this->state === 1) {
149
            $this->childRoot[ $name ] = $block;
150
            return;
151
        }
152
        // make sure we got child block of child template of current block
153
        while ($block->child && $block->child->child && $block->tplIndex <= $block->child->tplIndex) {
154
            $block->child = $block->child->child;
155
        }
156
        $this->process($tpl, $block);
157
    }
158
 
159
    /**
160
     * Goto child block or render this
161
     *
162
     * @param \Smarty_Internal_Template   $tpl
163
     * @param \Smarty_Internal_Block      $block
164
     * @param \Smarty_Internal_Block|null $parent
165
     *
166
     * @throws \SmartyException
167
     */
168
    public function process(
169
        Smarty_Internal_Template $tpl,
170
        Smarty_Internal_Block $block,
171
        Smarty_Internal_Block $parent = null
172
    ) {
173
        if ($block->hide && !isset($block->child)) {
174
            return;
175
        }
176
        if (isset($block->child) && $block->child->hide && !isset($block->child->child)) {
177
            $block->child = null;
178
        }
179
        $block->parent = $parent;
180
        if ($block->append && !$block->prepend && isset($parent)) {
181
            $this->callParent($tpl, $block, '\'{block append}\'');
182
        }
183
        if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) {
184
            $this->callBlock($block, $tpl);
185
        } else {
186
            $this->process($tpl, $block->child, $block);
187
        }
188
        if ($block->prepend && isset($parent)) {
189
            $this->callParent($tpl, $block, '{block prepend}');
190
            if ($block->append) {
191
                if ($block->callsChild || !isset($block->child)
192
                    || ($block->child->hide && !isset($block->child->child))
193
                ) {
194
                    $this->callBlock($block, $tpl);
195
                } else {
196
                    $this->process($tpl, $block->child, $block);
197
                }
198
            }
199
        }
200
        $block->parent = null;
201
    }
202
 
203
    /**
204
     * Render child on \$smarty.block.child
205
     *
206
     * @param \Smarty_Internal_Template $tpl
207
     * @param \Smarty_Internal_Block    $block
208
     *
209
     * @return null|string block content
210
     * @throws \SmartyException
211
     */
212
    public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block)
213
    {
214
        if (isset($block->child)) {
215
            $this->process($tpl, $block->child, $block);
216
        }
217
    }
218
 
219
    /**
220
     * Render parent block on \$smarty.block.parent or {block append/prepend}
221
     *
222
     * @param \Smarty_Internal_Template $tpl
223
     * @param \Smarty_Internal_Block    $block
224
     * @param string                    $tag
225
     *
226
     * @return null|string  block content
227
     * @throws \SmartyException
228
     */
229
    public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $tag)
230
    {
231
        if (isset($block->parent)) {
232
            $this->callBlock($block->parent, $tpl);
233
        } else {
234
            throw new SmartyException("inheritance: illegal '{$tag}' used in child template '{$tpl->inheritance->sources[$block->tplIndex]->filepath}' block '{$block->name}'");
235
        }
236
    }
237
 
238
    /**
239
     * render block
240
     *
241
     * @param \Smarty_Internal_Block    $block
242
     * @param \Smarty_Internal_Template $tpl
243
     */
244
    public function callBlock(Smarty_Internal_Block $block, Smarty_Internal_Template $tpl)
245
    {
246
        $this->sourceStack[] = $tpl->source;
247
        $tpl->source = $this->sources[ $block->tplIndex ];
248
        $block->callBlock($tpl);
249
        $tpl->source = array_pop($this->sourceStack);
250
    }
251
}