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 ( b698f4...f6bbce )
by Zordius
02:44
created

Runtime::ifvar()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 8

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 5.3846
cc 8
eloc 2
nc 17
nop 3
crap 8
1
<?php
0 ignored issues
show
Bug introduced by
Unexpected token: :, line: 411, 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
        if ($v instanceof \Closure) {
386 2
            if ($cx['flags']['mustlam'] || $cx['flags']['lambda']) {
387 2
                $v = $v();
388 2
            }
389 2
        }
390
391 142
        $isAry = is_array($v) || ($v instanceof \ArrayObject);
392 142
        $isTrav = $v instanceof \Traversable;
393 142
        $loop = $each;
394 142
        $keys = null;
395 142
        $last = null;
396 142
        $isObj = false;
397
398 142
        if ($isAry && $else !== null && count($v) === 0) {
399 3
            $ret = $else($cx, $in);
400 3
            return $ret;
401
        }
402
403
        // #var, detect input type is object or not
404 140
        if (!$loop && $isAry) {
405 60
            $keys = array_keys($v);
406 60
            $loop = (count(array_diff_key($v, array_keys($keys))) == 0);
407 60
            $isObj = !$loop;
408 60
        }
409
410 140
        if ($cx['flags']['mustlam'] && ($v instanceof \Closure)) {
411
            self:err('Do not support Section Lambdas!');
412
        }
413
414 140
        if (($loop && $isAry) || $isTrav) {
415 90
            if ($each && !$isTrav) {
416
                // Detect input type is object or not when never done once
417 38
                if ($keys == null) {
418 38
                    $keys = array_keys($v);
419 38
                    $isObj = (count(array_diff_key($v, array_keys($keys))) > 0);
420 38
                }
421 38
            }
422 90
            $ret = array();
423 90
            $cx['scopes'][] = $in;
424 90
            $i = 0;
425 90
            if ($cx['flags']['spvar']) {
426 79
                $old_spvar = $cx['sp_vars'];
427 79
                $cx['sp_vars'] = array(
428 79
                    '_parent' => $old_spvar,
429 79
                    'root' => $old_spvar['root'],
430
                );
431 79
                if (!$isTrav) {
432 78
                    $last = count($keys) - 1;
433 78
                }
434 79
            }
435
436 90
            $isSparceArray = $isObj && (count(array_filter(array_keys($v), 'is_string')) == 0);
437 90
            foreach ($v as $index => $raw) {
438 84
                if ($cx['flags']['spvar']) {
439 74
                    $cx['sp_vars']['first'] = ($i === 0);
440 74
                    $cx['sp_vars']['last'] = ($i == $last);
441 74
                    $cx['sp_vars']['key'] = $index;
442 74
                    $cx['sp_vars']['index'] = $isSparceArray ? $index : $i;
443 74
                    $i++;
444 74
                }
445 84
                $ret[] = $cb($cx, $raw);
446 90
            }
447 90
            if ($cx['flags']['spvar']) {
448 79
                if ($isObj) {
449 14
                    unset($cx['sp_vars']['key']);
450 14
                } else {
451 67
                    unset($cx['sp_vars']['last']);
452
                }
453 79
                unset($cx['sp_vars']['index']);
454 79
                unset($cx['sp_vars']['first']);
455 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...
456 79
            }
457 90
            array_pop($cx['scopes']);
458 90
            return join('', $ret);
459
        }
460 53
        if ($each) {
461 2
            if ($else !== null) {
462 1
                $ret = $else($cx, $v);
463 1
                return $ret;
464
            }
465 2
            return '';
466
        }
467 52
        if ($isAry) {
468 9
            $cx['scopes'][] = $in;
469 9
            $ret = $cb($cx, $v);
470 9
            array_pop($cx['scopes']);
471 9
            return $ret;
472
        }
473
474 44
        if ($v === true) {
475 22
            return $cb($cx, $in);
476
        }
477
478 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...
479 4
            return $cb($cx, $v);
480
        }
481
482 20
        if ($else !== null) {
483 6
            $ret = $else($cx, $in);
484 6
            return $ret;
485
        }
486
487 15
        return '';
488
    }
489
490
    /**
491
     * LightnCandy runtime method for {{#with var}} .
492
     *
493
     * @param array<string,array|string|integer> $cx render time context
494
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
495
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
496
     * @param Closure $cb callback function to render child context
497
     * @param Closure|null $else callback function to render child context when {{else}}
498
     *
499
     * @return string The rendered string of the token
500
     *
501
     * @expect '' when input array(), false, false, function () {return 'A';}
502
     * @expect '' when input array(), null, null, function () {return 'A';}
503
     * @expect '{"a":"b"}' when input array(), array('a'=>'b'), array('a'=>'c'), function ($c, $i) {return json_encode($i);}
504
     * @expect '-b=' when input array(), 'b', array('a'=>'b'), function ($c, $i) {return "-$i=";}
505
     */
