GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — v0.89-develop ( f6bbce...af3048 )
by Zordius
02:31
created

Runtime::sec()   F

Complexity

Conditions 38
Paths > 20000

Size

Total Lines 116
Code Lines 77

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 90
CRAP Score 38.0148

Importance

Changes 6
Bugs 2 Features 0
Metric Value
c 6
b 2
f 0
dl 0
loc 116
ccs 90
cts 92
cp 0.9783
rs 2
cc 38
eloc 77
nc 41964
nop 6
crap 38.0148

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Bug introduced by
Unexpected token: :, line: 413, col: 17, file: src/Runtime.php.
Loading history...
2
/*
3
4
Copyrights for code authored by Yahoo! Inc. is licensed under the following terms:
5
MIT License
6
Copyright (c) 2013-2015 Yahoo! Inc. All Rights Reserved.
7
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10
11
Origin: https://github.com/zordius/lightncandy
12
*/
13
14
/**
15
 * file to support LightnCandy compiled PHP runtime
16
 *
17
 * @package    LightnCandy
18
 * @author     Zordius <[email protected]>
19
 */
20
21
namespace LightnCandy;
22
23
/**
24
 * LightnCandy class for compiled PHP runtime.
25
 */
26
class Runtime {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the opening brace for this class should be on a new line.
Loading history...
27
    const DEBUG_ERROR_LOG = 1;
28
    const DEBUG_ERROR_EXCEPTION = 2;
29
    const DEBUG_TAGS = 4;
30
    const DEBUG_TAGS_ANSI = 12;
31
    const DEBUG_TAGS_HTML = 20;
32
33
    /**
34
     * LightnCandy runtime method for output debug info.
35
     *
36
     * @param string $v expression
37
     * @param string $f runtime function name
38
     * @param array<string,array|string|integer> $cx render time context
39
     *
40
     * @expect '{{123}}' when input '123', 'miss', array('flags' => array('debug' => Runtime::DEBUG_TAGS), 'runtime' => 'LightnCandy\\Runtime'), ''
41
     * @expect '<!--MISSED((-->{{#123}}<!--))--><!--SKIPPED--><!--MISSED((-->{{/123}}<!--))-->' when input '123', 'wi', array('flags' => array('debug' => Runtime::DEBUG_TAGS_HTML), 'runtime' => 'LightnCandy\\Runtime'), false, false, function () {return 'A';}
42
     */
43 9
    public static function debug($v, $f, $cx) {
44 9
        $params = array_slice(func_get_args(), 2);
45 9
        $r = call_user_func_array((isset($cx['funcs'][$f]) ? $cx['funcs'][$f] : "{$cx['runtime']}::$f"), $params);
46
47 8
        if ($cx['flags']['debug'] & static::DEBUG_TAGS) {
48 5
            $ansi = $cx['flags']['debug'] & (static::DEBUG_TAGS_ANSI - static::DEBUG_TAGS);
49 5
            $html = $cx['flags']['debug'] & (static::DEBUG_TAGS_HTML - static::DEBUG_TAGS);
50 5
            $cs = ($html ? (($r !== '') ? '<!!--OK((-->' : '<!--MISSED((-->') : '')
51 5
                  . ($ansi ? (($r !== '') ? "\033[0;32m" : "\033[0;31m") : '');
52 5
            $ce = ($html ? '<!--))-->' : '')
53 5
                  . ($ansi ? "\033[0m" : '');
54
            switch ($f) {
55 5
                case 'sec':
56 5
                case 'ifv':
57 5
                case 'unl':
58 5
                case 'wi':
59 3
                    if ($r == '') {
60 3
                        if ($ansi) {
61 1
                            $r = "\033[0;33mSKIPPED\033[0m";
62 1
                        }
63 3
                        if ($html) {
64 2
                            $r = '<!--SKIPPED-->';
65 2
                        }
66 3
                    }
67 3
                    return "$cs{{#{$v}}}$ce{$r}$cs{{/{$v}}}$ce";
68 3
                default:
69 3
                    return "$cs{{{$v}}}$ce";
70 3
            }
71
        } else {
72 3
            return $r;
73
        }
74
    }
75
76
    /**
77
     * LightnCandy runtime method for error
78
     *
79
     * @param array<string,array|string|integer> $cx render time context
80
     * @param string $err error message
81
     *
82
     * @throws \Exception
83
     */
84 7
    public static function err($cx, $err) {
85 7
        if ($cx['flags']['debug'] & static::DEBUG_ERROR_LOG) {
86 2
            error_log($err);
87 2
            return;
88
        }
89 5
        if ($cx['flags']['debug'] & static::DEBUG_ERROR_EXCEPTION) {
90 2
            throw new \Exception($err);
91
        }
92 3
    }
93
94
    /**
95
     * LightnCandy runtime method for missing data error.
96
     *
97
     * @param array<string,array|string|integer> $cx render time context
98
     * @param string $v expression
99
     */
100 5
    public static function miss($cx, $v) {
101 5
        static::err($cx, "Runtime: $v is not exist");
102 4
    }
103
104
    /**
105
     * LightnCandy runtime method for variable lookup. It is slower and only be used for instance property or method detection or lambdas.
106
     *
107
     * @param array<string,array|string|integer> $cx render time context
108
     * @param array<array|string|integer> $base current variable context
109
     * @param array<string|integer> $path array of names for path
110
     *
111
     * @return null|string Return the value or null when not found
112
     *
113
     * @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), 0, array('a', 'b')
114
     * @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0), 'mustlok' => 0), array('a' => array('b' => 3)), array('a', 'b')
115
     * @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), (Object) array('a' => array('b' => 3)), array('a', 'b')
116
     * @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 1, 'method' => 0, 'mustlok' => 0)), (Object) array('a' => array('b' => 3)), array('a', 'b')
117
     */
118 310
    public static function v($cx, $base, $path) {
119 310
        $count = count($cx['scopes']);
120 310
        while ($base) {
121 281
            $v = $base;
122 281
            foreach ($path as $name) {
123 281
                if (is_array($v) && isset($v[$name])) {
124 277
                    $v = $v[$name];
125 277
                    continue;
126
                }
127 27
                if (is_object($v)) {
128 5
                    if ($cx['flags']['prop'] && !($v instanceof \Closure) && isset($v->$name)) {
129 3
                        $v = $v->$name;
130 3
                        continue;
131
                    }
132 5
                    if ($cx['flags']['method'] && is_callable(array($v, $name))) {
133 4
                        $v = $v->$name();
134 4
                        continue;
135
                    }
136 3
                }
137 25
                if ($cx['flags']['mustlok']) {
138 22
                    unset($v);
139 22
                    break;
140
                }
141 3
                return null;
142 281
            }
143 281
            if (isset($v)) {
144 271
                return $v;
145
            }
146 22
            $count--;
147
            switch ($count) {
148 22
                case -1:
149 21
                    $base = $cx['sp_vars']['root'];
150 21
                    break;
151 22
                case -2:
152 21
                    return null;
153 2
                default:
154 2
                    $base = $cx['scopes'][$count];
155 2
            }
156 22
        }
157 31
    }
158
159
    /**
160
     * LightnCandy runtime method for {{#if var}}.
161
     *
162
     * @param array<string,array|string|integer> $cx render time context
163
     * @param array<array|string|integer>|string|integer|null $v value to be tested
164
     * @param boolean $zero include zero as true
165
     *
166
     * @return boolean Return true when the value is not null nor false.
167
     *
168
     * @expect false when input array(), null, false
169
     * @expect false when input array(), 0, false
170
     * @expect true when input array(), 0, true
171
     * @expect false when input array(), false, false
172
     * @expect true when input array(), true, false
173
     * @expect true when input array(), 1, false
174
     * @expect false when input array(), '', false
175
     * @expect false when input array(), array(), false
176
     * @expect true when input array(), array(''), false
177
     * @expect true when input array(), array(0), false
178
     */
179 53
    public static function ifvar($cx, $v, $zero) {
0 ignored issues
show
Unused Code introduced by
The parameter $cx is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
180 53
        return !is_null($v) && ($v !== false) && ($zero || ($v !== 0) && ($v !== 0.0)) && ($v !== '') && (is_array($v) ? (count($v) > 0) : true);
0 ignored issues
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
181
    }
182
183
    /**
184
     * LightnCandy runtime method for {{#if var}} when {{../var}} used.
185
     *
186
     * @param array<string,array|string|integer> $cx render time context
187
     * @param array<array|string|integer>|string|integer|null $v value to be tested
188
     * @param boolean $zero include zero as true
189
     * @param array<array|string|integer> $in input data with current scope
190
     * @param Closure|null $truecb callback function when test result is true
191
     * @param Closure|null $falsecb callback function when test result is false
192
     *
193
     * @return string The rendered string of the section
194
     *
195
     * @expect '' when input array('scopes' => array()), null, false, array(), null
196
     * @expect '' when input array('scopes' => array()), null, false, array(), function () {return 'Y';}
197
     * @expect 'Y' when input array('scopes' => array()), 1, false, array(), function () {return 'Y';}
198
     * @expect 'N' when input array('scopes' => array()), null, false, array(), function () {return 'Y';}, function () {return 'N';}
199
     */
200 1
    public static function ifv($cx, $v, $zero, $in, $truecb, $falsecb = null) {
201 1
        if (static::ifvar($cx, $v, $zero)) {
202 1
            if ($truecb) {
203 1
                return $truecb($cx, $in);
204
            }
205
        } else {
206 1
            if ($falsecb) {
207 1
                return $falsecb($cx, $in);
208
            }
209
        }
210 1
        return '';
211
    }
212
213
    /**
214
     * LightnCandy runtime method for {{#unless var}} when {{../var}} used.
215
     *
216
     * @param array<string,array|string|integer> $cx render time context
217
     * @param array<array|string|integer>|string|integer|null $var value be tested
218
     * @param boolean $zero include zero as true
219
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
220
     * @param Closure $truecb callback function when test result is true
221
     * @param Closure|null $falsecb callback function when test result is false
222
     *
223
     * @return string Return rendered string when the value is not null nor false.
224
     *
225
     * @expect '' when input array('scopes' => array()), null, false, array(), null
226
     * @expect 'Y' when input array('scopes' => array()), null, false, array(), function () {return 'Y';}
227
     * @expect '' when input array('scopes' => array()), 1, false, array(), function () {return 'Y';}
228
     * @expect 'Y' when input array('scopes' => array()), null, false, array(), function () {return 'Y';}, function () {return 'N';}
229
     * @expect 'N' when input array('scopes' => array()), true, false, array(), function () {return 'Y';}, function () {return 'N';}
230
     */
231 1
    public static function unl($cx, $var, $zero, $in, $truecb, $falsecb = null) {
232 1
        return static::ifv($cx, $var, $zero, $in, $falsecb, $truecb);
233
    }
234
235
    /**
236
     * LightnCandy runtime method for {{^var}} inverted section.
237
     *
238
     * @param array<string,array|string|integer> $cx render time context
239
     * @param array<array|string|integer>|string|integer|null $v value to be tested
240
     *
241
     * @return boolean Return true when the value is not null nor false.
242
     *
243
     * @expect true when input array(), null
244
     * @expect false when input array(), 0
245
     * @expect true when input array(), false
246
     * @expect false when input array(), 'false'
247
     * @expect true when input array(), array()
248
     * @expect false when input array(), array('1')
249
     */
250 36
    public static function isec($cx, $v) {
0 ignored issues
show
Unused Code introduced by
The parameter $cx is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
251 36
        return is_null($v) || ($v === false) || (is_array($v) && (count($v) === 0));
0 ignored issues
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
252
    }
253
254
    /**
255
     * LightnCandy runtime method for {{{var}}} .
256
     *
257
     * @param array<string,array|string|integer> $cx render time context
258
     * @param array<array|string|integer>|string|integer|null $v value to be output
259
     *
260
     * @return string The raw value of the specified variable
261
     *
262
     * @expect true when input array('flags' => array('jstrue' => 0, 'mustlam' => 0, 'lambda' => 0)), true
263
     * @expect 'true' when input array('flags' => array('jstrue' => 1)), true
264
     * @expect '' when input array('flags' => array('jstrue' => 0, 'mustlam' => 0, 'lambda' => 0)), false
265
     * @expect 'false' when input array('flags' => array('jstrue' => 1)), false
266
     * @expect 'false' when input array('flags' => array('jstrue' => 1)), false, true
267
     * @expect 'Array' when input array('flags' => array('jstrue' => 1, 'jsobj' => 0)), array('a', 'b')
268
     * @expect 'a,b' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1, 'mustlam' => 0, 'lambda' => 0)), array('a', 'b')
269
     * @expect '[object Object]' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('a', 'c' => 'b')
270
     * @expect '[object Object]' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('c' => 'b')
271
     * @expect 'a,true' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1, 'mustlam' => 0, 'lambda' => 0)), array('a', true)
272
     * @expect 'a,1' when input array('flags' => array('jstrue' => 0, 'jsobj' => 1, 'mustlam' => 0, 'lambda' => 0)), array('a',true)
273
     * @expect 'a,' when input array('flags' => array('jstrue' => 0, 'jsobj' => 1, 'mustlam' => 0, 'lambda' => 0)), array('a',false)
274
     * @expect 'a,false' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1, 'mustlam' => 0, 'lambda' => 0)), array('a',false)
275
     */
276 255
    public static function raw($cx, $v) {
277 255
        if ($v === true) {
278 1
            if ($cx['flags']['jstrue']) {
279 1
                return 'true';
280
            }
281 1
        }
282
283 255
        if (($v === false)) {
284 6
            if ($cx['flags']['jstrue']) {
285 6
                return 'false';
286
            }
287 1
        }
288
289 250
        if (is_array($v)) {
290 6
            if ($cx['flags']['jsobj']) {
291 6
                if (count(array_diff_key($v, array_keys(array_keys($v)))) > 0) {
292 2
                    return '[object Object]';
293
                } else {
294 5
                    $ret = array();
295 5
                    foreach ($v as $k => $vv) {
296 5
                        $ret[] = static::raw($cx, $vv);
297 5
                    }
298 5
                    return join(',', $ret);
299
                }
300
            } else {
301 1
                return 'Array';
302
            }
303
        }
304
305 250
        if ($v instanceof \Closure) {
306 9
            if ($cx['flags']['mustlam'] || $cx['flags']['lambda']) {
307 9
                $v = $v();
308 9
            }
309 9
        }
310
311 250
        return "$v";
312
    }
313
314
    /**
315
     * LightnCandy runtime method for {{var}} .
316
     *
317
     * @param array<string,array|string|integer> $cx render time context
318
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
319
     *
320
     * @return string The htmlencoded value of the specified variable
321
     *
322
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
323
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
324
     * @expect 'a&#039;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
325
     */
326 44
    public static function enc($cx, $var) {
327 44
        return htmlentities(static::raw($cx, $var), ENT_QUOTES, 'UTF-8');
328
    }
329
330
    /**
331
     * LightnCandy runtime method for {{var}} , and deal with single quote to same as handlebars.js .
332
     *
333
     * @param array<string,array|string|integer> $cx render time context
334
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
335
     *
336
     * @return string The htmlencoded value of the specified variable
337
     *
338
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
339
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
340
     * @expect 'a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
341
     * @expect '&#x60;a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), '`a\'b'
342
     */
343 185
    public static function encq($cx, $var) {
344 185
        return preg_replace('/=/', '&#x3D;', preg_replace('/`/', '&#x60;', preg_replace('/&#039;/', '&#x27;', htmlentities(static::raw($cx, $var), ENT_QUOTES, 'UTF-8'))));
345
    }
346
347
    /**
348
     * LightnCandy runtime method for {{#var}} section.
349
     *
350
     * @param array<string,array|string|integer> $cx render time context
351
     * @param array<array|string|integer>|string|integer|null $v value for the section
352
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
353
     * @param boolean $each true when rendering #each
354
     * @param Closure $cb callback function to render child context
355
     * @param Closure|null $else callback function to render child context when {{else}}
356
     *
357
     * @return string The rendered string of the section
358
     *
359
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), false, false, false, function () {return 'A';}
360
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), null, null, false, function () {return 'A';}
361
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), true, true, false, function () {return 'A';}
362
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 0, 0, false, function () {return 'A';}
363
     * @expect '-a=' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a'), array('a'), false, function ($c, $i) {return "-$i=";}
364
     * @expect '-a=-b=' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a','b'), array('a','b'), false, function ($c, $i) {return "-$i=";}
365
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 'abc', 'abc', true, function ($c, $i) {return "-$i=";}
366
     * @expect '-b=' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a' => 'b'), array('a' => 'b'), true, function ($c, $i) {return "-$i=";}
367
     * @expect '1' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 'b', 'b', false, function ($c, $i) {return count($i);}
368
     * @expect '1' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 1, 1, false, function ($c, $i) {return print_r($i, true);}
369
     * @expect '0' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 0, 0, false, function ($c, $i) {return print_r($i, true);}
370
     * @expect '{"b":"c"}' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('b' => 'c'), array('b' => 'c'), false, function ($c, $i) {return json_encode($i);}
371
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array(), 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
372
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array(), 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
373
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), false, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
374
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), false, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
375
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), '', 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
376
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), '', 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
377
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 0, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
378
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 0, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
379
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), new stdClass, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
380
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), new stdClass, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
381
     * @expect '268' when input array('flags' => array('spvar' => 1, 'mustlam' => 0, 'lambda' => 0), 'sp_vars'=>array('root' => 0)), array(1,3,4), 0, false, function ($c, $i) {return $i * 2;}
382
     * @expect '038' when input array('flags' => array('spvar' => 1, 'mustlam' => 0, 'lambda' => 0), 'sp_vars'=>array('root' => 0)), array(1,3,'a'=>4), 0, true, function ($c, $i) {return $i * $c['sp_vars']['index'];}
383
     */
384 142
    public static function sec($cx, $v, $in, $each, $cb, $else = null) {
385 142
        $push = ($in !== $v) || $each;
386
387 142
        if ($v instanceof \Closure) {
388 2
            if ($cx['flags']['mustlam'] || $cx['flags']['lambda']) {
389 2
                $v = $v();
390 2
            }
391 2
        }
392
393 142
        $isAry = is_array($v) || ($v instanceof \ArrayObject);
394 142
        $isTrav = $v instanceof \Traversable;
395 142
        $loop = $each;
396 142
        $keys = null;
397 142
        $last = null;
398 142
        $isObj = false;
399
400 142
        if ($isAry && $else !== null && count($v) === 0) {
401 3
            $ret = $else($cx, $in);
402 3
            return $ret;
403
        }
404
405
        // #var, detect input type is object or not
406 140
        if (!$loop && $isAry) {
407 60
            $keys = array_keys($v);
408 60
            $loop = (count(array_diff_key($v, array_keys($keys))) == 0);
409 60
            $isObj = !$loop;
410 60
        }
411
412 140
        if ($cx['flags']['mustlam'] && ($v instanceof \Closure)) {
413
            self:err('Do not support Section Lambdas!');
414
        }
415
416 140
        if (($loop && $isAry) || $isTrav) {
417 90
            if ($each && !$isTrav) {
418
                // Detect input type is object or not when never done once
419 38
                if ($keys == null) {
420 38
                    $keys = array_keys($v);
421 38
                    $isObj = (count(array_diff_key($v, array_keys($keys))) > 0);
422 38
                }
423 38
            }
424 90
            $ret = array();
425 90
            $c = count($cx['scopes']);
0 ignored issues
show
Unused Code introduced by
$c is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
426 90
            if ($push) {
427 88
                $cx['scopes'][] = $in;
428 88
            }
429 90
            $i = 0;
430 90
            if ($cx['flags']['spvar']) {
431 79
                $old_spvar = $cx['sp_vars'];
432 79
                $cx['sp_vars'] = array(
433 79
                    '_parent' => $old_spvar,
434 79
                    'root' => $old_spvar['root'],
435
                );
436 79
                if (!$isTrav) {
437 78
                    $last = count($keys) - 1;
438 78
                }
439 79
            }
440
441 90
            $isSparceArray = $isObj && (count(array_filter(array_keys($v), 'is_string')) == 0);
442 90
            foreach ($v as $index => $raw) {
443 84
                if ($cx['flags']['spvar']) {
444 74
                    $cx['sp_vars']['first'] = ($i === 0);
445 74
                    $cx['sp_vars']['last'] = ($i == $last);
446 74
                    $cx['sp_vars']['key'] = $index;
447 74
                    $cx['sp_vars']['index'] = $isSparceArray ? $index : $i;
448 74
                    $i++;
449 74
                }
450 84
                $ret[] = $cb($cx, $raw);
451 90
            }
452 90
            if ($cx['flags']['spvar']) {
453 79
                if ($isObj) {
454 14
                    unset($cx['sp_vars']['key']);
455 14
                } else {
456 67
                    unset($cx['sp_vars']['last']);
457
                }
458 79
                unset($cx['sp_vars']['index']);
459 79
                unset($cx['sp_vars']['first']);
460 79
                $cx['sp_vars'] = $old_spvar;
0 ignored issues
show
Bug introduced by
The variable $old_spvar does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
461 79
            }
462 90
            if ($push) {
463 88
                array_pop($cx['scopes']);
464 88
            }
465 90
            return join('', $ret);
466
        }
467 53
        if ($each) {
468 2
            if ($else !== null) {
469 1
                $ret = $else($cx, $v);
470 1
                return $ret;
471
            }
472 2
            return '';
473
        }
474 52
        if ($isAry) {
475 9
            if ($push) {
476 8
                $cx['scopes'][] = $in;
477 8
            }
478 9
            $ret = $cb($cx, $v);
479 9
            if ($push) {
480 8
                array_pop($cx['scopes']);
481 8
            }
482 9
            return $ret;
483
        }
484
485 44
        if ($v === true) {
486 22
            return $cb($cx, $in);
487
        }
488
489 23
        if (!is_null($v) && ($v !== false)) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
490 4
            return $cb($cx, $v);
491
        }
492
493 20
        if ($else !== null) {
494 6
            $ret = $else($cx, $in);
495 6
            return $ret;
496
        }
497
498 15
        return '';
499
    }
