PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.18
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.18
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 / RuleSet / DeclarationBlock.php

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

262 lines 9.4 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\RuleSet;
5
6 use WCPOS\Vendor\Sabberworm\CSS\Comment\Comment;
7 use WCPOS\Vendor\Sabberworm\CSS\Comment\CommentContainer;
8 use WCPOS\Vendor\Sabberworm\CSS\CSSElement;
9 use WCPOS\Vendor\Sabberworm\CSS\CSSList\CSSList;
10 use WCPOS\Vendor\Sabberworm\CSS\CSSList\CSSListItem;
11 use WCPOS\Vendor\Sabberworm\CSS\CSSList\KeyFrame;
12 use WCPOS\Vendor\Sabberworm\CSS\OutputFormat;
13 use WCPOS\Vendor\Sabberworm\CSS\Parsing\OutputException;
14 use WCPOS\Vendor\Sabberworm\CSS\Parsing\ParserState;
15 use WCPOS\Vendor\Sabberworm\CSS\Parsing\UnexpectedEOFException;
16 use WCPOS\Vendor\Sabberworm\CSS\Parsing\UnexpectedTokenException;
17 use WCPOS\Vendor\Sabberworm\CSS\Position\Position;
18 use WCPOS\Vendor\Sabberworm\CSS\Position\Positionable;
19 use WCPOS\Vendor\Sabberworm\CSS\Property\Declaration;
20 use WCPOS\Vendor\Sabberworm\CSS\Property\KeyframeSelector;
21 use WCPOS\Vendor\Sabberworm\CSS\Property\Selector;
22 use WCPOS\Vendor\Sabberworm\CSS\Settings;
23 /**
24 * This class represents a `RuleSet` constrained by a `Selector`.
25 *
26 * It contains an array of selector objects (comma-separated in the CSS) as well as the rules to be applied to the
27 * matching elements.
28 *
29 * Declaration blocks usually appear directly inside a `Document` or another `CSSList` (mostly a `MediaQuery`).
30 *
31 * Note that `CSSListItem` extends both `Commentable` and `Renderable`, so those interfaces must also be implemented.
32 */
33 class DeclarationBlock implements CSSElement, CSSListItem, Positionable, DeclarationList
34 {
35 use CommentContainer;
36 use LegacyDeclarationListMethods;
37 use Position;
38 /**
39 * @var list<Selector>
40 */
41 private $selectors = [];
42 /**
43 * @var RuleSet
44 */
45 private $ruleSet;
46 /**
47 * @param int<1, max>|null $lineNumber
48 */
49 public function __construct(?int $lineNumber = null)
50 {
51 $this->ruleSet = new RuleSet($lineNumber);
52 $this->setPosition($lineNumber);
53 }
54 /**
55 * @throws UnexpectedTokenException
56 * @throws UnexpectedEOFException
57 *
58 * @internal since V8.8.0
59 */
60 public static function parse(ParserState $parserState, ?CSSList $list = null) : ?DeclarationBlock
61 {
62 $comments = [];
63 $result = new DeclarationBlock($parserState->currentLine());
64 try {
65 $selectors = self::parseSelectors($parserState, $list, $comments);
66 $result->setSelectors($selectors, $list);
67 if ($parserState->comes('{')) {
68 $parserState->consume(1);
69 }
70 } catch (UnexpectedTokenException $e) {
71 if ($parserState->getSettings()->usesLenientParsing()) {
72 if (!$parserState->consumeIfComes('}')) {
73 $parserState->consumeUntil(['}', ParserState::EOF], \false, \true);
74 }
75 return null;
76 } else {
77 throw $e;
78 }
79 }
80 $result->setComments($comments);
81 RuleSet::parseRuleSet($parserState, $result->getRuleSet());
82 return $result;
83 }
84 /**
85 * @param array<Selector|string>|string $selectors
86 *
87 * @throws UnexpectedTokenException
88 */
89 public function setSelectors($selectors, ?CSSList $list = null) : void
90 {
91 if (\is_array($selectors)) {
92 $selectorsToSet = $selectors;
93 } else {
94 // A string of comma-separated selectors requires parsing.
95 try {
96 $parserState = new ParserState($selectors, Settings::create());
97 $selectorsToSet = self::parseSelectors($parserState, $list);
98 if (!$parserState->isEnd()) {
99 throw new UnexpectedTokenException('EOF', 'more');
100 }
101 } catch (UnexpectedTokenException $exception) {
102 // The exception message from parsing may refer to the faux `{` block start token,
103 // which would be confusing.
104 // Rethrow with a more useful message, that also includes the selector(s) string that was passed.
105 throw new UnexpectedTokenException('Selector(s) string is not valid.', $selectors, 'custom');
106 }
107 }
108 // Convert all items to a `Selector` if not already
109 foreach ($selectorsToSet as $key => $selector) {
110 if (!$selector instanceof Selector) {
111 if ($list === null || !$list instanceof KeyFrame) {
112 if (!Selector::isValid($selector)) {
113 throw new UnexpectedTokenException("Selector did not match '" . Selector::SELECTOR_VALIDATION_RX . "'.", $selector, 'custom');
114 }
115 $selectorsToSet[$key] = new Selector($selector);
116 } else {
117 if (!KeyframeSelector::isValid($selector)) {
118 throw new UnexpectedTokenException("Selector did not match '" . KeyframeSelector::SELECTOR_VALIDATION_RX . "'.", $selector, 'custom');
119 }
120 $selectorsToSet[$key] = new KeyframeSelector($selector);
121 }
122 }
123 }
124 // Discard the keys and reindex the array
125 $this->selectors = \array_values($selectorsToSet);
126 }
127 /**
128 * Remove one of the selectors of the block.
129 *
130 * @param Selector|string $selectorToRemove
131 */
132 public function removeSelector($selectorToRemove) : bool
133 {
134 if ($selectorToRemove instanceof Selector) {
135 $selectorToRemove = $selectorToRemove->getSelector();
136 }
137 foreach ($this->selectors as $key => $selector) {
138 if ($selector->getSelector() === $selectorToRemove) {
139 unset($this->selectors[$key]);
140 return \true;
141 }
142 }
143 return \false;
144 }
145 /**
146 * @return list<Selector>
147 */
148 public function getSelectors() : array
149 {
150 return $this->selectors;
151 }
152 public function getRuleSet() : RuleSet
153 {
154 return $this->ruleSet;
155 }
156 /**
157 * @see RuleSet::addDeclaration()
158 */
159 public function addDeclaration(Declaration $declarationToAdd, ?Declaration $sibling = null) : void
160 {
161 $this->ruleSet->addDeclaration($declarationToAdd, $sibling);
162 }
163 /**
164 * @return array<int<0, max>, Declaration>
165 *
166 * @see RuleSet::getDeclarations()
167 */
168 public function getDeclarations(?string $searchPattern = null) : array
169 {
170 return $this->ruleSet->getDeclarations($searchPattern);
171 }
172 /**
173 * @param array<Declaration> $declarations
174 *
175 * @see RuleSet::setDeclarations()
176 */
177 public function setDeclarations(array $declarations) : void
178 {
179 $this->ruleSet->setDeclarations($declarations);
180 }
181 /**
182 * @return array<string, Declaration>
183 *
184 * @see RuleSet::getDeclarationsAssociative()
185 */
186 public function getDeclarationsAssociative(?string $searchPattern = null) : array
187 {
188 return $this->ruleSet->getDeclarationsAssociative($searchPattern);
189 }
190 /**
191 * @see RuleSet::removeDeclaration()
192 */
193 public function removeDeclaration(Declaration $declarationToRemove) : void
194 {
195 $this->ruleSet->removeDeclaration($declarationToRemove);
196 }
197 /**
198 * @see RuleSet::removeMatchingDeclarations()
199 */
200 public function removeMatchingDeclarations(string $searchPattern) : void
201 {
202 $this->ruleSet->removeMatchingDeclarations($searchPattern);
203 }
204 /**
205 * @see RuleSet::removeAllDeclarations()
206 */
207 public function removeAllDeclarations() : void
208 {
209 $this->ruleSet->removeAllDeclarations();
210 }
211 /**
212 * @return non-empty-string
213 *
214 * @throws OutputException
215 */
216 public function render(OutputFormat $outputFormat) : string
217 {
218 $formatter = $outputFormat->getFormatter();
219 $result = $formatter->comments($this);
220 if (\count($this->selectors) === 0) {
221 // If all the selectors have been removed, this declaration block becomes invalid
222 throw new OutputException('Attempt to print declaration block with missing selector', $this->getLineNumber());
223 }
224 $result .= $outputFormat->getContentBeforeDeclarationBlock();
225 $result .= $formatter->implode($formatter->spaceBeforeSelectorSeparator() . ',' . $formatter->spaceAfterSelectorSeparator(), $this->selectors);
226 $result .= $outputFormat->getContentAfterDeclarationBlockSelectors();
227 $result .= $formatter->spaceBeforeOpeningBrace() . '{';
228 $result .= $this->ruleSet->render($outputFormat);
229 $result .= '}';
230 $result .= $outputFormat->getContentAfterDeclarationBlock();
231 return $result;
232 }
233 /**
234 * @return array<string, bool|int|float|string|array<mixed>|null>
235 *
236 * @internal
237 */
238 public function getArrayRepresentation() : array
239 {
240 throw new \BadMethodCallException('`getArrayRepresentation` is not yet implemented for `' . self::class . '`');
241 }
242 /**
243 * @param list<Comment> $comments
244 *
245 * @return list<Selector>
246 *
247 * @throws UnexpectedTokenException
248 */
249 private static function parseSelectors(ParserState $parserState, ?CSSList $list, array &$comments = []) : array
250 {
251 $selectorClass = $list instanceof KeyFrame ? KeyFrameSelector::class : Selector::class;
252 $selectors = [];
253 while (\true) {
254 $selectors[] = $selectorClass::parse($parserState, $comments);
255 if (!$parserState->consumeIfComes(',')) {
256 break;
257 }
258 }
259 return $selectors;
260 }
261 }
262