506 13
    public static function wi($cx, $v, $in, $cb, $else = null) {
507 13
        if (($v === false) || ($v === null)) {
508 4
            return $else ? $else($cx, $in) : '';
509
        }
510 10
        $cx['scopes'][] = $in;
511 10
        $ret = $cb($cx, $v);
512 10
        array_pop($cx['scopes']);
513 10
        return $ret;
514
    }
515
516
    /**
517
     * LightnCandy runtime method for {{> partial}} .
518
     *
519
     * @param array<string,array|string|integer> $cx render time context
520
     * @param string $p partial name
521
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
522
     *
523
     * @return string The rendered string of the partial
524
     *
525
     */
526 52
    public static function p($cx, $p, $v, $sp = '') {
527 52
        $param = $v[0][0];
528
529 52
        if (is_array($v[1])) {
530 52
            if (is_array($v[0][0])) {
531 45
                $param = array_merge($v[0][0], $v[1]);
532 52
            } else if (($cx['flags']['method'] || $cx['flags']['prop']) && is_object($v[0][0])) {
533 1
                foreach ($v[1] as $i => $v) {
534 1
                    $param->$i = $v;
535 1
                }
536 1
            }
537 52
        }
538
539 52
        return call_user_func($cx['partials'][$p], $cx, $param, $sp);
540
    }
541
542
    /**
543
     * LightnCandy runtime method for custom helpers.
544
     *
545
     * @param array<string,array|string|integer> $cx render time context
546
     * @param string $ch the name of custom helper to be executed
547
     * @param array<array> $vars variables for the helper
548
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
549
     *
550
     * @return string The rendered string of the token
551
     *
552
     * @expect '---' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('-'),array()), 'raw'
553
     * @expect '-&amp;-' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('&'),array()), 'enc'
554
     * @expect '-&#x27;-' when input array('helpers' => array('a' => function ($i) {return "-$i[0]-";})), 'a', array(array('\''),array()), 'encq'
555
     * @expect '-b-' when input array('helpers' => array('a' => function ($i,$j) {return "-{$j['a']}-";})), 'a', array(array(),array('a' => 'b')), 'raw'
556
     */
557 22
    public static function ch($cx, $ch, $vars, $op) {
558 22
        return static::chret(call_user_func_array($cx['helpers'][$ch], $vars), $op);
559
    }
560
561
    /**
562
     * LightnCandy runtime method to handle response of custom helpers.
563
     *
564
     * @param string|array<string,array|string|integer> $ret return value from custom helper
565
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
566
     *
567
     * @return string The rendered string of the token
568
     *
569
     * @expect '-&-' when input '-&-', 'raw'
570
     * @expect '-&amp;&#039;-' when input '-&\'-', 'enc'
571
     * @expect '-&amp;&#x27;-' when input '-&\'-', 'encq'
572
     * @expect '-&amp;&#039;-' when input array('-&\'-'), 'enc'
573
     * @expect '-&amp;&#x27;-' when input array('-&\'-'), 'encq'
574
     * @expect '-&amp;-' when input array('-&-', false), 'enc'
575
     * @expect '-&-' when input array('-&-', false), 'raw'
576
     * @expect '-&-' when input array('-&-', 'raw'), 'enc'
577
     * @expect '-&amp;&#x27;-' when input array('-&\'-', 'encq'), 'raw'
578
     */
579 127
    public static function chret($ret, $op) {
580 127
        if (is_array($ret)) {
581 8
            if (isset($ret[1]) && $ret[1]) {
582 7
                $op = $ret[1];
583 7
            }
584 8
            $ret = $ret[0];
585 8
        }
586
587
        switch ($op) {
588 127
            case 'enc':
589 9
                return htmlentities($ret, ENT_QUOTES, 'UTF-8');
590 121
            case 'encq':
591 61
                return preg_replace('/=/', '&#x3D;', preg_replace('/`/', '&#x60;', preg_replace('/&#039;/', '&#x27;', htmlentities($ret, ENT_QUOTES, 'UTF-8'))));
592
        }
593 77
        return $ret;
594
    }