500
501
    /**
502
     * LightnCandy runtime method for {{#with var}} .
503
     *
504
     * @param array<string,array|string|integer> $cx render time context
505
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
506
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
507
     * @param Closure $cb callback function to render child context
508
     * @param Closure|null $else callback function to render child context when {{else}}
509
     *
510
     * @return string The rendered string of the token
511
     *
512
     * @expect '' when input array(), false, false, function () {return 'A';}
513
     * @expect '' when input array(), null, null, function () {return 'A';}
514
     * @expect '{"a":"b"}' when input array(), array('a'=>'b'), array('a'=>'c'), function ($c, $i) {return json_encode($i);}
515
     * @expect '-b=' when input array(), 'b', array('a'=>'b'), function ($c, $i) {return "-$i=";}
516
     */
517 13
    public static function wi($cx, $v, $in, $cb, $else = null) {
518 13
        if (($v === false) || ($v === null)) {
519 4
            return $else ? $else($cx, $in) : '';
520
        }
521 10
        $cx['scopes'][] = $in;
522 10
        $ret = $cb($cx, $v);
523 10
        array_pop($cx['scopes']);
524 10
        return $ret;
525
    }
526
527
    /**
528
     * LightnCandy runtime method for {{> partial}} .
529
     *
530
     * @param array<string,array|string|integer> $cx render time context
531
     * @param string $p partial name
532
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
533
     *
534
     * @return string The rendered string of the partial
535
     *
536
     */
