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 ( 9799ea...0ad74a )
by Zordius
03:45
created

Compiler   D

Complexity

Total Complexity 123

Size/Duplication

Total Lines 581
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 89.21%

Importance

Changes 59
Bugs 5 Features 5
Metric Value
wmc 123
c 59
b 5
f 5
lcom 1
cbo 6
dl 0
loc 581
ccs 215
cts 241
cp 0.8921
rs 4.8718

20 Methods

Rating   Name   Duplication   Size   Complexity  
A getVariableNameOrSubExpression() 0 3 2
A invertedSection() 0 4 1
B blockCustomHelper() 0 11 5
A with() 0 7 4
B customHelper() 0 12 7
B compileLookup() 0 9 7
B compileVariable() 0 8 7
B compileTemplate() 0 34 5
A composePHPRender() 0 52 3
A getFuncName() 0 13 4
A getVariableNames() 0 15 4
A compileSubExpression() 0 14 4
F getVariableName() 0 40 22
C compileToken() 0 29 7
C partial() 0 23 8
D blockEnd() 0 31 10
B blockBegin() 0 20 11
B section() 0 16 7
A doElse() 0 10 3
A addUsageCount() 0 6 2

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
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 of LightnCandy Compiler
16
 *
17
 * @package    LightnCandy
18
 * @author     Zordius <[email protected]>
19
 */
20
21
namespace LightnCandy;
22
23
use \LightnCandy\Validator;
24
use \LightnCandy\Token;
25
use \LightnCandy\Expression;
26
use \LightnCandy\Parser;
27
28
/**
29
 * LightnCandy Compiler
30
 */
31
class Compiler extends Validator
32
{
33
    public static $lastParsed;
34
35
    /**
36
     * Compile template into PHP code
37
     *
38
     * @param array<string,array|string|integer> $context Current context
39
     * @param string $template handlebars template
40
     *
41
     * @return string|null generated PHP code
42
     */
43 640
    public static function compileTemplate(&$context, $template) {
44 640
        array_unshift($context['parsed'], array());
45 640
        Validator::verify($context, $template);
46
47 640
        if (count($context['error'])) {
48 65
            return;
49
        }
50
51
        // Do PHP code generation.
52 576
        Parser::setDelimiter($context);
53
54
        // Handle dynamic partials
55 576
        Partial::handleDynamicPartial($context);
56
57 576
        $code = '';
58 576
        foreach ($context['parsed'][0] as $info) {
59 576
            if (is_array($info)) {
60 535
                $context['tokens']['current']++;
61 535
                $tmpl = static::compileToken($context, $info);
62 535
                if ($tmpl == $context['ops']['seperator']) {
63 1
                    $tmpl = '';
64
                } else {
65 534
                    $tmpl = "'$tmpl'";
66
                }
67 535
                $code .= $tmpl;
68
            } else {
69 576
                $code .= $info;
70
            }
71
        }
72
73 576
        static::$lastParsed = array_shift($context['parsed']);
74
75 576
        return $code;
76
    }
77
78
    /**
79
     * Compose LightnCandy render codes for include()
80
     *
81
     * @param array<string,array|string|integer> $context Current context
82
     * @param string $code generated PHP code
83
     *
84
     * @return string Composed PHP code
85
     */
86 575
    public static function composePHPRender($context, $code) {
87 575
        $flagJStrue = Expression::boolString($context['flags']['jstrue']);
88 575
        $flagJSObj = Expression::boolString($context['flags']['jsobj']);
89 575
        $flagSPVar = Expression::boolString($context['flags']['spvar']);
90 575
        $flagProp = Expression::boolString($context['flags']['prop']);
91 575
        $flagMethod = Expression::boolString($context['flags']['method']);
92 575
        $flagLambda = Expression::boolString($context['flags']['lambda']);
93 575
        $flagMustlok = Expression::boolString($context['flags']['mustlok']);
94 575
        $flagMustlam = Expression::boolString($context['flags']['mustlam']);
95 575
        $flagEcho = Expression::boolString($context['flags']['echo']);
96 575
        $flagPartNC = Expression::boolString($context['flags']['partnc']);
97
98 575
        $libstr = Exporter::runtime($context);
99 575
        $constants = Exporter::constants($context);
100 575
        $helpers = Exporter::helpers($context);
101 575
        $bhelpers = Exporter::helpers($context, 'blockhelpers');
102 575
        $hbhelpers = Exporter::helpers($context, 'hbhelpers');
103 575
        $debug = Runtime::DEBUG_ERROR_LOG;
104 575
        $phpstart = $context['flags']['bare'] ? '' : "<?php use {$context['runtime']} as LR;\n";
105 575
        $phpend = $context['flags']['bare'] ? ';' : "\n?>";
106
107
        // Return generated PHP code string.
108 575
        return "{$phpstart}return function (\$in, \$options = null) {
109
    \$cx = array(
110
        'flags' => array(
111
            'jstrue' => $flagJStrue,
112
            'jsobj' => $flagJSObj,
113
            'spvar' => $flagSPVar,
114
            'prop' => $flagProp,
115
            'method' => $flagMethod,
116
            'lambda' => $flagLambda,
117
            'mustlok' => $flagMustlok,
118
            'mustlam' => $flagMustlam,
119
            'echo' => $flagEcho,
120
            'partnc' => $flagPartNC,
121
            'debug' => isset(\$options['debug']) ? \$options['debug'] : $debug,
122
        ),
123
        'constants' => $constants,
124
        'helpers' => $helpers,
125
        'blockhelpers' => $bhelpers,
126
        'hbhelpers' => isset(\$options['helpers']) ? array_merge($hbhelpers, \$options['helpers']) : $hbhelpers,
127 575
        'partials' => array({$context['partialCode']}),
128
        'scopes' => array(),
129
        'sp_vars' => isset(\$options['data']) ? array_merge(array('root' => \$in), \$options['data']) : array('root' => \$in),
130
        'blparam' => array(),
131 575
        'runtime' => '{$context['runtime']}',
132
$libstr
133
    );
134 575
    {$context['renderex']}
135 575
    {$context['ops']['op_start']}'$code'{$context['ops']['op_end']}
136 575
}$phpend";
137
    }
