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 — master ( 21f791...86a886 )
by Zordius
04:17
created

StringObject   A

Complexity

Total Complexity 2

Size/Duplication

Total Lines 12
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 2
lcom 0
cbo 0
dl 0
loc 12
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A __toString() 0 3 1
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 1
    public function __construct($string) {
31 1
        $this->string = $string;
32 1
    }
33
34 1
    public function __toString() {
35 1
        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
            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
                        $v = $v->$name();
173 4
                        continue;
174
                    }
175
                }
176 34
                if ($cx['flags']['mustlok']) {
177 31
                    unset($v);
178 31
                    break;
179
                }
180 3
                return null;
181
            }
182 351
            if (isset($v)) {
183 340
                if ($v instanceof \Closure) {
184 29
                    if ($cx['flags']['mustlam'] || $cx['flags']['lambda']) {
185 29
                        if (!$cx['flags']['knohlp'] && ($args || ($args === 0))) {
186 20
                            $A = $args ? $args[0] : array();
187 20
                            $A[] = array('hash' => $args[1], '_this' => $in);
188
                        } else {
189 10
                            $A = array($in);
190
                        }
191 29
                        $v = call_user_func_array($v, $A);
192
                    }
193
                }
194 340
                return $v;
195
            }
196 31
            $count--;
197
            switch ($count) {
198 31
                case -1:
199 30
                    $base = $cx['sp_vars']['root'];
200 30
                    break;
201 30
                case -2:
202 29
                    return null;
203
                default:
204 6
                    $base = $cx['scopes'][$count];
205
            }
206
        }
207 40
        if ($args) {
208 3
            static::err($cx, 'Can not find helper or lambda: "' . implode('.', $path) . '" !');
209
        }
210 40
    }
211
212
    /**
213
     * For {{#if}} .
214
     *
215
     * @param array<string,array|string|integer> $cx render time context for lightncandy
216
     * @param array<array|string|integer>|string|integer|null $v value to be tested
217
     * @param boolean $zero include zero as true
218
     *
219
     * @return boolean Return true when the value is not null nor false.
220
     *
221
     * @expect false when input array(), null, false
222
     * @expect false when input array(), 0, false
223
     * @expect true when input array(), 0, true
224
     * @expect false when input array(), false, false
225
     * @expect true when input array(), true, false
226
     * @expect true when input array(), 1, false
227
     * @expect false when input array(), '', false
228
     * @expect false when input array(), array(), false
229
     * @expect true when input array(), array(''), false
230
     * @expect true when input array(), array(0), false
231
     */
232 74
    public static function ifvar($cx, $v, $zero) {
233 74
        return ($v !== null) && ($v !== false) && ($zero || ($v !== 0) && ($v !== 0.0)) && ($v !== '') && (is_array($v) ? (count($v) > 0) : true);
234
    }
235
236
    /**
237
     * For {{^var}} .
238
     *
239
     * @param array<string,array|string|integer> $cx render time context for lightncandy
240
     * @param array<array|string|integer>|string|integer|null $v value to be tested
241
     *
242
     * @return boolean Return true when the value is not null nor false.
243
     *
244
     * @expect true when input array(), null
245
     * @expect false when input array(), 0
246
     * @expect true when input array(), false
247
     * @expect false when input array(), 'false'
248
     * @expect true when input array(), array()
249
     * @expect false when input array(), array('1')
250
     */
251 37
    public static function isec($cx, $v) {
252 37
        return ($v === null) || ($v === false) || (is_array($v) && (count($v) === 0));
253
    }
254
255
    /**
256
     * For {{var}} .
257
     *
258
     * @param array<string,array|string|integer> $cx render time context for lightncandy
259
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
260
     *
261
     * @return string The htmlencoded value of the specified variable
262
     *
263
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
264
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
265
     * @expect 'a&#039;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
266
     * @expect 'a&b' when input null, new \LightnCandy\SafeString('a&b')
267
     */
268 46
    public static function enc($cx, $var) {
269 46
        if ($var instanceof \LightnCandy\SafeString) {
270 1
            return (string)$var;
271
        }
272
273 46
        return htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8');
274
    }