537 52
    public static function p($cx, $p, $v, $sp = '') {
538 52
        $param = $v[0][0];
539
540 52
        if (is_array($v[1])) {
541 52
            if (is_array($v[0][0])) {
542 45
                $param = array_merge($v[0][0], $v[1]);
543 52
            } else if (($cx['flags']['method'] || $cx['flags']['prop']) && is_object($v[0][0])) {
544 1
                foreach ($v[1] as $i => $v) {
545 1
                    $param->$i = $v;
546 1
                }
547 1
            }
548 52
        }
549
550 52
        return call_user_func($cx['partials'][$p], $cx, $param, $sp);
551
    }
552
553
    /**
554
     * LightnCandy runtime method for custom helpers.
555
     *
556
     * @param array<string,array|string|integer> $cx render time context
557
     * @param string $ch the name of custom helper to be executed
558
     * @param array<array> $vars variables for the helper
559
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
560
     *
561
     * @return string The rendered string of the token
562
     *
563
     * @expect '---' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('-'),array()), 'raw'
564
     * @expect '-&amp;-' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('&'),array()), 'enc'
565
     * @expect '-&#x27;-' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('\''),array()), 'encq'
566
     * @expect '-b-' when input array('helpers' => array('a' => function ($i,$j) {return "-{$j['a']}-";})), 'a', array(array(),array('a' => 'b')), 'raw'
567
     */