138
139
    /**
140
     * Get function name for standalone or none standalone template.
141
     *
142
     * @param array<string,array|string|integer> $context Current context of compiler progress.
143
     * @param string $name base function name
144
     * @param string $tag original handlabars tag for debug
145
     *
146
     * @return string compiled Function name
147
     *
148
     * @expect 'LR::test(' when input array('flags' => array('standalone' => 0, 'debug' => 0), 'runtime' => 'Runtime'), 'test', ''
149
     * @expect 'LR::test2(' when input array('flags' => array('standalone' => 0, 'debug' => 0), 'runtime' => 'Runtime'), 'test2', ''
150
     * @expect "\$cx['funcs']['test3'](" when input array('flags' => array('standalone' => 1, 'debug' => 0), 'runtime' => 'Runtime'), 'test3', ''
151
     * @expect 'LR::debug(\'abc\', \'test\', ' when input array('flags' => array('standalone' => 0, 'debug' => 1), 'runtime' => 'Runtime'), 'test', 'abc'
152
     */
153 511
    protected static function getFuncName(&$context, $name, $tag) {
154 511
        static::addUsageCount($context, 'runtime', $name);
155
156 511
        if ($context['flags']['debug'] && ($name != 'miss')) {
157 10
            $dbg = "'$tag', '$name', ";
158 10
            $name = 'debug';
159 10
            static::addUsageCount($context, 'runtime', 'debug');
160
        } else {
161 509
            $dbg = '';
162
        }
163
164 511
        return $context['flags']['standalone'] ? "\$cx['funcs']['$name']($dbg" : "LR::$name($dbg";
165
    }
166
167
    /**
168
     * Get string presentation of variables
169
     *
170
     * @param array<string,array|string|integer> $context current compile context
171
     * @param array<array> $vn variable name array.
172
     * @param array<string>|null $blockParams block param list
173
     *
174
     * @return array<string|array> variable names
175
     *
176
     * @expect array('array(array($in),array())', array('this')) when input array('flags'=>array('spvar'=>true)), array(null)
177
     * @expect array('array(array($in,$in),array())', array('this', 'this')) when input array('flags'=>array('spvar'=>true)), array(null, null)
178
     * @expect array('array(array(),array(\'a\'=>$in))', array('this')) when input array('flags'=>array('spvar'=>true)), array('a' => null)
179
     */
