PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.4
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.4
2.4.3 2.4.4 2.4.2 2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 All 60 releases
easy-invoice / vendor / sabberworm / php-css-parser / src / Value / Value.php

Value.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.4, at vendor/sabberworm/php-css-parser/src/Value/Value.php

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