568 22
    public static function ch($cx, $ch, $vars, $op) {
569 22
        return static::chret(call_user_func_array($cx['helpers'][$ch], $vars), $op);
570
    }
571
572
    /**
573
     * LightnCandy runtime method to handle response of custom helpers.
574
     *
575
     * @param string|array<string,array|string|integer> $ret return value from custom helper
576
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
577
     *
578
     * @return string The rendered string of the token
579
     *
580
     * @expect '-&-' when input '-&-', 'raw'
581
     * @expect '-&amp;&#039;-' when input '-&\'-', 'enc'
582
     * @expect '-&amp;&#x27;-' when input '-&\'-', 'encq'
583
     * @expect '-&amp;&#039;-' when input array('-&\'-'), 'enc'
584
     * @expect '-&amp;&#x27;-' when input array('-&\'-'), 'encq'
585
     * @expect '-&amp;-' when input array('-&-', false), 'enc'
586
     * @expect '-&-' when input array('-&-', false), 'raw'
587
     * @expect '-&-' when input array('-&-', 'raw'), 'enc'
588
     * @expect '-&amp;&#x27;-' when input array('-&\'-', 'encq'), 'raw'
589
     */
590 127
    public static function chret($ret, $op) {
591 127
        if (is_array($ret)) {
592 8
            if (isset($ret[1]) && $ret[1]) {
593 7
                $op = $ret[1];
594 7
            }
595 8
            $ret = $ret[0];
596 8
        }
597
598
        switch ($op) {
599 127
            case 'enc':
600 9
                return htmlentities($ret, ENT_QUOTES, 'UTF-8');
601 121
            case 'encq':
602 61
                return preg_replace('/=/', '&#x3D;', preg_replace('/`/', '&#x60;', preg_replace('/&#039;/', '&#x27;', htmlentities($ret, ENT_QUOTES, 'UTF-8'))));
603
        }
604 77
        return $ret;
605
    }