180 207
    protected static function getVariableNames(&$context, $vn, $blockParams = null) {
181 207
        $vars = array(array(), array());
182 207
        $exps = array();
183 207
        foreach ($vn as $i => $v) {
184 170
            $V = static::getVariableNameOrSubExpression($context, $v);
185 170
            if (is_string($i)) {
186 29
                $vars[1][] = "'$i'=>{$V[0]}";
187
            } else {
188 157
                $vars[0][] = $V[0];
189
            }
190 170
            $exps[] = $V[1];
191
        }
192 207
        $bp = $blockParams ? (',array(' . Expression::listString($blockParams) . ')') : '';
193 207
        return array('array(array(' . implode(',', $vars[0]) . '),array(' . implode(',', $vars[1]) . ")$bp)", $exps);
194
    }
195
196
    /**
197
     * Get string presentation of a sub expression
198
     *
199
     * @param array<string,array|string|integer> $context current compile context
200
     * @param array<boolean|integer|string|array> $vars parsed arguments list
201
     *
202
     * @return array<string> code representing passed expression
203
     */
204 35
    public static function compileSubExpression(&$context, $vars) {
205 35
        $origSeperator = $context['ops']['seperator'];
206 35
        $context['ops']['seperator'] = '';
207
208 35
        $ret = static::customHelper($context, $vars, true);
209
210 35
        if (($ret === null) && $context['flags']['lambda']) {
211 2
            $ret = static::compileVariable($context, $vars, true);
212
        }
213
214 35
        $context['ops']['seperator'] = $origSeperator;
215
216 35
        return array($ret ? $ret : '', 'FIXME: $subExpression');
217
    }
218
219
    /**
220
     * Get string presentation of a subexpression or a variable
221
     *
222
     * @param array<array|string|integer> $context current compile context
223
     * @param array<array|string|integer> $var variable parsed path
224
     *
225
     * @return array<string> variable names
226
     */
227 344
    protected static function getVariableNameOrSubExpression(&$context, $var) {
228 344
        return Parser::isSubExp($var) ? static::compileSubExpression($context, $var[1]) : static::getVariableName($context, $var);
229
    }
230
231
    /**
232
     * Get string presentation of a variable
233
     *
234
     * @param array<array|string|integer> $var variable parsed path
235
     * @param array<array|string|integer> $context current compile context
236
     * @param array<string> $lookup extra lookup string as valid PHP variable name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $lookup not be string[]|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
237
     *
238
     * @return array<string> variable names
239
     *
240
     * @expect array('$in', 'this') when input array('flags'=>array('spvar'=>true,'debug'=>0)), array(null)
241
     * @expect array('((isset($in[\'true\']) && is_array($in)) ? $in[\'true\'] : null)', '[true]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('true')
242
     * @expect array('((isset($in[\'false\']) && is_array($in)) ? $in[\'false\'] : null)', '[false]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('false')
243
     * @expect array('true', 'true') when input array('flags'=>array('spvar'=>true,'debug'=>0)), array(0, 'true')
244
     * @expect array('false', 'false') when input array('flags'=>array('spvar'=>true,'debug'=>0)), array(0, 'false')
245
     * @expect array('((isset($in[\'2\']) && is_array($in)) ? $in[\'2\'] : null)', '[2]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('2')
246
     * @expect array('2', '2') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0)), array(0, '2')
247
     * @expect array('((isset($in[\'@index\']) && is_array($in)) ? $in[\'@index\'] : null)', '[@index]') when input array('flags'=>array('spvar'=>false,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('@index')
248
     * @expect array("((isset(\$cx['sp_vars']['index']) && is_array(\$cx['sp_vars'])) ? \$cx['sp_vars']['index'] : null)", '@[index]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('@index')
249
     * @expect array("((isset(\$cx['sp_vars']['key']) && is_array(\$cx['sp_vars'])) ? \$cx['sp_vars']['key'] : null)", '@[key]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('@key')
250
     * @expect array("((isset(\$cx['sp_vars']['first']) && is_array(\$cx['sp_vars'])) ? \$cx['sp_vars']['first'] : null)", '@[first]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('@first')
251
     * @expect array("((isset(\$cx['sp_vars']['last']) && is_array(\$cx['sp_vars'])) ? \$cx['sp_vars']['last'] : null)", '@[last]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('@last')
252
     * @expect array('((isset($in[\'"a"\']) && is_array($in)) ? $in[\'"a"\'] : null)', '["a"]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('"a"')
253
     * @expect array('"a"', '"a"') when input array('flags'=>array('spvar'=>true,'debug'=>0)), array(0, '"a"')
254
     * @expect array('((isset($in[\'a\']) && is_array($in)) ? $in[\'a\'] : null)', '[a]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array('a')
255
     * @expect array('((isset($cx[\'scopes\'][count($cx[\'scopes\'])-1][\'a\']) && is_array($cx[\'scopes\'][count($cx[\'scopes\'])-1])) ? $cx[\'scopes\'][count($cx[\'scopes\'])-1][\'a\'] : null)', '../[a]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array(1,'a')
256
     * @expect array('((isset($cx[\'scopes\'][count($cx[\'scopes\'])-3][\'a\']) && is_array($cx[\'scopes\'][count($cx[\'scopes\'])-3])) ? $cx[\'scopes\'][count($cx[\'scopes\'])-3][\'a\'] : null)', '../../../[a]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array(3,'a')
257
     * @expect array('((isset($in[\'id\']) && is_array($in)) ? $in[\'id\'] : null)', 'this.[id]') when input array('flags'=>array('spvar'=>true,'debug'=>0,'prop'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0)), array(null, 'id')
258
     * @expect array('LR::v($cx, isset($in) ? $in : null, array(\'id\'))', 'this.[id]') when input array('flags'=>array('prop'=>true,'spvar'=>true,'debug'=>0,'method'=>0,'mustlok'=>0,'mustlam'=>0, 'lambda'=>0,'standalone'=>0), 'runtime' => 'Runtime'), array(null, 'id')
259
     */
