PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Libraries/Sabberworm/CSS/src/Rule/Rule.php +198 -0 10.10.1 → 11.1.0 View file →
@@ -1,0 +1,198 @@
1 +<?php
2 +
3 +declare(strict_types=1);
4 +
5 +namespace AcyMailing\Libraries\Sabberworm\CSS\Rule;
6 +
7 +use AcyMailing\Libraries\Sabberworm\CSS\Comment\Comment;
8 +use AcyMailing\Libraries\Sabberworm\CSS\Comment\Commentable;
9 +use AcyMailing\Libraries\Sabberworm\CSS\Comment\CommentContainer;
10 +use AcyMailing\Libraries\Sabberworm\CSS\CSSElement;
11 +use AcyMailing\Libraries\Sabberworm\CSS\OutputFormat;
12 +use AcyMailing\Libraries\Sabberworm\CSS\Parsing\ParserState;
13 +use AcyMailing\Libraries\Sabberworm\CSS\Parsing\UnexpectedEOFException;
14 +use AcyMailing\Libraries\Sabberworm\CSS\Parsing\UnexpectedTokenException;
15 +use AcyMailing\Libraries\Sabberworm\CSS\Position\Position;
16 +use AcyMailing\Libraries\Sabberworm\CSS\Position\Positionable;
17 +use AcyMailing\Libraries\Sabberworm\CSS\Value\RuleValueList;
18 +use AcyMailing\Libraries\Sabberworm\CSS\Value\Value;
19 +
20 +/**
21 + * `Rule`s just have a string key (the rule) and a 'Value'.
22 + *
23 + * In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
24 + */
25 +class Rule implements Commentable, CSSElement, Positionable
26 +{
27 + use CommentContainer;
28 + use Position;
29 +
30 + /**
31 + * @var non-empty-string
32 + */
33 + private $rule;
34 +
35 + /**
36 + * @var RuleValueList|string|null
37 + */
38 + private $value;
39 +
40 + /**
41 + * @var bool
42 + */
43 + private $isImportant = false;
44 +
45 + /**
46 + * @param non-empty-string $rule
47 + * @param int<1, max>|null $lineNumber
48 + * @param int<0, max>|null $columnNumber
49 + */
50 + public function __construct(string $rule, ?int $lineNumber = null, ?int $columnNumber = null)
51 + {
52 + $this->rule = $rule;
53 + $this->setPosition($lineNumber, $columnNumber);
54 + }
55 +
56 + /**
57 + * @param list<Comment> $commentsBeforeRule
58 + *
59 + * @throws UnexpectedEOFException
60 + * @throws UnexpectedTokenException
61 + *
62 + * @internal since V8.8.0
63 + */
64 + public static function parse(ParserState $parserState, array $commentsBeforeRule = []): Rule
65 + {
66 + $comments = \array_merge($commentsBeforeRule, $parserState->consumeWhiteSpace());
67 + $rule = new Rule(
68 + $parserState->parseIdentifier(!$parserState->comes('--')),
69 + $parserState->currentLine(),
70 + $parserState->currentColumn()
71 + );
72 + $rule->setComments($comments);
73 + $rule->addComments($parserState->consumeWhiteSpace());
74 + $parserState->consume(':');
75 + $value = Value::parseValue($parserState, self::listDelimiterForRule($rule->getRule()));
76 + $rule->setValue($value);
77 + $parserState->consumeWhiteSpace();
78 + if ($parserState->comes('!')) {
79 + $parserState->consume('!');
80 + $parserState->consumeWhiteSpace();
81 + $parserState->consume('important');
82 + $rule->setIsImportant(true);
83 + }
84 + $parserState->consumeWhiteSpace();
85 + while ($parserState->comes(';')) {
86 + $parserState->consume(';');
87 + }
88 +
89 + return $rule;
90 + }
91 +
92 + /**
93 + * Returns a list of delimiters (or separators).
94 + * The first item is the innermost separator (or, put another way, the highest-precedence operator).
95 + * The sequence continues to the outermost separator (or lowest-precedence operator).
96 + *
97 + * @param non-empty-string $rule
98 + *
99 + * @return list<non-empty-string>
100 + */
101 + private static function listDelimiterForRule(string $rule): array
102 + {
103 + if (\preg_match('/^font($|-)/', $rule)) {
104 + return [',', '/', ' '];
105 + }
106 +
107 + switch ($rule) {
108 + case 'src':
109 + return [' ', ','];
110 + default:
111 + return [',', ' ', '/'];
112 + }
113 + }
114 +
115 + /**
116 + * @param non-empty-string $rule
117 + */
118 + public function setRule(string $rule): void
119 + {
120 + $this->rule = $rule;
121 + }
122 +
123 + /**
124 + * @return non-empty-string
125 + */
126 + public function getRule(): string
127 + {
128 + return $this->rule;
129 + }
130 +
131 + /**
132 + * @return RuleValueList|string|null
133 + */
134 + public function getValue()
135 + {
136 + return $this->value;
137 + }
138 +
139 + /**
140 + * @param RuleValueList|string|null $value
141 + */
142 + public function setValue($value): void
143 + {
144 + $this->value = $value;
145 + }
146 +
147 + /**
148 + * Adds a value to the existing value. Value will be appended if a `RuleValueList` exists of the given type.
149 + * Otherwise, the existing value will be wrapped by one.
150 + *
151 + * @param RuleValueList|array<int, RuleValueList> $value
152 + */
153 + public function addValue($value, string $type = ' '): void
154 + {
155 + if (!\is_array($value)) {
156 + $value = [$value];
157 + }
158 + if (!($this->value instanceof RuleValueList) || $this->value->getListSeparator() !== $type) {
159 + $currentValue = $this->value;
160 + $this->value = new RuleValueList($type, $this->getLineNumber());
161 + if ($currentValue !== null && $currentValue !== '') {
162 + $this->value->addListComponent($currentValue);
163 + }
164 + }
165 + foreach ($value as $valueItem) {
166 + $this->value->addListComponent($valueItem);
167 + }
168 + }
169 +
170 + public function setIsImportant(bool $isImportant): void
171 + {
172 + $this->isImportant = $isImportant;
173 + }
174 +
175 + public function getIsImportant(): bool
176 + {
177 + return $this->isImportant;
178 + }
179 +
180 + /**
181 + * @return non-empty-string
182 + */
183 + public function render(OutputFormat $outputFormat): string
184 + {
185 + $formatter = $outputFormat->getFormatter();
186 + $result = "{$formatter->comments($this)}{$this->rule}:{$formatter->spaceAfterRuleName()}";
187 + if ($this->value instanceof Value) { // Can also be a ValueList
188 + $result .= $this->value->render($outputFormat);
189 + } else {
190 + $result .= $this->value;
191 + }
192 + if ($this->isImportant) {
193 + $result .= ' !important';
194 + }
195 + $result .= ';';
196 + return $result;
197 + }
198 +}