606
607
    /**
608
     * LightnCandy runtime method for Handlebars.js style custom helpers.
609
     *
610
     * @param array<string,array|string|integer> $cx render time context
611
     * @param string $ch the name of custom helper to be executed
612
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
613
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
614
     * @param boolean $inverted the logic will be inverted
615
     * @param Closure|null $cb callback function to render child context
616
     * @param Closure|null $else callback function to render child context when {{else}}
617
     *
618
     * @return string The rendered string of the token
619
     */
620 107
    public static function hbch($cx, $ch, $vars, $op, $inverted, $cb = null, $else = null) {
621 107
        $isBlock = (is_object($cb) && ($cb instanceof \Closure));
622 107
        $args = $vars[0];
623
        $options = array(
624 107
            'name' => $ch,
625 107
            'hash' => $vars[1],
626 107
            '_this' => $isBlock ? $op : $inverted,
627 107
        );
628
629
        // $invert the logic
630 107
        if ($inverted) {
631 47
            $tmp = $else;
632 47
            $else = $cb;
633 47
            $cb = $tmp;
634 47
        }
635
636 107
        if ($isBlock) {
637
            $options['fn'] = function ($context = '_NO_INPUT_HERE_', $data = null) use ($cx, $op, $cb) {
638 30
                if ($cx['flags']['echo']) {
639 6
                    ob_start();
640 6
                }
641 30
                $cx['scopes'][] = $op;
642 30
                if ($data) {
643 1
                    $tmp_data = $cx['sp_vars'];
644 1
                    $cx['sp_vars'] = array_merge($cx['sp_vars'], $data['data']);
645 1
                }
646 30
                if ($context === '_NO_INPUT_HERE_') {
647 8
                    $ret = $cb($cx, $op);
648 8
                } else {
649 23
                    $ret = $cb($cx, $context);
650
                }
651 30
                array_pop($cx['scopes']);
652 30
                if ($data) {
653 1
                    $cx['sp_vars'] = $tmp_data;
0 ignored issues
show
Bug introduced by
The variable $tmp_data does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
654 1
                }
655 30
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
656
            };
657 41
        }
658
659 107
        if ($else) {
660 7
            $options['inverse'] = function ($context = '_NO_INPUT_HERE_', $data = null) use ($cx, $op, $else) {
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
661 7
                if ($cx['flags']['echo']) {
662 3
                    ob_start();
663 3
                }
664 7
                if ($context === '_NO_INPUT_HERE_') {
665 2
                    $ret = $else($cx, $op);
666 2
                } else {
667 5
                    $cx['scopes'][] = $op;
668 5
                    $ret = $else($cx, $context);
669 5
                    array_pop($cx['scopes']);
670
                }
671 7
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
672
            };
673 12
        }
674
675
        // prepare $options['data']
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
676 107
        if ($cx['flags']['spvar']) {
677 96
            $options['data'] = $cx['sp_vars'];
678 96
        }
679
680 107
        $args[] = $options;
681 107
        $e = null;
682 107
        $r = true;
683
684
        try {
685 107
            $r = call_user_func_array($cx['hbhelpers'][$ch], $args);
686 107
        } catch (\Exception $E) {
687 2
            $e = "Runtime: call custom helper '$ch' error: " . $E->getMessage();
688
        }
689
690 107
        if($e !== null) {
691 2
            static::err($cx, $e);
692 1
        }
693
694 106
        return static::chret($r, $isBlock ? 'raw' : $op);
695
    }
