Completed
Branch master (e379bd)
by Pierre-Henry
33:06
created

Smarty_Internal_Runtime_Inheritance   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 231
rs 8.4864
c 0
b 0
f 0
wmc 48
lcom 1
cbo 4

2 Methods

Rating   Name   Duplication   Size   Complexity  
C init() 0 27 7
B endChild() 0 12 7

How to fix   Complexity   

Complex Class

Complex classes like Smarty_Internal_Runtime_Inheritance often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Smarty_Internal_Runtime_Inheritance, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Inheritance Runtime Methods processBlock, endChild, init
5
 *
6
 * @package    Smarty
7
 * @subpackage PluginsInternal
8
 * @author     Uwe Tews
9
 *
10
 **/
11
class Smarty_Internal_Runtime_Inheritance
12
{
13
14
    /**
15
     * State machine
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
21
     *
22
     * @var int
23
     */
24
    public $state = 0;
25
26
    /**
27
     * Array of root child {block} objects
28
     *
29
     * @var Smarty_Internal_Block[]
30
     */
31
    public $childRoot = array();
32
33
    /**
34
     * inheritance template nesting level
35
     *
36
     * @var int
37
     */
38
    public $inheritanceLevel = 0;
39
40
    /**
41
     * inheritance template index
42
     *
43
     * @var int
44
     */
45
    public $tplIndex = - 1;
46
47
    /**
48
     * Array of template source objects
49
     * - key template index
50
     *
51
     * @var Smarty_Template_Source[]
52
     */
53
    public $sources = array();
54
55
    /**
56
     * Stack of source objects while executing block code
57
     *
58
     * @var Smarty_Template_Source[]
59
     */
60
    public $sourceStack = array();
61
62
    /**
63
     * Initialize inheritance
64
     *
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
68
     *
69
     */
70
    public function init(Smarty_Internal_Template $tpl, $initChild, $blockNames = array())
71
    {
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);
76
            return;
77
        }
78
        $this->tplIndex ++;
79
        $this->sources[ $this->tplIndex ] = $tpl->source;
80
81
        // start of child sub template(s)
82
        if ($initChild) {
83
            $this->state = 1;
84
            if (!$this->inheritanceLevel) {
85
                //grab any output of child templates
86
                ob_start();
87
            }
88
            $this->inheritanceLevel ++;
89
            //           $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
90
            //           $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
91
        }
92
        // if state was waiting for parent change state to parent
93
        if ($this->state == 2) {
94
            $this->state = 3;
95
        }
96
    }
97
98
    /**
99
     * End of child template(s)
100
     * - if outer level is reached flush output buffer and switch to wait for parent template state
101
     *
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
106
     */
107
    public function endChild(Smarty_Internal_Template $tpl, $template = null, $uid = null, $func = null)
108
    {
109
        $this->inheritanceLevel --;
110
        if (!$this->inheritanceLevel) {
111
            ob_end_clean();
112
            $this->state = 2;
113
        }
114
        if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') || $tpl->smarty->extends_recursion)) {
0 ignored issues
show
Bug introduced by
The property source does not seem to exist in Smarty_Internal_Data.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
115
            $tpl->_subTemplateRender($template, $tpl->cache_id, $tpl->compile_id, $tpl->caching ? 9999 : 0,
116
                                     $tpl->cache_lifetime, array(), 2, false, $uid, $func);
117
        }
118
    }
119
120
    /**
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
124
     *
125
     * @param \Smarty_Internal_Template $tpl
126
     * @param                           $className
127
     * @param string                    $name
128
     * @param int|null                  $tplIndex index of outer level {block} if nested
129
     */
130
    public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null)
131
    {
132
        $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex);
133
        if (isset($this->childRoot[ $name ])) {
134
            $block->child = $this->childRoot[ $name ];
135
        }
136
        if ($this->state == 1) {
137
            $this->childRoot[ $name ] = $block;
138
            return;
139
        }
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;
143
        }
144
        $this->process($tpl, $block);
145
    }
146
147
    /**
148
     * Goto child block or render this
149
     *
150
     * @param \Smarty_Internal_Template   $tpl
151
     * @param \Smarty_Internal_Block      $block
152
     * @param \Smarty_Internal_Block|null $parent
153
     *
154
     * @throws \SmartyException
155
     */
156
    public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block,
157
                            Smarty_Internal_Block $parent = null)
158
    {
159
        if ($block->hide && !isset($block->child)) {
160
            return;
161
        }
162
        if (isset($block->child) && $block->child->hide && !isset($block->child->child)) {
163
            $block->child = null;
164
        }
165
        $block->parent = $parent;
166
        if ($block->append && !$block->prepend && isset($parent)) {
167
            $this->callParent($tpl, $block);
168
        }
169
        if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) {
170
            $this->callBlock($block, $tpl);
171
        } else {
172
            $this->process($tpl, $block->child, $block);
173
        }
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))
179
                ) {
180
                    $this->callBlock($block, $tpl);
181
                } else {
182
                    $this->process($tpl, $block->child, $block);
183
                }
184
            }
185
        }
186
        $block->parent = null;
187
    }
188
189
    /**
190
     * Render child on {$smarty.block.child}
191
     *
192
     * @param \Smarty_Internal_Template $tpl
193
     * @param \Smarty_Internal_Block    $block
194
     */
195
    public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block)
196
    {
197
        if (isset($block->child)) {
198
            $this->process($tpl, $block->child, $block);
199
        }
200
    }
201
202
    /**
203
     * Render parent on {$smarty.block.parent} or {block append/prepend}     *
204
     *
205
     * @param \Smarty_Internal_Template $tpl
206
     * @param \Smarty_Internal_Block    $block
207
     *
208
     * @param null                      $name
209
     *
210
     * @throws \SmartyException
211
     */
212
    public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $name = null)
213
    {
214
        if (isset($name)) {
215
            $block = $block->parent;
216
            while (isset($block)) {
217
                if (isset($block->subBlocks[ $name ])) {
0 ignored issues
show
Bug introduced by
The property subBlocks does not seem to exist in Smarty_Internal_Block.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
218
                } else {
219
                    $block = $block->parent;
220
                }
221
            }
222
            return;
223
        } else if (isset($block->parent)) {
224
            $this->callBlock($block->parent, $tpl);
225
        } else {
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}'");
227
        }
228
    }
229
230
    /**
231
     * @param \Smarty_Internal_Block    $block
232
     * @param \Smarty_Internal_Template $tpl
233
     */
234
    public function callBlock(Smarty_Internal_Block $block, Smarty_Internal_Template $tpl)
235
    {
236
        $this->sourceStack[] = $tpl->source;
237
        $tpl->source = $this->sources[ $block->tplIndex ];
238
        $block->callBlock($tpl);
239
        $tpl->source = array_pop($this->sourceStack);
240
    }
241
}
242