Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.67% |
42 / 43 |
|
90.91% |
10 / 11 |
CRAP | |
0.00% |
0 / 1 |
Less_Environment | |
97.67% |
42 / 43 |
|
90.91% |
10 / 11 |
19 | |
0.00% |
0 / 1 |
Init | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
addParsedFile | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
clone | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
isFileParsed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
copyEvalEnv | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
isMathOn | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isPathRelative | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
callImportCallback | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
normalizePath | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
7 | |||
unshiftFrame | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
shiftFrame | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * @private |
4 | */ |
5 | class Less_Environment { |
6 | |
7 | /** |
8 | * Information about the current file - for error reporting and importing and making urls relative etc. |
9 | * |
10 | * - rootpath: rootpath to append to URLs |
11 | * |
12 | * @var array|null |
13 | */ |
14 | public $currentFileInfo; |
15 | |
16 | /** @var bool Whether we are currently importing multiple copies */ |
17 | public $importMultiple = false; |
18 | |
19 | /** |
20 | * @var array |
21 | */ |
22 | public $frames = []; |
23 | |
24 | /** @var Less_Tree_Media[] */ |
25 | public $mediaBlocks = []; |
26 | /** @var Less_Tree_Media[] */ |
27 | public $mediaPath = []; |
28 | |
29 | /** @var string[] */ |
30 | public $imports = []; |
31 | |
32 | /** |
33 | * This is the equivalent of `importVisitor.onceFileDetectionMap` |
34 | * as used by the dynamic `importNode.skip` function. |
35 | * |
36 | * @see less-2.5.3.js#ImportVisitor.prototype.onImported |
37 | * @var array<string,true> |
38 | */ |
39 | public $importVisitorOnceMap = []; |
40 | |
41 | public static $parensStack = 0; |
42 | |
43 | public static $tabLevel = 0; |
44 | |
45 | public static $lastRule = false; |
46 | |
47 | public static $_noSpaceCombinators; |
48 | |
49 | public static $mixin_stack = 0; |
50 | |
51 | public $strictMath = false; |
52 | |
53 | public $importCallback = null; |
54 | |
55 | /** |
56 | * @var array |
57 | */ |
58 | public $functions = []; |
59 | |
60 | public function Init() { |
61 | self::$parensStack = 0; |
62 | self::$tabLevel = 0; |
63 | self::$lastRule = false; |
64 | self::$mixin_stack = 0; |
65 | |
66 | self::$_noSpaceCombinators = [ |
67 | '' => true, |
68 | ' ' => true, |
69 | '|' => true |
70 | ]; |
71 | } |
72 | |
73 | /** |
74 | * @param string $file |
75 | * @return void |
76 | */ |
77 | public function addParsedFile( $file ) { |
78 | $this->imports[] = $file; |
79 | } |
80 | |
81 | public function clone() { |
82 | $new_env = clone $this; |
83 | // NOTE: Match JavaScript by-ref behaviour for arrays |
84 | $new_env->imports =& $this->imports; |
85 | $new_env->importVisitorOnceMap =& $this->importVisitorOnceMap; |
86 | return $new_env; |
87 | } |
88 | |
89 | /** |
90 | * @param string $file |
91 | * @return bool |
92 | */ |
93 | public function isFileParsed( $file ) { |
94 | return in_array( $file, $this->imports ); |
95 | } |
96 | |
97 | public function copyEvalEnv( $frames = [] ) { |
98 | $new_env = new self(); |
99 | $new_env->frames = $frames; |
100 | return $new_env; |
101 | } |
102 | |
103 | /** |
104 | * @return bool |
105 | * @see Eval.prototype.isMathOn in less.js 3.0.0 https://github.com/less/less.js/blob/v3.0.0/dist/less.js#L1007 |
106 | */ |
107 | public function isMathOn() { |
108 | return $this->strictMath ? (bool)self::$parensStack : true; |
109 | } |
110 | |
111 | /** |
112 | * @param string $path |
113 | * @return bool |
114 | * @see less-2.5.3.js#Eval.isPathRelative |
115 | */ |
116 | public static function isPathRelative( $path ) { |
117 | return !preg_match( '/^(?:[a-z-]+:|\/|#)/', $path ); |
118 | } |
119 | |
120 | /** |
121 | * Apply legacy 'import_callback' option. |
122 | * |
123 | * See Less_Parser::$default_options to learn more about the 'import_callback' option. |
124 | * This option is deprecated in favour of Less_Parser::SetImportDirs. |
125 | * |
126 | * @param Less_Tree_Import $importNode |
127 | * @return array{0:string,1:string|null}|null Array containing path and (optional) uri or null |
128 | */ |
129 | public function callImportCallback( Less_Tree_Import $importNode ) { |
130 | if ( is_callable( $this->importCallback ) ) { |
131 | return ( $this->importCallback )( $importNode ); |
132 | } |
133 | } |
134 | |
135 | /** |
136 | * Canonicalize a path by resolving references to '/./', '/../' |
137 | * Does not remove leading "../" |
138 | * @param string $path or url |
139 | * @return string Canonicalized path |
140 | */ |
141 | public static function normalizePath( $path ) { |
142 | $segments = explode( '/', $path ); |
143 | $segments = array_reverse( $segments ); |
144 | |
145 | $path = []; |
146 | $path_len = 0; |
147 | |
148 | while ( $segments ) { |
149 | $segment = array_pop( $segments ); |
150 | switch ( $segment ) { |
151 | |
152 | case '.': |
153 | break; |
154 | |
155 | case '..': |
156 | // @phan-suppress-next-line PhanTypeInvalidDimOffset False positive |
157 | if ( !$path_len || ( $path[$path_len - 1] === '..' ) ) { |
158 | $path[] = $segment; |
159 | $path_len++; |
160 | } else { |
161 | array_pop( $path ); |
162 | $path_len--; |
163 | } |
164 | break; |
165 | |
166 | default: |
167 | $path[] = $segment; |
168 | $path_len++; |
169 | break; |
170 | } |
171 | } |
172 | |
173 | return implode( '/', $path ); |
174 | } |
175 | |
176 | public function unshiftFrame( $frame ) { |
177 | array_unshift( $this->frames, $frame ); |
178 | } |
179 | |
180 | public function shiftFrame() { |
181 | return array_shift( $this->frames ); |
182 | } |
183 | |
184 | } |