260 508
    protected static function getVariableName(&$context, $var, $lookup = null) {
261 508
        if (isset($var[0]) && ($var[0] === 0)) {
262 62
            return array($var[1], preg_replace('/\'(.*)\'/', '$1', $var[1]));
263
        }
264
265 481
        list($levels, $spvar , $var) = Expression::analyze($context, $var);
0 ignored issues
show
Documentation introduced by
$var is of type array<integer,array|stri...array|string|integer"}>, but the function expects a array<integer,array|string|integer>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
266 481
        $exp = Expression::toString($levels, $spvar, $var);
267 481
        $base = $spvar ? "\$cx['sp_vars']" : '$in';
268
269
        // change base when trace to parent
270 481
        if ($levels > 0) {
271 36
            if ($spvar) {
272 2
                $base .= str_repeat("['_parent']", $levels);
273
            } else {
274 34
                $base = "\$cx['scopes'][count(\$cx['scopes'])-$levels]";
275
            }
276
        }
277
278 481
        if ((count($var) == 0) || (($var[0] === null) && (count($var) == 1))) {
279 113
            return array($base, $exp);
280
        }
281
282 439
        if ($var[0] === null) {
283 1
            array_shift($var);
284
        }
285
286
        // To support recursive context lookup, instance properties + methods and lambdas
287
        // the only way is using slower rendering time variable resolver.
288 439
        if ($context['flags']['prop'] || $context['flags']['method'] || $context['flags']['mustlok'] || $context['flags']['mustlam'] || $context['flags']['lambda']) {
289 341
            $L = $lookup ? ", $lookup[0]" : '';
290 341
            return array(static::getFuncName($context, 'v', $exp) . "\$cx, isset($base) ? $base : null, array(" . Expression::listString($var) . "$L))", $lookup ? "lookup $exp $lookup[1]" : $exp);
291
        }
292
293 99
        $n = Expression::arrayString($var);
294 99
        array_pop($var);
295 99
        $L = $lookup ? "[{$lookup[0]}]" : '';
296 99
        $p = $lookup ? $n : (count($var) ? Expression::arrayString($var) : '');
297
298 99
        return array("((isset($base$n$L) && is_array($base$p)) ? $base$n$L : " . ($context['flags']['debug'] ? (static::getFuncName($context, 'miss', '') . "\$cx, '$exp')") : 'null' ) . ')', $lookup ? "lookup $exp $lookup[1]" : $exp);
299
    }