595
596
    /**
597
     * LightnCandy runtime method for Handlebars.js style custom helpers.
598
     *
599
     * @param array<string,array|string|integer> $cx render time context
600
     * @param string $ch the name of custom helper to be executed
601
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
602
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
603
     * @param boolean $inverted the logic will be inverted
604
     * @param Closure|null $cb callback function to render child context
605
     * @param Closure|null $else callback function to render child context when {{else}}
606
     *
607
     * @return string The rendered string of the token
608
     */
609 107
    public static function hbch($cx, $ch, $vars, $op, $inverted, $cb = null, $else = null) {
610 107
        $isBlock = (is_object($cb) && ($cb instanceof \Closure));
611 107
        $args = $vars[0];
612
        $options = array(
613 107
            'name' => $ch,
614 107
            'hash' => $vars[1],
615 107
            '_this' => $isBlock ? $op : $inverted,
616 107
        );
617
618
        // $invert the logic
619 107
        if ($inverted) {
620 47
            $tmp = $else;
621 47
            $else = $cb;
622 47
            $cb = $tmp;
623 47
        }
624
625 107
        if ($isBlock) {
626
            $options['fn'] = function ($context = '_NO_INPUT_HERE_', $data = null) use ($cx, $op, $cb) {
627 30
                if ($cx['flags']['echo']) {
628 6
                    ob_start();
629 6
                }
630 30
                $cx['scopes'][] = $op;
631 30
                if ($data) {
632 1
                    $tmp_data = $cx['sp_vars'];
633 1
                    $cx['sp_vars'] = array_merge($cx['sp_vars'], $data['data']);
634 1
                }
635 30
                if ($context === '_NO_INPUT_HERE_') {
636 8
                    $ret = $cb($cx, $op);
637 8
                } else {
638 23
                    $ret = $cb($cx, $context);
639
                }
640 30
                array_pop($cx['scopes']);
641 30
                if ($data) {
642 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...
643 1
                }
644 30
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
645
            };
646 41
        }
647
648 107
        if ($else) {
649 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...
650 7
                if ($cx['flags']['echo']) {
651 3
                    ob_start();
652 3
                }
653 7
                if ($context === '_NO_INPUT_HERE_') {
654 2
                    $ret = $else($cx, $op);
655 2
                } else {
656 5
                    $cx['scopes'][] = $op;
657 5
                    $ret = $else($cx, $context);
658 5
                    array_pop($cx['scopes']);
659
                }
660 7
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
661
            };
662 12
        }
663
664
        // 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...
665 107
        if ($cx['flags']['spvar']) {
666 96
            $options['data'] = $cx['sp_vars'];
667 96
        }
668
669 107
        $args[] = $options;
670 107
        $e = null;
671 107
        $r = true;
672
673
        try {
674 107
            $r = call_user_func_array($cx['hbhelpers'][$ch], $args);
675 107
        } catch (\Exception $E) {
676 2
            $e = "Runtime: call custom helper '$ch' error: " . $E->getMessage();
677
        }
678
679 107
        if($e !== null) {
680 2
            static::err($cx, $e);
681 1
        }
682
683 106
        return static::chret($r, $isBlock ? 'raw' : $op);
684
    }
685
686
    /**
687
     * LightnCandy runtime method for block custom helpers.
688
     *
689
     * @param array<string,array|string|integer> $cx render time context
690
     * @param string $ch the name of custom helper to be executed
691
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
692
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
693
     * @param boolean $inverted the logic will be inverted
694
     * @param Closure $cb callback function to render child context
695
     * @param Closure|null $else callback function to render child context when {{else}}
696
     *
697
     * @return string The rendered string of the token
698
     *
699
     * @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);}
700
     * @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);}
701
     * @expect '' when input array('blockhelpers' => array('a' => function ($cx,$in) {})), 'a', array('6', 0), 2, false, function($cx, $i) {return implode('.', $i);}
702
     */
703 4
    public static function bch($cx, $ch, $vars, $in, $inverted, $cb, $else = null) {
704 4
        $r = call_user_func($cx['blockhelpers'][$ch], $in, $vars[0], $vars[1]);
705
706
        // $invert the logic
707 4
        if ($inverted) {
708 2
            $tmp = $else;
709 2
            $else = $cb;
710 2
            $cb = $tmp;
711 2
        }
712
713 4
        $ret = '';
714 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...
715 2
            if ($else) {
716 1
                $cx['scopes'][] = $in;
717 1
                $ret = $else($cx, $r);
718 1
                array_pop($cx['scopes']);
719 1
            }
720 2
        } else {
721 3
            if ($cb) {
722 3
                $cx['scopes'][] = $in;
723 3
                $ret = $cb($cx, $r);
724 3
                array_pop($cx['scopes']);
725 3
            }
726
        }
727
728 4
        return $ret;
729
    }
730
}
731
732