Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.59% covered (success)
98.59%
70 / 71
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Less_Tree_Call
98.59% covered (success)
98.59%
70 / 71
80.00% covered (warning)
80.00%
4 / 5
26
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 accept
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 functionCaller
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
5.03
 compile
100.00% covered (success)
100.00%
49 / 49
100.00% covered (success)
100.00%
1 / 1
16
 genCSS
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * @private
4 * @see less.tree.Call in less.js 3.0.0 https://github.com/less/less.js/blob/v3.0.0/dist/less.js#L6336
5 */
6class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
7    public $value;
8
9    public $name;
10    public $args;
11    /** @var bool */
12    public $mathOn;
13    public $index;
14    public $currentFileInfo;
15
16    public function __construct( $name, $args, $index, $currentFileInfo = null ) {
17        $this->name = $name;
18        $this->args = $args;
19        $this->mathOn = ( $name !== 'calc' );
20        $this->index = $index;
21        $this->currentFileInfo = $currentFileInfo;
22    }
23
24    public function accept( $visitor ) {
25        $this->args = $visitor->visitArray( $this->args );
26    }
27
28    /**
29     * @see less-2.5.3.js#functionCaller.prototype.call
30     */
31    private function functionCaller( $function, array $arguments ) {
32        // This code is terrible and should be replaced as per this issue...
33        // https://github.com/less/less.js/issues/2477
34        $filtered = [];
35        foreach ( $arguments as $argument ) {
36            if ( $argument instanceof Less_Tree_Comment ) {
37                continue;
38            }
39            $filtered[] = $argument;
40        }
41        foreach ( $filtered as $index => $argument ) {
42            if ( $argument instanceof Less_Tree_Expression ) {
43                $filtered[$index] = $argument->mapToFunctionCallArgument();
44            }
45        }
46        return $function( ...$filtered );
47    }
48
49    //
50    // When evaluating a function call,
51    // we either find the function in Less_Functions,
52    // in which case we call it, passing the evaluated arguments,
53    // or we simply print it out as it literal CSS.
54    //
55    // The reason why we compile the arguments, is in the case one
56    // of them is a LESS variable that only PHP knows the value of,
57    // like: `saturate(@mycolor)`.
58    // The function should receive the value, not the variable.
59    //
60    public function compile( $env ) {
61        // Turn off math for calc(). https://phabricator.wikimedia.org/T331688
62        $currentMathContext = $env->strictMath;
63        $env->strictMath = !$this->mathOn;
64
65        $args = [];
66        foreach ( $this->args as $a ) {
67            $args[] = $a->compile( $env );
68        }
69
70        $env->strictMath = $currentMathContext;
71
72        $nameLC = strtolower( $this->name );
73        switch ( $nameLC ) {
74            case '%':
75                $nameLC = '_percent';
76                break;
77
78            case 'get-unit':
79                $nameLC = 'getunit';
80                break;
81
82            case 'data-uri':
83                $nameLC = 'datauri';
84                break;
85
86            case 'svg-gradient':
87                $nameLC = 'svggradient';
88                break;
89            case 'image-size':
90                $nameLC = 'imagesize';
91                break;
92            case 'image-width':
93                $nameLC = 'imagewidth';
94                break;
95            case 'image-height':
96                $nameLC = 'imageheight';
97                break;
98        }
99
100        $result = null;
101        if ( $nameLC === 'default' ) {
102            $result = Less_Tree_DefaultFunc::compile();
103        } else {
104            $func = null;
105            $functions = new Less_Functions( $env, $this->currentFileInfo );
106            $funcBuiltin = [ $functions, $nameLC ];
107            // Avoid method_exists() as that considers private utility functions too
108            if ( is_callable( $funcBuiltin ) ) {
109                $func = $funcBuiltin;
110            } elseif ( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) {
111                $func = $env->functions[$nameLC];
112            }
113            // If the function name isn't known to LESS, output it unchanged as CSS.
114            if ( $func ) {
115                try {
116                    $result = $this->functionCaller( $func, $args );
117                } catch ( Exception $e ) {
118                    // Preserve original trace, especially from custom functions.
119                    // https://github.com/wikimedia/less.php/issues/38
120                    throw new Less_Exception_Compiler(
121                        'error evaluating function `' . $this->name . '` ' . $e->getMessage()
122                            . ' index: ' . $this->index,
123                        $e
124                    );
125                }
126            }
127        }
128
129        if ( $result !== null ) {
130            return $result;
131        }
132
133        return new self( $this->name, $args, $this->index, $this->currentFileInfo );
134    }
135
136    /**
137     * @see Less_Tree::genCSS
138     */
139    public function genCSS( $output ) {
140        $output->add( $this->name . '(', $this->currentFileInfo, $this->index );
141        $args_len = count( $this->args );
142        for ( $i = 0; $i < $args_len; $i++ ) {
143            $this->args[$i]->genCSS( $output );
144            if ( $i + 1 < $args_len ) {
145                $output->add( ', ' );
146            }
147        }
148
149        $output->add( ')' );
150    }
151
152}