PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.19
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.19
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / vendor_prefixed / sabberworm / php-css-parser / src / Value / Value.php

Value.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.19, at vendor_prefixed/sabberworm/php-css-parser/src/Value/Value.php

200 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace WCPOS\Vendor\Sabberworm\CSS\Value;
5
6 use WCPOS\Vendor\Sabberworm\CSS\CSSElement;
7 use WCPOS\Vendor\Sabberworm\CSS\Parsing\ParserState;
8 use WCPOS\Vendor\Sabberworm\CSS\Parsing\SourceException;
9 use WCPOS\Vendor\Sabberworm\CSS\Parsing\UnexpectedEOFException;
10 use WCPOS\Vendor\Sabberworm\CSS\Parsing\UnexpectedTokenException;
11 use WCPOS\Vendor\Sabberworm\CSS\Position\Position;
12 use WCPOS\Vendor\Sabberworm\CSS\Position\Positionable;
13 use WCPOS\Vendor\Sabberworm\CSS\ShortClassNameProvider;
14 use function WCPOS\Vendor\Safe\preg_match;
15 /**
16 * Abstract base class for specific classes of CSS values: `Size`, `Color`, `CSSString` and `URL`, and another
17 * abstract subclass `ValueList`.
18 */
19 abstract class Value implements CSSElement, Positionable
20 {
21 use Position;
22 use ShortClassNameProvider;
23 /**
24 * @param int<1, max>|null $lineNumber
25 */
26 public function __construct(?int $lineNumber = null)
27 {
28 $this->setPosition($lineNumber);
29 }
30 /**
31 * @param array<non-empty-string> $listDelimiters
32 *
33 * @return Value|string
34 *
35 * @throws UnexpectedTokenException
36 * @throws UnexpectedEOFException
37 *
38 * @internal since V8.8.0
39 */
40 public static function parseValue(ParserState $parserState, array $listDelimiters = [])
41 {
42 /** @var list<Value|string> $stack */
43 $stack = [];
44 $parserState->consumeWhiteSpace();
45 //Build a list of delimiters and parsed values
46 while (!($parserState->comes('}') || $parserState->comes(';') || $parserState->comes('!') || $parserState->comes(')') || $parserState->isEnd())) {
47 if (\count($stack) > 0) {
48 $foundDelimiter = \false;
49 foreach ($listDelimiters as $delimiter) {
50 if ($parserState->comes($delimiter)) {
51 \array_push($stack, $parserState->consume($delimiter));
52 $parserState->consumeWhiteSpace();
53 $foundDelimiter = \true;
54 break;
55 }
56 }
57 if (!$foundDelimiter) {
58 //Whitespace was the list delimiter
59 \array_push($stack, ' ');
60 }
61 }
62 \array_push($stack, self::parsePrimitiveValue($parserState));
63 $parserState->consumeWhiteSpace();
64 }
65 // Convert the list to list objects
66 foreach ($listDelimiters as $delimiter) {
67 $stackSize = \count($stack);
68 if ($stackSize === 1) {
69 return $stack[0];
70 }
71 $newStack = [];
72 for ($offset = 0; $offset < $stackSize; ++$offset) {
73 if ($offset === $stackSize - 1 || $delimiter !== $stack[$offset + 1]) {
74 $newStack[] = $stack[$offset];
75 continue;
76 }
77 $length = 2;
78 //Number of elements to be joined
79 for ($i = $offset + 3; $i < $stackSize; $i += 2, ++$length) {
80 if ($delimiter !== $stack[$i]) {
81 break;
82 }
83 }
84 $list = new RuleValueList($delimiter, $parserState->currentLine());
85 for ($i = $offset; $i - $offset < $length * 2; $i += 2) {
86 $list->addListComponent($stack[$i]);
87 }
88 $newStack[] = $list;
89 $offset += $length * 2 - 2;
90 }
91 $stack = $newStack;
92 }
93 if (!isset($stack[0])) {
94 throw new UnexpectedTokenException(" {$parserState->peek()} ", $parserState->peek(1, -1) . $parserState->peek(2), 'literal', $parserState->currentLine());
95 }
96 return $stack[0];
97 }
98 /**
99 * @return CSSFunction|string
100 *
101 * @throws UnexpectedEOFException
102 * @throws UnexpectedTokenException
103 *
104 * @internal since V8.8.0
105 */
106 public static function parseIdentifierOrFunction(ParserState $parserState, bool $ignoreCase = \false)
107 {
108 $anchor = $parserState->anchor();
109 $result = $parserState->parseIdentifier($ignoreCase);
110 if ($parserState->comes('(')) {
111 $anchor->backtrack();
112 if ($parserState->streql('url', $result)) {
113 $result = URL::parse($parserState);
114 } elseif ($parserState->streql('calc', $result)) {
115 $result = CalcFunction::parse($parserState);
116 } else {
117 $result = CSSFunction::parse($parserState, $ignoreCase);
118 }
119 }
120 return $result;
121 }
122 /**
123 * @return CSSFunction|CSSString|LineName|Size|URL|string
124 *
125 * @throws UnexpectedEOFException
126 * @throws UnexpectedTokenException
127 * @throws SourceException
128 *
129 * @internal since V8.8.0
130 */
131 public static function parsePrimitiveValue(ParserState $parserState)
132 {
133 $parserState->consumeWhiteSpace();
134 if (\is_numeric($parserState->peek()) || $parserState->comes('-.') && \is_numeric($parserState->peek(1, 2)) || ($parserState->comes('-') || $parserState->comes('.')) && \is_numeric($parserState->peek(1, 1))) {
135 $value = Size::parse($parserState);
136 } elseif ($parserState->comes('#') || $parserState->comes('rgb', \true) || $parserState->comes('hsl', \true)) {
137 $value = Color::parse($parserState);
138 } elseif ($parserState->comes("'") || $parserState->comes('"')) {
139 $value = CSSString::parse($parserState);
140 } elseif ($parserState->comes('progid:') && $parserState->getSettings()->usesLenientParsing()) {
141 $value = self::parseMicrosoftFilter($parserState);
142 } elseif ($parserState->comes('[')) {
143 $value = LineName::parse($parserState);
144 } elseif ($parserState->comes('U+')) {
145 $value = self::parseUnicodeRangeValue($parserState);
146 } else {
147 $nextCharacter = $parserState->peek(1);
148 try {
149 $value = self::parseIdentifierOrFunction($parserState);
150 } catch (UnexpectedTokenException $e) {
151 if (\in_array($nextCharacter, ['+', '-', '*', '/'], \true)) {
152 $value = $parserState->consume(1);
153 } else {
154 throw $e;
155 }
156 }
157 }
158 $parserState->consumeWhiteSpace();
159 return $value;
160 }
161 /**
162 * @return array<string, bool|int|float|string|array<mixed>|null>
163 *
164 * @internal
165 */
166 public function getArrayRepresentation() : array
167 {
168 return ['class' => $this->getShortClassName()];
169 }
170 /**
171 * @throws UnexpectedEOFException
172 * @throws UnexpectedTokenException
173 */
174 private static function parseMicrosoftFilter(ParserState $parserState) : CSSFunction
175 {
176 $function = $parserState->consumeUntil('(', \false, \true);
177 $arguments = Value::parseValue($parserState, [',', '=']);
178 return new CSSFunction($function, $arguments, ',', $parserState->currentLine());
179 }
180 /**
181 * @throws UnexpectedEOFException
182 * @throws UnexpectedTokenException
183 */
184 private static function parseUnicodeRangeValue(ParserState $parserState) : string
185 {
186 $codepointMaxLength = 6;
187 // Code points outside BMP can use up to six digits
188 $range = '';
189 $parserState->consume('U+');
190 do {
191 if ($parserState->comes('-')) {
192 $codepointMaxLength = 13;
193 // Max length is 2 six-digit code points + the dash(-) between them
194 }
195 $range .= $parserState->consume(1);
196 } while (\strlen($range) < $codepointMaxLength && preg_match('/[A-Fa-f0-9\\?-]/', $parserState->peek()) === 1);
197 return "U+{$range}";
198 }
199 }
200