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
Pull Request — master (#309)
by
unknown
06:11
created

Runtime::v()   F

Complexity

Conditions 28
Paths 213

Size

Total Lines 68

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 28

Importance

Changes 0
Metric Value
dl 0
loc 68
ccs 41
cts 41
cp 1
rs 3.1708
c 0
b 0
f 0
cc 28
nc 213
nop 5
crap 28

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
2
/*
3
4
MIT License
5
Copyright 2013-2018 Zordius Chen. All Rights Reserved.
6
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:
7
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
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.
9
10
Origin: https://github.com/zordius/lightncandy
11
*/
12
13
/**
14
 * file to support LightnCandy compiled PHP runtime
15
 *
16
 * @package    LightnCandy
17
 * @author     Zordius <[email protected]>
18
 */
19
20
namespace LightnCandy;
21
use \LightnCandy\Encoder;
22
23
/**
24
 * LightnCandy class for Object property access on a string.
25
 */
26
class StringObject
27
{
28
    protected $string;
29
30 2
    public function __construct($string) {
31 2
        $this->string = $string;
32 2
    }
33
34 2
    public function __toString() {
35 2
        return strval($this->string);
36
    }
37
}
38
39
/**
40
 * LightnCandy class for compiled PHP runtime.
41
 */
42
class Runtime extends Encoder
43
{
44
    const DEBUG_ERROR_LOG = 1;
45
    const DEBUG_ERROR_EXCEPTION = 2;
46
    const DEBUG_TAGS = 4;
47
    const DEBUG_TAGS_ANSI = 12;
48
    const DEBUG_TAGS_HTML = 20;
49
50
    /**
51
     * Output debug info.
52
     *
53
     * @param string $v expression
54
     * @param string $f runtime function name
55
     * @param array<string,array|string|integer> $cx render time context for lightncandy
56
     *
57
     * @expect '{{123}}' when input '123', 'miss', array('flags' => array('debug' => Runtime::DEBUG_TAGS), 'runtime' => 'LightnCandy\\Runtime'), ''
58
     * @expect '<!--MISSED((-->{{#123}}<!--))--><!--SKIPPED--><!--MISSED((-->{{/123}}<!--))-->' when input '123', 'wi', array('flags' => array('debug' => Runtime::DEBUG_TAGS_HTML), 'runtime' => 'LightnCandy\\Runtime'), false, null, false, function () {return 'A';}
59
     */
60 9
    public static function debug($v, $f, $cx) {
61
        // Build array of reference for call_user_func_array
62 9
        $P = func_get_args();
63 9
        $params = array();
64 9
        for ($i=2;$i<count($P);$i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
65 9
            $params[] = &$P[$i];
66
        }
67 9
        $r = call_user_func_array((isset($cx['funcs'][$f]) ? $cx['funcs'][$f] : "{$cx['runtime']}::$f"), $params);
68
69 8
        if ($cx['flags']['debug'] & static::DEBUG_TAGS) {
70 5
            $ansi = $cx['flags']['debug'] & (static::DEBUG_TAGS_ANSI - static::DEBUG_TAGS);
71 5
            $html = $cx['flags']['debug'] & (static::DEBUG_TAGS_HTML - static::DEBUG_TAGS);
72 5
            $cs = ($html ? (($r !== '') ? '<!!--OK((-->' : '<!--MISSED((-->') : '')
73 5
                  . ($ansi ? (($r !== '') ? "\033[0;32m" : "\033[0;31m") : '');
74 5
            $ce = ($html ? '<!--))-->' : '')
75 5
                  . ($ansi ? "\033[0m" : '');
76 5
            switch ($f) {
77 5
                case 'sec':
78 3
                case 'wi':
79 3
                    if ($r == '') {
80 3
                        if ($ansi) {
81 1
                            $r = "\033[0;33mSKIPPED\033[0m";
82
                        }
83 3
                        if ($html) {
84 2
                            $r = '<!--SKIPPED-->';
85
                        }
86
                    }
87 3
                    return "$cs{{#{$v}}}$ce{$r}$cs{{/{$v}}}$ce";
88
                default:
89 3
                    return "$cs{{{$v}}}$ce";
90
            }
91
        } else {
92 3
            return $r;
93
        }
94
    }
95
96
    /**
97
     * Handle error by error_log or throw exception.
98
     *
99
     * @param array<string,array|string|integer> $cx render time context for lightncandy
100
     * @param string $err error message
101
     *
102
     * @throws \Exception
103
     */
104 18
    public static function err($cx, $err) {
105 18
        if ($cx['flags']['debug'] & static::DEBUG_ERROR_LOG) {
106 5
            error_log($err);
107 5
            return;
108
        }
109 13
        if ($cx['flags']['debug'] & static::DEBUG_ERROR_EXCEPTION) {
110 9
            throw new \Exception($err);
111
        }
112 4
    }
113
114
    /**
115
     * Handle missing data error.
116
     *
117
     * @param array<string,array|string|integer> $cx render time context for lightncandy
118
     * @param string $v expression
119
     */
120 5
    public static function miss($cx, $v) {
121 5
        static::err($cx, "Runtime: $v does not exist");
122 4
    }
123
124
    /**
125
     * For {{log}} .
126
     *
127
     * @param array<string,array|string|integer> $cx render time context for lightncandy
128
     * @param string $v expression
129
     */
130
    public static function lo($cx, $v) {
131
        error_log(var_export($v[0], true));
132
        return '';
133
    }
134
135
    /**
136
     * Resursive lookup variable and helpers. This is slow and will only be used for instance property or method detection or lambdas.
137
     *
138
     * @param array<string,array|string|integer> $cx render time context for lightncandy
139
     * @param array|string|boolean|integer|double|null $in current context
140
     * @param array<array|string|integer> $base current variable context
141
     * @param array<string|integer> $path array of names for path
142
     * @param array|null $args extra arguments for lambda
143
     *
144
     * @return null|string Return the value or null when not found
145
     *
146
     * @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), null, 0, array('a', 'b')
147
     * @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0), 'mustlok' => 0), null, array('a' => array('b' => 3)), array('a', 'b')
148
     * @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), null, (Object) array('a' => array('b' => 3)), array('a', 'b')
149
     * @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 1, 'method' => 0, 'mustlok' => 0)), null, (Object) array('a' => array('b' => 3)), array('a', 'b')
150
     */
151 388
    public static function v($cx, $in, $base, $path, $args = null) {
152 388
        $count = count($cx['scopes']);
153 388
        $plen = count($path);
154 388
        while ($base) {
155 352
            $v = $base;
156 352
            foreach ($path as $i => $name) {
157 352
                if (is_array($v)) {
158 350
                    if (isset($v[$name])) {
159 346
                        $v = $v[$name];
160 346
                        continue;
161
                    }
162 31
                    if (($i === $plen - 1) && ($name === 'length')) {
163 1
                        return count($v);
164
                    }
165
                }
166 37
                if (is_object($v)) {
167 6
                    if ($cx['flags']['prop'] && !($v instanceof \Closure) && isset($v->$name)) {
168 4
                        $v = $v->$name;
169 4
                        continue;
170
                    }
171 5
                    if ($cx['flags']['method'] && is_callable(array($v, $name))) {
172 4
                        try {
173 4
                            $v = $v->$name();
174
                            continue;
175
                        } catch (\BadMethodCallException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
176 34
                    }
177 31
                    if ($v instanceof \ArrayAccess) {
178 31
                        if (isset($v[$name])) {
179
                            $v = $v[$name];
180 3
                            continue;
181
                        }
182 351
                    }
183 340
                }
184 29
                if ($cx['flags']['mustlok']) {
185 29
                    unset($v);
186 20
                    break;
187 20
                }
188
                return null;
189 10
            }
190
            if (isset($v)) {
191 29
                if ($v instanceof \Closure) {
192
                    if ($cx['flags']['mustlam'] || $cx['flags']['lambda']) {
193
                        if (!$cx['flags']['knohlp'] && ($args || ($args === 0))) {
194 340
                            $A = $args ? $args[0] : array();
195
                            $A[] = array('hash' => $args[1], '_this' => $in);
196 31
                        } else {
197 31
                            $A = array($in);
198
                        }
199 30
                        $v = call_user_func_array($v, $A);
200 30
                    }
201
                }
202 29
                return $v;
203
            }
204 6
            $count--;
205
            switch ($count) {
206
                case -1:
207 40
                    $base = $cx['sp_vars']['root'];
208 3
                    break;
209
                case -2:
210 40
                    return null;
211
                default:
212
                    $base = $cx['scopes'][$count];
213
            }
214
        }
215
        if ($args) {
216
            static::err($cx, 'Can not find helper or lambda: "' . implode('.', $path) . '" !');
217
        }
218
    }
219
220
    /**
221
     * For {{#if}} .
222
     *
223
     * @param array<string,array|string|integer> $cx render time context for lightncandy
224
     * @param array<array|string|integer>|string|integer|null $v value to be tested
225
     * @param boolean $zero include zero as true
226
     *
227
     * @return boolean Return true when the value is not null nor false.
228
     *
229
     * @expect false when input array(), null, false
230
     * @expect false when input array(), 0, false
231
     * @expect true when input array(), 0, true
232 74
     * @expect false when input array(), false, false
233 74
     * @expect true when input array(), true, false
234
     * @expect true when input array(), 1, false
235
     * @expect false when input array(), '', false
236
     * @expect false when input array(), array(), false
237
     * @expect true when input array(), array(''), false
238
     * @expect true when input array(), array(0), false
239
     */
240
    public static function ifvar($cx, $v, $zero) {
241
        return ($v !== null) && ($v !== false) && ($zero || ($v !== 0) && ($v !== 0.0)) && ($v !== '') && (is_array($v) ? (count($v) > 0) : true);
242
    }
243
244
    /**
245
     * For {{^var}} .
246
     *
247
     * @param array<string,array|string|integer> $cx render time context for lightncandy
248
     * @param array<array|string|integer>|string|integer|null $v value to be tested
249
     *
250
     * @return boolean Return true when the value is not null nor false.
251 37
     *
252 37
     * @expect true when input array(), null
253
     * @expect false when input array(), 0
254
     * @expect true when input array(), false
255
     * @expect false when input array(), 'false'
256
     * @expect true when input array(), array()
257
     * @expect false when input array(), array('1')
258
     */
259
    public static function isec($cx, $v) {
260
        return ($v === null) || ($v === false) || (is_array($v) && (count($v) === 0));
261
    }
262
263
    /**
264
     * For {{var}} .
265
     *
266
     * @param array<string,array|string|integer> $cx render time context for lightncandy
267
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
268 46
     *
269 46
     * @return string The htmlencoded value of the specified variable
270 1
     *
271
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
272
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
273 46
     * @expect 'a&#039;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
274
     * @expect 'a&b' when input null, new \LightnCandy\SafeString('a&b')
275
     */
276
    public static function enc($cx, $var) {
277
        if ($var instanceof \LightnCandy\SafeString) {
278
            return (string)$var;
279
        }
280
281
        return htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8');
282
    }
283
284
    /**
285
     * For {{var}} , do html encode just like handlebars.js .
286
     *
287
     * @param array<string,array|string|integer> $cx render time context for lightncandy
288
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
289 341
     *
290 341
     * @return string The htmlencoded value of the specified variable
291 3
     *
292
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
293
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
294 338
     * @expect 'a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
295
     * @expect '&#x60;a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), '`a\'b'
296
     */
297
    public static function encq($cx, $var) {
298
        if ($var instanceof \LightnCandy\SafeString) {
299
            return (string)$var;
300
        }
301
302
        return str_replace(array('=', '`', '&#039;'), array('&#x3D;', '&#x60;', '&#x27;'), htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8'));
303
    }
304
305
    /**
306
     * For {{#var}} or {{#each}} .
307
     *
308
     * @param array<string,array|string|integer> $cx render time context for lightncandy
309
     * @param array<array|string|integer>|string|integer|null $v value for the section
310
     * @param array<string>|null $bp block parameters
311
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
312
     * @param boolean $each true when rendering #each
313
     * @param Closure $cb callback function to render child context
314
     * @param Closure|null $else callback function to render child context when {{else}}
315
     *
316
     * @return string The rendered string of the section
317
     *
318
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), false, null, false, false, function () {return 'A';}
319
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), null, null, null, false, function () {return 'A';}
320
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), true, null, true, false, function () {return 'A';}
321
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 0, null, 0, false, function () {return 'A';}
322
     * @expect '-a=' when input array('scopes' => array(), 'flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a'), null, array('a'), false, function ($c, $i) {return "-$i=";}
323
     * @expect '-a=-b=' when input array('scopes' => array(), 'flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a','b'), null, array('a','b'), false, function ($c, $i) {return "-$i=";}
324
     * @expect '' when input array('scopes' => array(), 'flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 'abc', null, 'abc', true, function ($c, $i) {return "-$i=";}
325
     * @expect '-b=' when input array('scopes' => array(), 'flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('a' => 'b'), null, array('a' => 'b'), true, function ($c, $i) {return "-$i=";}
326
     * @expect 'b' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 'b', null, 'b', false, function ($c, $i) {return print_r($i, true);}
327
     * @expect '1' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 1, null, 1, false, function ($c, $i) {return print_r($i, true);}
328
     * @expect '0' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 0, null, 0, false, function ($c, $i) {return print_r($i, true);}
329
     * @expect '{"b":"c"}' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array('b' => 'c'), null, array('b' => 'c'), false, function ($c, $i) {return json_encode($i);}
330
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array(), null, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
331
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), array(), null, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
332
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), false, null, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
333
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), false, null, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
334
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), '', null, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
335 170
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), '', null, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
336 170
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 0, null, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
337
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 0, null, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
338 170
     * @expect 'inv' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), new stdClass, null, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
339 170
     * @expect 'cb' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), new stdClass, null, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
340 170
     * @expect '268' when input array('scopes' => array(), 'flags' => array('spvar' => 1, 'mustlam' => 0, 'lambda' => 0), 'sp_vars'=>array('root' => 0)), array(1,3,4), null, 0, false, function ($c, $i) {return $i * 2;}
341 170
     * @expect '038' when input array('scopes' => array(), 'flags' => array('spvar' => 1, 'mustlam' => 0, 'lambda' => 0), 'sp_vars'=>array('root' => 0)), array(1,3,'a'=>4), null, 0, true, function ($c, $i) {return $i * $c['sp_vars']['index'];}
342 170
     */
343 170
    public static function sec($cx, $v, $bp, $in, $each, $cb, $else = null) {
344
        $push = ($in !== $v) || $each;
345 170
346 3
        $isAry = is_array($v) || ($v instanceof \ArrayObject);
347 3
        $isTrav = $v instanceof \Traversable;
348
        $loop = $each;
349
        $keys = null;
350
        $last = null;
351 168
        $isObj = false;
352 66
353 66
        if ($isAry && $else !== null && count($v) === 0) {
354 66
            $ret = $else($cx, $in);
355
            return $ret;
356
        }
357 168
358 106
        // #var, detect input type is object or not
359
        if (!$loop && $isAry) {
360 50
            $keys = array_keys($v);
361 50
            $loop = (count(array_diff_key($v, array_keys($keys))) == 0);
362 50
            $isObj = !$loop;
363
        }
364
365 106
        if (($loop && $isAry) || $isTrav) {
366 106
            if ($each && !$isTrav) {
367 104
                // Detect input type is object or not when never done once
368
                if ($keys == null) {
369 106
                    $keys = array_keys($v);
370 106
                    $isObj = (count(array_diff_key($v, array_keys($keys))) > 0);
371 95
                }
372 95
            }
373 95
            $ret = array();
374 94
            if ($push) {
375
                $cx['scopes'][] = $in;
376
            }
377
            $i = 0;
378 106
            if ($cx['flags']['spvar']) {
379 106
                $old_spvar = $cx['sp_vars'];
380 99
                $cx['sp_vars'] = array_merge(array('root' => $old_spvar['root']), $old_spvar, array('_parent' => $old_spvar));
381 89
                if (!$isTrav) {
382 89
                    $last = count($keys) - 1;
383 89
                }
384 89
            }
385 89
386
            $isSparceArray = $isObj && (count(array_filter(array_keys($v), 'is_string')) == 0);
387 99
            foreach ($v as $index => $raw) {
388 4
                if ($cx['flags']['spvar']) {
389
                    $cx['sp_vars']['first'] = ($i === 0);
390 99
                    $cx['sp_vars']['last'] = ($i == $last);
391 3
                    $cx['sp_vars']['key'] = $index;
392
                    $cx['sp_vars']['index'] = $isSparceArray ? $index : $i;
393 99
                    $i++;
394
                }
395 105
                if (isset($bp[0])) {
396 94
                    $raw = static::m($cx, $raw, array($bp[0] => $raw));
397 16
                }
398
                if (isset($bp[1])) {
399 80
                    $raw = static::m($cx, $raw, array($bp[1] => $index));
400
                }
401 94
                $ret[] = $cb($cx, $raw);
402 94
            }
403 94
            if ($cx['flags']['spvar']) {
404
                if ($isObj) {
405 105
                    unset($cx['sp_vars']['key']);
406 103
                } else {
407
                    unset($cx['sp_vars']['last']);
408 105
                }
409
                unset($cx['sp_vars']['index']);
410 66
                unset($cx['sp_vars']['first']);
411 2
                $cx['sp_vars'] = $old_spvar;
412 1
            }
413 1
            if ($push) {
414
                array_pop($cx['scopes']);
415 2
            }
416
            return join('', $ret);
417 65
        }
418 11
        if ($each) {
419 10
            if ($else !== null) {
420
                $ret = $else($cx, $v);
421 11
                return $ret;
422 11
            }
423 10
            return '';
424
        }
425 11
        if ($isAry) {
426
            if ($push) {
427
                $cx['scopes'][] = $in;
428 55
            }
429 20
            $ret = $cb($cx, $v);
430
            if ($push) {
431
                array_pop($cx['scopes']);
432 35
            }
433 9
            return $ret;
434
        }
435
436 28
        if ($cx['flags']['mustsec']) {
437 9
            return $v ? $cb($cx, $in) : '';
438
        }
439
440 21
        if ($v === true) {
441 10
            return $cb($cx, $in);
442 10
        }
443
444
        if (($v !== null) && ($v !== false)) {
445 12
            return $cb($cx, $v);
446
        }
447
448
        if ($else !== null) {
449
            $ret = $else($cx, $in);
450
            return $ret;
451
        }
452
453
        return '';
454
    }
455
456
    /**
457
     * For {{#with}} .
458
     *
459
     * @param array<string,array|string|integer> $cx render time context for lightncandy
460
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
461
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
462
     * @param array<string>|null $bp block parameters
463
     * @param Closure $cb callback function to render child context
464
     * @param Closure|null $else callback function to render child context when {{else}}
465 30
     *
466 30
     * @return string The rendered string of the token
467 4
     *
468
     * @expect '' when input array(), false, null, false, function () {return 'A';}
469 30
     * @expect '' when input array(), null, null, null, function () {return 'A';}
470 5
     * @expect '{"a":"b"}' when input array(), array('a'=>'b'), null, array('a'=>'c'), function ($c, $i) {return json_encode($i);}
471
     * @expect '-b=' when input array(), 'b', null, array('a'=>'b'), function ($c, $i) {return "-$i=";}
472 26
     */
473 5
    public static function wi($cx, $v, $bp, $in, $cb, $else = null) {
474
        if (isset($bp[0])) {
475 21
            $v = static::m($cx, $v, array($bp[0] => $v));
476 21
        }
477 21
        if (($v === false) || ($v === null) || (is_array($v) && (count($v) === 0))) {
478
            return $else ? $else($cx, $in) : '';
479 26
        }
480
        if ($v === $in) {
481
            $ret = $cb($cx, $v);
482
        } else {
483
            $cx['scopes'][] = $in;
484
            $ret = $cb($cx, $v);
485
            array_pop($cx['scopes']);
486
        }
487
        return $ret;
488
    }
489
490
    /**
491
     * Get merged context.
492 103
     *
493 103
     * @param array<string,array|string|integer> $cx render time context for lightncandy
494 103
     * @param array<array|string|integer>|string|integer|null $a the context to be merged
495 14
     * @param array<array|string|integer>|string|integer|null $b the new context to overwrite
496 92
     *
497 82
     * @return array<array|string|integer>|string|integer the merged context object
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string|integer|null|StringObject? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
498 10
     *
499 6
     */
500 2
    public static function m($cx, $a, $b) {
501
        if (is_array($b)) {
502 6
            if ($a === null) {
503 2
                return $b;
504
            } else if (is_array($a)) {
505
                return array_merge($a, $b);
506
            } else if ($cx['flags']['method'] || $cx['flags']['prop']) {
507 10
                if (!is_object($a)) {
508
                    $a = new StringObject($a);
509
                }
510
                foreach ($b as $i => $v) {
511
                    $a->$i = $v;
512
                }
513
            }
514
        }
515
        return $a;
516
    }
517
518
    /**
519
     * For {{> partial}} .
520 100
     *
521 100
     * @param array<string,array|string|integer> $cx render time context for lightncandy
522
     * @param string $p partial name
523 100
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
524 8
     *
525 4
     * @return string The rendered string of the partial
526
     *
527
     */
528 94
    public static function p($cx, $p, $v, $pid, $sp = '') {
529
        $pp = ($p === '@partial-block') ? "$p" . ($pid > 0 ? $pid : $cx['partialid']) : $p;
530 94
531
        if (!isset($cx['partials'][$pp])) {
532
            static::err($cx, "Can not find partial named as '$p' !!");
533
            return '';
534
        }
535
536
        $cx['partialid'] = ($p === '@partial-block') ? (($pid > 0) ? $pid : (($cx['partialid'] > 0) ? $cx['partialid'] - 1 : 0)) : $pid;
537
538
        return call_user_func($cx['partials'][$pp], $cx, static::m($cx, $v[0][0], $v[1]), $sp);
539
    }
540
541 7
    /**
542 7
     * For {{#* inlinepartial}} .
543 7
     *
544
     * @param array<string,array|string|integer> $cx render time context for lightncandy
545
     * @param string $p partial name
546
     * @param Closure $code the compiled partial code
547
     *
548
     */
549
    public static function in(&$cx, $p, $code) {
550
        $cx['partials'][$p] = $code;
551
    }
552
553
    /* For single custom helpers.
554
     *
555 120
     * @param array<string,array|string|integer> $cx render time context for lightncandy
556 120
     * @param string $ch the name of custom helper to be executed
557 1
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
558
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
559
     * @param array<string,array|string|integer> $_this current rendering context for the helper
560
     *
561 120
     * @return string The rendered string of the token
562 120
     */
563 120
    public static function hbch($cx, $ch, $vars, $op, &$_this) {
564 120
        if (isset($cx['blparam'][0][$ch])) {
565 120
            return $cx['blparam'][0][$ch];
566
        }
567
568 120
        $options = array(
569 115
            'name' => $ch,
570
            'hash' => $vars[1],
571
            'contexts' => count($cx['scopes']) ? $cx['scopes'] : array(null),
572 120
            'fn.blockParams' => 0,
573
            '_this' => &$_this
574
        );
575
576
        if ($cx['flags']['spvar']) {
577
            $options['data'] = $cx['sp_vars'];
578
        }
579
580
        return static::exch($cx, $ch, $vars, $options);
581
    }
582
583
    /**
584
     * For block custom helpers.
585
     *
586
     * @param array<string,array|string|integer> $cx render time context for lightncandy
587
     * @param string $ch the name of custom helper to be executed
588 57
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
589
     * @param array<string,array|string|integer> $_this current rendering context for the helper
590 57
     * @param boolean $inverted the logic will be inverted
591 57
     * @param Closure|null $cb callback function to render child context
592 57
     * @param Closure|null $else callback function to render child context when {{else}}
593 57
     *
594 57
     * @return string The rendered string of the token
595
     */
596
    public static function hbbch($cx, $ch, $vars, &$_this, $inverted, $cb, $else = null) {
597 57
        $options = array(
598 53
            'name' => $ch,
599
            'hash' => $vars[1],
600
            'contexts' => count($cx['scopes']) ? $cx['scopes'] : array(null),
601 57
            'fn.blockParams' => 0,
602 3
            '_this' => &$_this,
603
        );
604
605
        if ($cx['flags']['spvar']) {
606 57
            $options['data'] = $cx['sp_vars'];
607
        }
608
609
        if (isset($vars[2])) {
610
            $options['fn.blockParams'] = count($vars[2]);
611
        }
612
613 46
        // $invert the logic
614
        if ($inverted) {
615
            $tmp = $else;
616 46
            $else = $cb;
617 6
            $cb = $tmp;
618 6
        }
619
620 46
        $options['fn'] = function ($context = '_NO_INPUT_HERE_', $data = null) use ($cx, &$_this, $cb, $options, $vars) {
621 46
            if ($cx['flags']['echo']) {
622 3
                ob_start();
623 3
            }
624 44
            if (isset($data['data'])) {
625 1
                $old_spvar = $cx['sp_vars'];
626
                $cx['sp_vars'] = array_merge(array('root' => $old_spvar['root']), $data['data'], array('_parent' => $old_spvar));
627 46
            }
628 29
            $ex = false;
629
            if (isset($data['blockParams']) && isset($vars[2])) {
630 20
                $ex = array_combine($vars[2], array_slice($data['blockParams'], 0, count($vars[2])));
631 20
                array_unshift($cx['blparam'], $ex);
632 20
            } else if (isset($cx['blparam'][0])) {
633
                $ex = $cx['blparam'][0];
634 46
            }
635 6
            if (($context === '_NO_INPUT_HERE_') || ($context === $_this)) {
636
                $ret = $cb($cx, is_array($ex) ? static::m($cx, $_this, $ex) : $_this);
637 46
            } else {
638
                $cx['scopes'][] = $_this;
639
                $ret = $cb($cx, is_array($ex) ? static::m($cx, $context, $ex) : $context);
640 57
                array_pop($cx['scopes']);
641
            }
642 6
            if (isset($data['data'])) {
643
                $cx['sp_vars'] = $old_spvar;
644
            }
645 6
            return $cx['flags']['echo'] ? ob_get_clean() : $ret;
646 1
        };
647
648 5
        if ($else) {
649 5
            $options['inverse'] = function ($context = '_NO_INPUT_HERE_') use ($cx, $_this, $else) {
650 5
                if ($cx['flags']['echo']) {
651
                    ob_start();
652 6
                }
653 10
                if ($context === '_NO_INPUT_HERE_') {
654
                    $ret = $else($cx, $_this);
655
                } else {
656
                    $cx['scopes'][] = $_this;
657
                    $ret = $else($cx, $context);
658
                    array_pop($cx['scopes']);
659
                }
660 57
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
661
            };
662
        } else {
663
            $options['inverse'] = function () {
664
                return '';
665
            };
666
        }
667
668
        return static::exch($cx, $ch, $vars, $options);
669
    }
670
671
    /**
672
     * Execute custom helper with prepared options
673 167
     *
674 167
     * @param array<string,array|string|integer> $cx render time context for lightncandy
675 167
     * @param string $ch the name of custom helper to be executed
676 167
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
677 167
     * @param array<string,array|string|integer> $options the options object
678
     *
679
     * @return string The rendered string of the token
680 167
     */
681 2
    public static function exch($cx, $ch, $vars, &$options) {
682 2
        $args = $vars[0];
683
        $args[] = $options;
684
        $e = null;
685 167
        $r = true;
686 2
687
        try {
688
            $r = call_user_func_array($cx['helpers'][$ch], $args);
689 166
        } catch (\Exception $E) {
690
            $e = "Runtime: call custom helper '$ch' error: " . $E->getMessage();
691
        }
692
693
        if($e !== null) {
694
            static::err($cx, $e);
695
        }
696
697
        return $r;
698
    }
699
}
700