300
301
    /**
302
     * Return compiled PHP code for a handlebars token
303
     *
304
     * @param array<string,array|string|integer> $context current compile context
305
     * @param array<string,array|boolean> $info parsed information
306
     *
307
     * @return string Return compiled code segment for the token
0 ignored issues
show
Documentation introduced by
Should the return type not be string|integer|double|boolean?

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.

Loading history...
308
     */
309 535
    protected static function compileToken(&$context, $info) {
310 535
        list($raw, $vars, $token, $indent) = $info;
311
312 535
        $context['tokens']['partialind'] = $indent;
313 535
        $context['currentToken'] = $token;
314
315
        // Do not touch the tag, keep it as is.
316 535
        if ($raw === -1) {
317
            return ".'" . Token::toString($token) . "'.";
318
        }
319
320 535
        if ($ret = static::operator($token[Token::POS_OP], $context, $vars)) {
321 329
            return $ret;
322
        }
323
324 421
        if (isset($vars[0][0])) {
325 389
            if ($ret = static::customHelper($context, $vars, $raw)) {
326 96
                return $ret;
327
            }
328 298
            if ($vars[0][0] === 'else') {
329 24
                return static::doElse($context);
330
            }
331 283
            if ($vars[0][0] === 'lookup') {
332 2
                return static::compileLookup($context, $vars, $raw);
333
            }
334
        }
335
336 320
        return static::compileVariable($context, $vars, $raw);
337
    }
338
339
    /**
340
     * handle partial
341
     *
342
     * @param array<string,array|string|integer> $context current compile context
343
     * @param array<boolean|integer|string|array> $vars parsed arguments list
344
     *
345
     * @return string Return compiled code segment for the partial
346
     */
