PluginProbe
WooCommerce / 11.0.0
WooCommerce v11.0.0
11.1.0 11.1.0-rc.2 11.1.0-rc.1 11.1.0-beta.2 11.1.0-beta.1 11.0.1 11.0.0 11.0.0-rc.3 11.0.0-rc.2 11.0.0-rc.1 11.0.0-beta.2 11.0.0-beta.1 10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 All 648 releases
woocommerce / lib / packages / Sabberworm / CSS / Rule / Rule.php
Rule.php
384 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Automattic\WooCommerce\Vendor\Sabberworm\CSS\Rule;
4
5 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Comment\Comment;
6 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Comment\Commentable;
7 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\CSSElement;
8 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\OutputFormat;
9 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Parsing\ParserState;
10 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Parsing\UnexpectedEOFException;
11 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Parsing\UnexpectedTokenException;
12 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Position\Position;
13 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Position\Positionable;
14 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Value\RuleValueList;
15 use Automattic\WooCommerce\Vendor\Sabberworm\CSS\Value\Value;
16
17 /**
18 * `Rule`s just have a string key (the rule) and a 'Value'.
19 *
20 * In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
21 */
22 class Rule implements Commentable, CSSElement, Positionable
23 {
24 use Position;
25
26 /**
27 * @var string
28 */
29 private $sRule;
30
31 /**
32 * @var RuleValueList|string|null
33 */
34 private $mValue;
35
36 /**
37 * @var bool
38 */
39 private $bIsImportant;
40
41 /**
42 * @var array<int, int>
43 */
44 private $aIeHack;
45
46 /**
47 * @var array<array-key, Comment>
48 *
49 * @internal since 8.8.0
50 */
51 protected $aComments;
52
53 /**
54 * @param string $sRule
55 * @param int $iLineNo
56 * @param int $iColNo
57 */
58 public function __construct($sRule, $iLineNo = 0, $iColNo = 0)
59 {
60 $this->sRule = $sRule;
61 $this->mValue = null;
62 $this->bIsImportant = false;
63 $this->aIeHack = [];
64 $this->setPosition($iLineNo, $iColNo);
65 $this->aComments = [];
66 }
67
68 /**
69 * @param array<int, Comment> $commentsBeforeRule
70 *
71 * @return Rule
72 *
73 * @throws UnexpectedEOFException
74 * @throws UnexpectedTokenException
75 *
76 * @internal since V8.8.0
77 */
78 public static function parse(ParserState $oParserState, $commentsBeforeRule = [])
79 {
80 $aComments = \array_merge($commentsBeforeRule, $oParserState->consumeWhiteSpace());
81 $oRule = new Rule(
82 $oParserState->parseIdentifier(!$oParserState->comes("--")),
83 $oParserState->currentLine(),
84 $oParserState->currentColumn()
85 );
86 $oRule->setComments($aComments);
87 $oRule->addComments($oParserState->consumeWhiteSpace());
88 $oParserState->consume(':');
89 $oValue = Value::parseValue($oParserState, self::listDelimiterForRule($oRule->getRule()));
90 $oRule->setValue($oValue);
91 if ($oParserState->getSettings()->bLenientParsing) {
92 while ($oParserState->comes('\\')) {
93 $oParserState->consume('\\');
94 $oRule->addIeHack($oParserState->consume());
95 $oParserState->consumeWhiteSpace();
96 }
97 }
98 $oParserState->consumeWhiteSpace();
99 if ($oParserState->comes('!')) {
100 $oParserState->consume('!');
101 $oParserState->consumeWhiteSpace();
102 $oParserState->consume('important');
103 $oRule->setIsImportant(true);
104 }
105 $oParserState->consumeWhiteSpace();
106 while ($oParserState->comes(';')) {
107 $oParserState->consume(';');
108 }
109
110 return $oRule;
111 }
112
113 /**
114 * Returns a list of delimiters (or separators).
115 * The first item is the innermost separator (or, put another way, the highest-precedence operator).
116 * The sequence continues to the outermost separator (or lowest-precedence operator).
117 *
118 * @param string $sRule
119 *
120 * @return list<non-empty-string>
121 */
122 private static function listDelimiterForRule($sRule)
123 {
124 if (preg_match('/^font($|-)/', $sRule)) {
125 return [',', '/', ' '];
126 }
127
128 switch ($sRule) {
129 case 'src':
130 return [' ', ','];
131 default:
132 return [',', ' ', '/'];
133 }
134 }
135
136 /**
137 * @param string $sRule
138 *
139 * @return void
140 */
141 public function setRule($sRule)
142 {
143 $this->sRule = $sRule;
144 }
145
146 /**
147 * @return string
148 */
149 public function getRule()
150 {
151 return $this->sRule;
152 }
153
154 /**
155 * @return RuleValueList|string|null
156 */
157 public function getValue()
158 {
159 return $this->mValue;
160 }
161
162 /**
163 * @param RuleValueList|string|null $mValue
164 *
165 * @return void
166 */
167 public function setValue($mValue)
168 {
169 $this->mValue = $mValue;
170 }
171
172 /**
173 * @param array<array-key, array<array-key, RuleValueList>> $aSpaceSeparatedValues
174 *
175 * @return RuleValueList
176 *
177 * @deprecated will be removed in version 9.0
178 * Old-Style 2-dimensional array given. Retained for (some) backwards-compatibility.
179 * Use `setValue()` instead and wrap the value inside a RuleValueList if necessary.
180 */
181 public function setValues(array $aSpaceSeparatedValues)
182 {
183 $oSpaceSeparatedList = null;
184 if (count($aSpaceSeparatedValues) > 1) {
185 $oSpaceSeparatedList = new RuleValueList(' ', $this->iLineNo);
186 }
187 foreach ($aSpaceSeparatedValues as $aCommaSeparatedValues) {
188 $oCommaSeparatedList = null;
189 if (count($aCommaSeparatedValues) > 1) {
190 $oCommaSeparatedList = new RuleValueList(',', $this->iLineNo);
191 }
192 foreach ($aCommaSeparatedValues as $mValue) {
193 if (!$oSpaceSeparatedList && !$oCommaSeparatedList) {
194 $this->mValue = $mValue;
195 return $mValue;
196 }
197 if ($oCommaSeparatedList) {
198 $oCommaSeparatedList->addListComponent($mValue);
199 } else {
200 $oSpaceSeparatedList->addListComponent($mValue);
201 }
202 }
203 if (!$oSpaceSeparatedList) {
204 $this->mValue = $oCommaSeparatedList;
205 return $oCommaSeparatedList;
206 } else {
207 $oSpaceSeparatedList->addListComponent($oCommaSeparatedList);
208 }
209 }
210 $this->mValue = $oSpaceSeparatedList;
211 return $oSpaceSeparatedList;
212 }
213
214 /**
215 * @return array<int, array<int, RuleValueList>>
216 *
217 * @deprecated will be removed in version 9.0
218 * Old-Style 2-dimensional array returned. Retained for (some) backwards-compatibility.
219 * Use `getValue()` instead and check for the existence of a (nested set of) ValueList object(s).
220 */
221 public function getValues()
222 {
223 if (!$this->mValue instanceof RuleValueList) {
224 return [[$this->mValue]];
225 }
226 if ($this->mValue->getListSeparator() === ',') {
227 return [$this->mValue->getListComponents()];
228 }
229 $aResult = [];
230 foreach ($this->mValue->getListComponents() as $mValue) {
231 if (!$mValue instanceof RuleValueList || $mValue->getListSeparator() !== ',') {
232 $aResult[] = [$mValue];
233 continue;
234 }
235 if ($this->mValue->getListSeparator() === ' ' || count($aResult) === 0) {
236 $aResult[] = [];
237 }
238 foreach ($mValue->getListComponents() as $mValue) {
239 $aResult[count($aResult) - 1][] = $mValue;
240 }
241 }
242 return $aResult;
243 }
244
245 /**
246 * Adds a value to the existing value. Value will be appended if a `RuleValueList` exists of the given type.
247 * Otherwise, the existing value will be wrapped by one.
248 *
249 * @param RuleValueList|array<int, RuleValueList> $mValue
250 * @param string $sType
251 *
252 * @return void
253 */
254 public function addValue($mValue, $sType = ' ')
255 {
256 if (!is_array($mValue)) {
257 $mValue = [$mValue];
258 }
259 if (!$this->mValue instanceof RuleValueList || $this->mValue->getListSeparator() !== $sType) {
260 $mCurrentValue = $this->mValue;
261 $this->mValue = new RuleValueList($sType, $this->getLineNumber());
262 if ($mCurrentValue) {
263 $this->mValue->addListComponent($mCurrentValue);
264 }
265 }
266 foreach ($mValue as $mValueItem) {
267 $this->mValue->addListComponent($mValueItem);
268 }
269 }
270
271 /**
272 * @param int $iModifier
273 *
274 * @return void
275 *
276 * @deprecated since V8.8.0, will be removed in V9.0
277 */
278 public function addIeHack($iModifier)
279 {
280 $this->aIeHack[] = $iModifier;
281 }
282
283 /**
284 * @param array<int, int> $aModifiers
285 *
286 * @return void
287 *
288 * @deprecated since V8.8.0, will be removed in V9.0
289 */
290 public function setIeHack(array $aModifiers)
291 {
292 $this->aIeHack = $aModifiers;
293 }
294
295 /**
296 * @return array<int, int>
297 *
298 * @deprecated since V8.8.0, will be removed in V9.0
299 */
300 public function getIeHack()
301 {
302 return $this->aIeHack;
303 }
304
305 /**
306 * @param bool $bIsImportant
307 *
308 * @return void
309 */
310 public function setIsImportant($bIsImportant)
311 {
312 $this->bIsImportant = $bIsImportant;
313 }
314
315 /**
316 * @return bool
317 */
318 public function getIsImportant()
319 {
320 return $this->bIsImportant;
321 }
322
323 /**
324 * @return string
325 *
326 * @deprecated in V8.8.0, will be removed in V9.0.0. Use `render` instead.
327 */
328 public function __toString()
329 {
330 return $this->render(new OutputFormat());
331 }
332
333 /**
334 * @param OutputFormat|null $oOutputFormat
335 *
336 * @return string
337 */
338 public function render($oOutputFormat)
339 {
340 $sResult = "{$oOutputFormat->comments($this)}{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}";
341 if ($this->mValue instanceof Value) { // Can also be a ValueList
342 $sResult .= $this->mValue->render($oOutputFormat);
343 } else {
344 $sResult .= $this->mValue;
345 }
346 if (!empty($this->aIeHack)) {
347 $sResult .= ' \\' . implode('\\', $this->aIeHack);
348 }
349 if ($this->bIsImportant) {
350 $sResult .= ' !important';
351 }
352 $sResult .= ';';
353 return $sResult;
354 }
355
356 /**
357 * @param array<array-key, Comment> $aComments
358 *
359 * @return void
360 */
361 public function addComments(array $aComments)
362 {
363 $this->aComments = array_merge($this->aComments, $aComments);
364 }
365
366 /**
367 * @return array<array-key, Comment>
368 */
369 public function getComments()
370 {
371 return $this->aComments;
372 }
373
374 /**
375 * @param array<array-key, Comment> $aComments
376 *
377 * @return void
378 */
379 public function setComments(array $aComments)
380 {
381 $this->aComments = $aComments;
382 }
383 }
384