275
276
    /**
277
     * For {{var}} , do html encode just like handlebars.js .
278
     *
279
     * @param array<string,array|string|integer> $cx render time context for lightncandy
280
     * @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
281
     *
282
     * @return string The htmlencoded value of the specified variable
283
     *
284
     * @expect 'a' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a'
285
     * @expect 'a&amp;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a&b'
286
     * @expect 'a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), 'a\'b'
287
     * @expect '&#x60;a&#x27;b' when input array('flags' => array('mustlam' => 0, 'lambda' => 0)), '`a\'b'
288
     */
289 340
    public static function encq($cx, $var) {
290 340
        if ($var instanceof \LightnCandy\SafeString) {
291 3
            return (string)$var;
292
        }
293
294 337
        return str_replace(array('=', '`', '&#039;'), array('&#x3D;', '&#x60;', '&#x27;'), htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8'));
295
    }
296
297
    /**
298
     * For {{#var}} or {{#each}} .
299
     *
300
     * @param array<string,array|string|integer> $cx render time context for lightncandy
301
     * @param array<array|string|integer>|string|integer|null $v value for the section
302
     * @param array<string>|null $bp block parameters
303
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
304
     * @param boolean $each true when rendering #each
305
     * @param Closure $cb callback function to render child context
306
     * @param Closure|null $else callback function to render child context when {{else}}
307
     *
308
     * @return string The rendered string of the section
309
     *
310
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), false, null, false, false, function () {return 'A';}
311
     * @expect '' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), null, null, null, false, function () {return 'A';}
312
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), true, null, true, false, function () {return 'A';}
313
     * @expect 'A' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 0, null, 0, false, function () {return 'A';}
314
     * @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=";}
315
     * @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=";}
316
     * @expect '' when input array('scopes' => array(), 'flags' => array('spvar' => 0, 'mustlam' => 0, 'lambda' => 0)), 'abc', null, 'abc', true, function ($c, $i) {return "-$i=";}
317
     * @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=";}
318
     * @expect '1' when input array('flags' => array('spvar' => 0, 'mustlam' => 0, 'mustsec' => 0, 'lambda' => 0)), 'b', null, 'b', false, function ($c, $i) {return count($i);}
319
     * @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);}
320
     * @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);}
321
     * @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);}
322
     * @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';}
323
     * @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';}
324
     * @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';}
325
     * @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';}
326
     * @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';}
327
     * @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';}
328
     * @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';}
329
     * @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';}
330
     * @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';}
331
     * @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';}
332
     * @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;}
333
     * @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'];}
334
     */
335 170
    public static function sec($cx, $v, $bp, $in, $each, $cb, $else = null) {
336 170
        $push = ($in !== $v) || $each;
337
338 170
        $isAry = is_array($v) || ($v instanceof \ArrayObject);
339 170
        $isTrav = $v instanceof \Traversable;
340 170
        $loop = $each;
341 170
        $keys = null;
342 170
        $last = null;
343 170
        $isObj = false;
344
345 170
        if ($isAry && $else !== null && count($v) === 0) {
346 3
            $ret = $else($cx, $in);
347 3
            return $ret;
348
        }
349
350
        // #var, detect input type is object or not
351 168
        if (!$loop && $isAry) {
352 66
            $keys = array_keys($v);
353 66
            $loop = (count(array_diff_key($v, array_keys($keys))) == 0);
354 66
            $isObj = !$loop;
355
        }
356
357 168
        if (($loop && $isAry) || $isTrav) {
358 106
            if ($each && !$isTrav) {
359
                // Detect input type is object or not when never done once
360 50
                if ($keys == null) {
361 50
                    $keys = array_keys($v);
362 50
                    $isObj = (count(array_diff_key($v, array_keys($keys))) > 0);
363
                }
364
            }
365 106
            $ret = array();
366 106
            if ($push) {
367 104
                $cx['scopes'][] = $in;
368
            }
369 106
            $i = 0;
370 106
            if ($cx['flags']['spvar']) {
371 95
                $old_spvar = $cx['sp_vars'];
372 95
                $cx['sp_vars'] = array_merge(array('root' => $old_spvar['root']), $old_spvar, array('_parent' => $old_spvar));
373 95
                if (!$isTrav) {
374 94
                    $last = count($keys) - 1;
375
                }
376
            }
377
378 106
            $isSparceArray = $isObj && (count(array_filter(array_keys($v), 'is_string')) == 0);
379 106
            foreach ($v as $index => $raw) {
380 99
                if ($cx['flags']['spvar']) {
381 89
                    $cx['sp_vars']['first'] = ($i === 0);
382 89
                    $cx['sp_vars']['last'] = ($i == $last);
383 89
                    $cx['sp_vars']['key'] = $index;
384 89
                    $cx['sp_vars']['index'] = $isSparceArray ? $index : $i;
385 89
                    $i++;
386
                }
387 99
                if (isset($bp[0])) {
388 4
                    $raw = static::m($cx, $raw, array($bp[0] => $raw));
389
                }
390 99
                if (isset($bp[1])) {
391 3
                    $raw = static::m($cx, $raw, array($bp[1] => $index));
392
                }
393 99
                $ret[] = $cb($cx, $raw);
394
            }
395 105
            if ($cx['flags']['spvar']) {
396 94
                if ($isObj) {
397 16
                    unset($cx['sp_vars']['key']);
398
                } else {
399 80
                    unset($cx['sp_vars']['last']);
400
                }
401 94
                unset($cx['sp_vars']['index']);
402 94
                unset($cx['sp_vars']['first']);
403 94
                $cx['sp_vars'] = $old_spvar;
404
            }
405 105
            if ($push) {
406 103
                array_pop($cx['scopes']);
407
            }
408 105
            return join('', $ret);
409
        }
410 66
        if ($each) {
411 2
            if ($else !== null) {
412 1
                $ret = $else($cx, $v);
413 1
                return $ret;
414
            }
415 2
            return '';
416
        }
417 65
        if ($isAry) {
418 11
            if ($push) {
419 10
                $cx['scopes'][] = $in;
420
            }
421 11
            $ret = $cb($cx, $v);
422 11
            if ($push) {
423 10
                array_pop($cx['scopes']);
424
            }
425 11
            return $ret;
426
        }
427
428 55
        if ($cx['flags']['mustsec']) {
429 20
            return $v ? $cb($cx, $in) : '';
430
        }
431
432 35
        if ($v === true) {
433 9
            return $cb($cx, $in);
434
        }
435
436 28
        if (($v !== null) && ($v !== false)) {
437 9
            return $cb($cx, $v);
438
        }
439
440 21
        if ($else !== null) {
441 10
            $ret = $else($cx, $in);
442 10
            return $ret;
443
        }
444
445 12
        return '';
446
    }
447
448
    /**
449
     * For {{#with}} .
450
     *
451
     * @param array<string,array|string|integer> $cx render time context for lightncandy
452
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
453
     * @param array<array|string|integer>|string|integer|null $in input data with current scope
454
     * @param array<string>|null $bp block parameters
455
     * @param Closure $cb callback function to render child context
456
     * @param Closure|null $else callback function to render child context when {{else}}
457
     *
458
     * @return string The rendered string of the token
459
     *
460
     * @expect '' when input array(), false, null, false, function () {return 'A';}
461
     * @expect '' when input array(), null, null, null, function () {return 'A';}
462
     * @expect '{"a":"b"}' when input array(), array('a'=>'b'), null, array('a'=>'c'), function ($c, $i) {return json_encode($i);}
463
     * @expect '-b=' when input array(), 'b', null, array('a'=>'b'), function ($c, $i) {return "-$i=";}
464
     */
465 30
    public static function wi($cx, $v, $bp, $in, $cb, $else = null) {
466 30
        if (isset($bp[0])) {
467 4
            $v = static::m($cx, $v, array($bp[0] => $v));
468
        }
469 30
        if (($v === false) || ($v === null) || (is_array($v) && (count($v) === 0))) {
470 5
            return $else ? $else($cx, $in) : '';
471
        }
472 26
        if ($v === $in) {
473 5
            $ret = $cb($cx, $v);
474
        } else {
475 21
            $cx['scopes'][] = $in;
476 21
            $ret = $cb($cx, $v);
477 21
            array_pop($cx['scopes']);
478
        }
479 26
        return $ret;
480
    }
481
482
    /**
483
     * Get merged context.
484
     *
485
     * @param array<string,array|string|integer> $cx render time context for lightncandy
486
     * @param array<array|string|integer>|string|integer|null $a the context to be merged
487
     * @param array<array|string|integer>|string|integer|null $b the new context to overwrite
488
     *
489
     * @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...
490
     *
491
     */
492 102
    public static function m($cx, $a, $b) {
493 102
        if (is_array($b)) {
494 102
            if ($a === null) {
495 14
                return $b;
496 91
            } else if (is_array($a)) {
497 82
                return array_merge($a, $b);
498 9
            } else if ($cx['flags']['method'] || $cx['flags']['prop']) {
499 5
                if (!is_object($a)) {
500 1
                    $a = new StringObject($a);
501
                }
502 5
                foreach ($b as $i => $v) {
503 2
                    $a->$i = $v;
504
                }
505
            }
506
        }
507 9
        return $a;
508
    }
509
510
    /**
511
     * For {{> partial}} .
512
     *
513
     * @param array<string,array|string|integer> $cx render time context for lightncandy
514
     * @param string $p partial name
515
     * @param array<array|string|integer>|string|integer|null $v value to be the new context
516
     *
517
     * @return string The rendered string of the partial
518
     *
519
     */
520 99
    public static function p($cx, $p, $v, $pid, $sp = '') {
521 99
        $pp = ($p === '@partial-block') ? "$p" . ($pid > 0 ? $pid : $cx['partialid']) : $p;
522
523 99
        if (!isset($cx['partials'][$pp])) {
524 8
            static::err($cx, "Can not find partial named as '$p' !!");
525 4
            return '';
526
        }
527
528 93
        $cx['partialid'] = ($p === '@partial-block') ? (($pid > 0) ? $pid : (($cx['partialid'] > 0) ? $cx['partialid'] - 1 : 0)) : $pid;
529
530 93
        return call_user_func($cx['partials'][$pp], $cx, static::m($cx, $v[0][0], $v[1]), $sp);
531
    }
532
533
    /**
534
     * For {{#* inlinepartial}} .
535
     *
536
     * @param array<string,array|string|integer> $cx render time context for lightncandy
537
     * @param string $p partial name
538
     * @param Closure $code the compiled partial code
539
     *
540
     */
541 7
    public static function in(&$cx, $p, $code) {
542 7
        $cx['partials'][$p] = $code;
543 7
    }
544
545
    /* For single custom helpers.
546
     *
547
     * @param array<string,array|string|integer> $cx render time context for lightncandy
548
     * @param string $ch the name of custom helper to be executed
549
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
550
     * @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
551
     * @param array<string,array|string|integer> $_this current rendering context for the helper
552
     *
553
     * @return string The rendered string of the token
554
     */
555 120
    public static function hbch($cx, $ch, $vars, $op, &$_this) {
556 120
        if (isset($cx['blparam'][0][$ch])) {
557 1
            return $cx['blparam'][0][$ch];
558
        }
559
560
        $options = array(
561 120
            'name' => $ch,
562 120
            'hash' => $vars[1],
563 120
            'contexts' => count($cx['scopes']) ? $cx['scopes'] : array(null),
564 120
            'fn.blockParams' => 0,
565 120
            '_this' => &$_this
566
        );
567
568 120
        if ($cx['flags']['spvar']) {
569 115
            $options['data'] = $cx['sp_vars'];
570
        }
571
572 120
        return static::exch($cx, $ch, $vars, $options);
573
    }
574
575
    /**
576
     * For block custom helpers.
577
     *
578
     * @param array<string,array|string|integer> $cx render time context for lightncandy
579
     * @param string $ch the name of custom helper to be executed
580
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
581
     * @param array<string,array|string|integer> $_this current rendering context for the helper
582
     * @param boolean $inverted the logic will be inverted
583
     * @param Closure|null $cb callback function to render child context
584
     * @param Closure|null $else callback function to render child context when {{else}}
585
     *
586
     * @return string The rendered string of the token
587
     */
588 57
    public static function hbbch($cx, $ch, $vars, &$_this, $inverted, $cb, $else = null) {
589
        $options = array(
590 57
            'name' => $ch,
591 57
            'hash' => $vars[1],
592 57
            'contexts' => count($cx['scopes']) ? $cx['scopes'] : array(null),
593 57
            'fn.blockParams' => 0,
594 57
            '_this' => &$_this,
595
        );
596
597 57
        if ($cx['flags']['spvar']) {
598 53
            $options['data'] = $cx['sp_vars'];
599
        }
600
601 57
        if (isset($vars[2])) {
602 3
            $options['fn.blockParams'] = count($vars[2]);
603
        }
604
605
        // $invert the logic
606 57
        if ($inverted) {
607
            $tmp = $else;
608
            $else = $cb;
609
            $cb = $tmp;
610
        }
611
612
        $options['fn'] = function ($context = '_NO_INPUT_HERE_', $data = null) use ($cx, &$_this, $cb, $options, $vars) {
613 46
            if ($cx['flags']['echo']) {
614
                ob_start();
615
            }
616 46
            if (isset($data['data'])) {
617 6
                $old_spvar = $cx['sp_vars'];
618 6
                $cx['sp_vars'] = array_merge(array('root' => $old_spvar['root']), $data['data'], array('_parent' => $old_spvar));
619
            }
620 46
            $ex = false;
621 46
            if (isset($data['blockParams']) && isset($vars[2])) {
622 3
                $ex = array_combine($vars[2], array_slice($data['blockParams'], 0, count($vars[2])));
623 3
                array_unshift($cx['blparam'], $ex);
624 44
            } else if (isset($cx['blparam'][0])) {
625 1
                $ex = $cx['blparam'][0];
626
            }
627 46
            if (($context === '_NO_INPUT_HERE_') || ($context === $_this)) {
628 29
                $ret = $cb($cx, is_array($ex) ? static::m($cx, $_this, $ex) : $_this);
629
            } else {
630 20
                $cx['scopes'][] = $_this;
631 20
                $ret = $cb($cx, is_array($ex) ? static::m($cx, $context, $ex) : $context);
632 20
                array_pop($cx['scopes']);
633
            }
634 46
            if (isset($data['data'])) {
635 6
                $cx['sp_vars'] = $old_spvar;
636
            }
637 46
            return $cx['flags']['echo'] ? ob_get_clean() : $ret;
638
        };
639
640 57
        if ($else) {
641
            $options['inverse'] = function ($context = '_NO_INPUT_HERE_') use ($cx, $_this, $else) {
642 6
                if ($cx['flags']['echo']) {
643
                    ob_start();
644
                }
645 6
                if ($context === '_NO_INPUT_HERE_') {
646 1
                    $ret = $else($cx, $_this);
647
                } else {
648 5
                    $cx['scopes'][] = $_this;
649 5
                    $ret = $else($cx, $context);
650 5
                    array_pop($cx['scopes']);
651
                }
652 6
                return $cx['flags']['echo'] ? ob_get_clean() : $ret;
653 10
            };
654
        } else {
655
            $options['inverse'] = function () {
656
                return '';
657
            };
658
        }
659
660 57
        return static::exch($cx, $ch, $vars, $options);
661
    }
662
663
    /**
664
     * Execute custom helper with prepared options
665
     *
666
     * @param array<string,array|string|integer> $cx render time context for lightncandy
667
     * @param string $ch the name of custom helper to be executed
668
     * @param array<array|string|integer>|string|integer|null $vars variables for the helper
669
     * @param array<string,array|string|integer> $options the options object
670
     *
671
     * @return string The rendered string of the token
672
     */
673 167
    public static function exch($cx, $ch, $vars, &$options) {
674 167
        $args = $vars[0];
675 167
        $args[] = $options;
676 167
        $e = null;
677 167
        $r = true;
678
679
        try {
680 167
            $r = call_user_func_array($cx['helpers'][$ch], $args);
681 2
        } catch (\Exception $E) {
682 2
            $e = "Runtime: call custom helper '$ch' error: " . $E->getMessage();
683
        }
684
685 167
        if($e !== null) {
686 2
            static::err($cx, $e);
687
        }
688
689 166
        return $r;
690
    }
691
}
692