696
697
    /**
698
     * LightnCandy runtime method for block custom helpers.
699
     *
700
     * @param array<string,array|string|integer> $cx render time context
701
     * @param string $ch the name of custom helper to be executed
702
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
703
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
704
     * @param boolean $inverted the logic will be inverted
705
     * @param Closure $cb callback function to render child context
706
     * @param Closure|null $else callback function to render child context when {{else}}
707
     *
708
     * @return string The rendered string of the token
709
     *
710
     * @expect '4.2.3' when input array('blockhelpers' => array('a' => function ($cx) {return array($cx,2,3);})), 'a', array(0, 0), 4, false, function($cx, $i) {return implode('.', $i);}
711
     * @expect '2.6.5' when input array('blockhelpers' => array('a' => function ($cx,$in) {return array($cx,$in[0],5);})), 'a', array('6', 0), 2, false, function($cx, $i) {return implode('.', $i);}
712
     * @expect '' when input array('blockhelpers' => array('a' => function ($cx,$in) {})), 'a', array('6', 0), 2, false, function($cx, $i) {return implode('.', $i);}
713
     */
714 4
    public static function bch($cx, $ch, $vars, $in, $inverted, $cb, $else = null) {
715 4
        $r = call_user_func($cx['blockhelpers'][$ch], $in, $vars[0], $vars[1]);
716
717
        // $invert the logic
718 4
        if ($inverted) {
719 2
            $tmp = $else;
720 2
            $else = $cb;
721 2
            $cb = $tmp;
722 2
        }
723
724 4
        $ret = '';
725 4
        if (is_null($r)) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
726 2
            if ($else) {
727 1
                $cx['scopes'][] = $in;
728 1
                $ret = $else($cx, $r);
729 1
                array_pop($cx['scopes']);
730 1
            }
731 2
        } else {
732 3
            if ($cb) {
733 3
                $cx['scopes'][] = $in;
734 3
                $ret = $cb($cx, $r);
735 3
                array_pop($cx['scopes']);
736 3
            }
737
        }
738
739 4
        return $ret;
740
    }
741
}
742
743