347 64
    public static function partial(&$context, $vars) {
348
        // mustache spec: ignore missing partial
349 64
        if (($context['usedFeature']['dynpartial'] === 0) && !isset($context['usedPartial'][$vars[0][0]])) {
350 1
            return $context['ops']['seperator'];
351
        }
352 63
        $bp = Parser::getBlockParams($vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|integer|string|array>, but the function expects a array<integer,boolean|integer|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
$bp is not used, you could remove the assignment.

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

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

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

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

Loading history...
353 63
        $p = array_shift($vars);
354 63
        if ($context['flags']['runpart']) {
355 56
            if (!isset($vars[0])) {
356 50
                $vars[0] = $context['flags']['partnc'] ? array(0, 'null') : array();
357
            }
358 56
            $v = static::getVariableNames($context, $vars);
359 56
            $tag = ">$p[0] " .implode(' ', $v[1]);
360 56
            if (Parser::isSubExp($p)) {
361 4
                list($p) = static::compileSubExpression($context, $p[1]);
362
            } else {
363 52
                $p = "'$p[0]'";
364
            }
365 56
            $sp = $context['tokens']['partialind'] ? ", '{$context['tokens']['partialind']}'" : '';
366 56
            return $context['ops']['seperator'] . static::getFuncName($context, 'p', $tag) . "\$cx, $p, $v[0]$sp){$context['ops']['seperator']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $context['ops']['...['ops']['seperator']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::partial of type integer|double|boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
367
        }
368 7
        return "{$context['ops']['seperator']}'" . Partial::compileStatic($context, $p[0]) . "'{$context['ops']['seperator']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return "{$context['ops']...['ops']['seperator']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::partial of type integer|double|boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
369
    }
370
371
    /**
372
     * Return compiled PHP code for a handlebars inverted section begin token
373
     *
374
     * @param array<string,array|string|integer> $context current compile context
375
     * @param array<boolean|integer|string|array> $vars parsed arguments list
376
     *
377
     * @return string Return compiled code segment for the token
378
     */
379 37
    protected static function invertedSection(&$context, $vars) {
380 37
        $v = static::getVariableName($context, $vars[0]);
381 37
        return "{$context['ops']['cnd_start']}(" . static::getFuncName($context, 'isec', '^' . $v[1]) . "\$cx, {$v[0]})){$context['ops']['cnd_then']}";
382
    }
383
384
    /**
385
     * Return compiled PHP code for a handlebars block custom helper begin token
386
     *
387
     * @param array<string,array|string|integer> $context current compile context
388
     * @param array<boolean|integer|string|array> $vars parsed arguments list
389
     * @param boolean $inverted the logic will be inverted
390
     *
391
     * @return string Return compiled code segment for the token
392
     */
393 54
    protected static function blockCustomHelper(&$context, $vars, $inverted = false) {
394 54
        $notHBCH = !isset($context['hbhelpers'][$vars[0][0]]);
395
396 54
        $bp = Parser::getBlockParams($vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|integer|string|array>, but the function expects a array<integer,boolean|integer|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
397 54
        $ch = array_shift($vars);
398 54
        $inverted = $inverted ? 'true' : 'false';
399 54
        static::addUsageCount($context, $notHBCH ? 'blockhelpers' : 'hbhelpers', $ch[0]);
400 54
        $v = static::getVariableNames($context, $vars, $bp);
401
402 54
        return $context['ops']['seperator'] . static::getFuncName($context, $notHBCH ? 'bch' : 'hbch', ($inverted ? '^' : '#') . implode(' ', $v[1])) . "\$cx, '$ch[0]', {$v[0]}, \$in, $inverted, function(\$cx, \$in) {{$context['ops']['f_start']}";
403
    }
404
405
    /**
406
     * Return compiled PHP code for a handlebars block end token
407
     *
408
     * @param array<string,array|string|integer> $context current compile context
409
     * @param array<boolean|integer|string|array> $vars parsed arguments list
410
     *
411
     * @return string Return compiled code segment for the token
412
     */
413 288
    protected static function blockEnd(&$context, $vars) {
414 288
        $pop = $context['stack'][count($context['stack']) - 1];
415 288
        switch ($context['currentToken'][Token::POS_INNERTAG]) {
416
            case 'if':
417
            case 'unless':
418 64
                if ($pop === ':') {
419 19
                    array_pop($context['stack']);
420 19
                    return "{$context['ops']['cnd_end']}";
421
                }
422 45
                if (!$context['flags']['nohbh']) {
423 43
                    return "{$context['ops']['cnd_else']}''{$context['ops']['cnd_end']}";
424
                }
425 2
                break;
426 224
            case 'with':
427 18
                if (!$context['flags']['nohbh']) {
428 17
                    return "{$context['ops']['f_end']}}){$context['ops']['seperator']}";
429
                }
430
        }
431
432 227
        if ($pop === ':') {
433
            array_pop($context['stack']);
434
            return "{$context['ops']['f_end']}}){$context['ops']['seperator']}";
435
        }
436
437
        switch($pop) {
438 227
            case '#':
439 203
                return "{$context['ops']['f_end']}}){$context['ops']['seperator']}";
440
            case '^':
441 32
                return "{$context['ops']['cnd_else']}''{$context['ops']['cnd_end']}";
442
        }
443
    }
444
445
    /**
446
     * Return compiled PHP code for a handlebars block begin token
447
     *
448
     * @param array<string,array|string|integer> $context current compile context
449
     * @param array<boolean|integer|string|array> $vars parsed arguments list
450
     *
451
     * @return string Return compiled code segment for the token
452
     */
453 212
    protected static function blockBegin(&$context, $vars) {
454 212
        $v = isset($vars[1]) ? static::getVariableNameOrSubExpression($context, $vars[1]) : array(null, array());
455 212
        if (!$context['flags']['nohbh']) {
456 174
            switch (isset($vars[0][0]) ? $vars[0][0] : null) {
457 3
                case 'if':
458 55
                    $includeZero = (isset($vars['includeZero'][1]) && $vars['includeZero'][1]) ? 'true' : 'false';
459 55
                    return "{$context['ops']['cnd_start']}(" . static::getFuncName($context, 'ifvar', $v[1]) . "\$cx, {$v[0]}, {$includeZero})){$context['ops']['cnd_then']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return "{$context['ops']...t['ops']['cnd_then']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::blockBegin of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
460 3
                case 'unless':
461 2
                    return "{$context['ops']['cnd_start']}(!" . static::getFuncName($context, 'ifvar', $v[1]) . "\$cx, {$v[0]}, false)){$context['ops']['cnd_then']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return "{$context['ops']...t['ops']['cnd_then']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::blockBegin of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
462 3
                case 'each':
463 45
                    return static::section($context, $vars, true);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|in...er|string|array|null"}>, but the function expects a array<integer,boolean|integer|string|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return static::section($context, $vars, true); (string) is incompatible with the return type of the parent method LightnCandy\Validator::blockBegin of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
464 70
                case 'with':
465 17
                    if ($r = static::with($context, $vars)) {
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|in...er|string|array|null"}>, but the function expects a array<integer,boolean|integer|string|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
466 17
                        return $r;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $r; (string) is incompatible with the return type of the parent method LightnCandy\Validator::blockBegin of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
467
                    }
468
            }
469
        }
470
471 108
        return static::section($context, $vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|in...er|string|array|null"}>, but the function expects a array<integer,boolean|integer|string|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return static::section($context, $vars); (string) is incompatible with the return type of the parent method LightnCandy\Validator::blockBegin of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
472
    }
473
474
    /**
475
     * compile {{#foo}} token
476
     *
477
     * @param array<string,array|string|integer> $context current compile context
478
     * @param array<boolean|integer|string|array> $vars parsed arguments list
479
     * @param boolean $isEach the section is #each
480
     *
481
     * @return string|null Return compiled code segment for the token
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
482
     */
483 153
    protected static function section(&$context, $vars, $isEach = false) {
484 153
        $bs = 'null';
485 153
        $be = '';
486 153
        if ($isEach) {
487 45
            $bp = Parser::getBlockParams($vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|integer|string|array>, but the function expects a array<integer,boolean|integer|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
488 45
            $bs = $bp ? ('array(' . Expression::listString($bp) . ')') : 'null';
489 45
            $be = $bp ? " as |$bp[0] $bp[1]|" : '';
490 45
            array_shift($vars);
491 45
            if (!isset($vars[0])) {
492
                $vars[0] = array(null);
493
            }
494
        }
495 153
        $v = static::getVariableNameOrSubExpression($context, $vars[0]);
496 153
        $each = $isEach ? 'true' : 'false';
497 153
        return $context['ops']['seperator'] . static::getFuncName($context, 'sec', ($isEach ? 'each ' : '') . $v[1] . $be) . "\$cx, {$v[0]}, $bs, \$in, $each, function(\$cx, \$in) {{$context['ops']['f_start']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $context['ops']['...xt['ops']['f_start']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::section of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
498
    }
499
500
    /**
501
     * compile {{with}} token
502
     *
503
     * @param array<string,array|string|integer> $context current compile context
504
     * @param array<boolean|integer|string|array> $vars parsed arguments list
505
     *
506
     * @return string|null Return compiled code segment for the token
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
507
     */
508 17
    protected static function with(&$context, $vars) {
509 17
        $v = isset($vars[1]) ? static::getVariableNameOrSubExpression($context, $vars[1]) : array(null, array());
510 17
        $bp = Parser::getBlockParams($vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<integer,boolean|in...er|string|array|null"}>, but the function expects a array<integer,boolean|integer|array>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
511 17
        $bs = $bp ? ('array(' . Expression::listString($bp) . ')') : 'null';
512 17
        $be = $bp ? " as |$bp[0]|" : '';
513 17
        return $context['ops']['seperator'] . static::getFuncName($context, 'wi', 'with ' . $v[1] . $be) . "\$cx, {$v[0]}, $bs, \$in, function(\$cx, \$in) {{$context['ops']['f_start']}";
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $context['ops']['...xt['ops']['f_start']}"; (string) is incompatible with the return type of the parent method LightnCandy\Validator::with of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
514
    }
515
516
    /**
517
     * Return compiled PHP code for a handlebars custom helper token
518
     *
519
     * @param array<string,array|string|integer> $context current compile context
520
     * @param array<boolean|integer|string|array> $vars parsed arguments list
521
     * @param boolean $raw is this {{{ token or not
522
     *
523
     * @return string|null Return compiled code segment for the token when the token is custom helper
524
     */
525 397
    protected static function customHelper(&$context, $vars, $raw) {
526 397
        $notHH = !isset($context['hbhelpers'][$vars[0][0]]);
527 397
        if (!isset($context['helpers'][$vars[0][0]]) && $notHH) {
528 300
            return;
529
        }
530
531 107
        $fn = $raw ? 'raw' : $context['ops']['enc'];
532 107
        $ch = array_shift($vars);
533 107
        $v = static::getVariableNames($context, $vars);
534 107
        static::addUsageCount($context, $notHH ? 'helpers' : 'hbhelpers', $ch[0]);
535 107
        return $context['ops']['seperator'] . static::getFuncName($context, $notHH ? 'ch' : 'hbch', "$ch[0] " . implode(' ', $v[1])) . "\$cx, '$ch[0]', {$v[0]}, '$fn'" . ($notHH ? '' : ', $in') . "){$context['ops']['seperator']}";
536
    }
537
538
    /**
539
     * Return compiled PHP code for a handlebars else token
540
     *
541
     * @param array<string,array|string|integer> $context current compile context
542
     *
543
     * @return string Return compiled code segment for the token when the token is else
544
     */
545 46
    protected static function doElse(&$context) {
546 46
        switch ($context['stack'][count($context['stack']) - 2]) {
547
            case '[if]':
548 27
            case '[unless]':
549 19
                $context['stack'][] = ':';
550 19
                return "{$context['ops']['cnd_else']}";
551
            default:
552 27
                return "{$context['ops']['f_end']}}, function(\$cx, \$in) {{$context['ops']['f_start']}";
553
        }
554
    }
555
556
    /**
557
     * Return compiled PHP code for a handlebars lookup token
558
     *
559
     * @param array<string,array|string|integer> $context current compile context
560
     * @param array<boolean|integer|string|array> $vars parsed arguments list
561
     * @param boolean $raw is this {{{ token or not
562
     *
563
     * @return string Return compiled code segment for the token
564
     */
565 2
    protected static function compileLookup(&$context, &$vars, $raw) {
566 2
        $v2 = static::getVariableName($context, $vars[2]);
567 2
        $v = static::getVariableName($context, $vars[1], $v2);
568 2
        if ($context['flags']['hbesc'] || $context['flags']['jsobj'] || $context['flags']['jstrue'] || $context['flags']['debug']) {
569 2
            return $context['ops']['seperator'] . static::getFuncName($context, $raw ? 'raw' : $context['ops']['enc'], $v[1]) . "\$cx, {$v[0]}){$context['ops']['seperator']}";
570
        } else {
571
            return $raw ? "{$context['ops']['seperator']}$v[0]{$context['ops']['seperator']}" : "{$context['ops']['seperator']}htmlentities((string){$v[0]}, ENT_QUOTES, 'UTF-8'){$context['ops']['seperator']}";
572
        }
573
    }
574
575
    /**
576
     * Return compiled PHP code for a handlebars variable token
577
     *
578
     * @param array<string,array|string|integer> $context current compile context
579
     * @param array<boolean|integer|string|array> $vars parsed arguments list
580
     * @param boolean $raw is this {{{ token or not
581
     *
582
     * @return string Return compiled code segment for the token
583
     */
584 322
    protected static function compileVariable(&$context, &$vars, $raw) {
585 322
        $v = static::getVariableName($context, $vars[0]);
586 322
        if ($context['flags']['hbesc'] || $context['flags']['jsobj'] || $context['flags']['jstrue'] || $context['flags']['debug']) {
587 287
            return $context['ops']['seperator'] . static::getFuncName($context, $raw ? 'raw' : $context['ops']['enc'], $v[1]) . "\$cx, {$v[0]}){$context['ops']['seperator']}";
588
        } else {
589 35
            return $raw ? "{$context['ops']['seperator']}$v[0]{$context['ops']['seperator']}" : "{$context['ops']['seperator']}htmlentities((string){$v[0]}, ENT_QUOTES, 'UTF-8'){$context['ops']['seperator']}";
590
        }
591
    }
592
593
    /**
594
     * Add usage count to context
595
     *
596
     * @param array<string,array|string|integer> $context current context
597
     * @param string $category ctegory name, can be one of: 'var', 'helpers', 'blockhelpers'
598
     * @param string $name used name
599
     * @param integer $count increment
600
     *
601
     * @expect 1 when input array('usedCount' => array('test' => array())), 'test', 'testname'
602
     * @expect 3 when input array('usedCount' => array('test' => array('testname' => 2))), 'test', 'testname'
603
     * @expect 5 when input array('usedCount' => array('test' => array('testname' => 2))), 'test', 'testname', 3
604
     */
605 511
    protected static function addUsageCount(&$context, $category, $name, $count = 1) {
606 511
        if (!isset($context['usedCount'][$category][$name])) {
607 511
            $context['usedCount'][$category][$name] = 0;
608
        }
609 511
        return ($context['usedCount'][$category][$name] += $count);
610
    }
611
}
612
613