MDL-65759 library: Update php-css-parser to 8.3.0
[moodle.git] / lib / php-css-parser / Rule / Rule.php
CommitLineData
fbe18cc0
FM
1<?php
2
3namespace Sabberworm\CSS\Rule;
4
376eb156
MM
5use Sabberworm\CSS\Comment\Commentable;
6use Sabberworm\CSS\Parsing\ParserState;
fbe18cc0
FM
7use Sabberworm\CSS\Renderable;
8use Sabberworm\CSS\Value\RuleValueList;
9use Sabberworm\CSS\Value\Value;
fbe18cc0
FM
10
11/**
12 * RuleSets contains Rule objects which always have a key and a value.
13 * In CSS, Rules are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
14 */
15class Rule implements Renderable, Commentable {
16
17 private $sRule;
18 private $mValue;
19 private $bIsImportant;
20 private $aIeHack;
21 protected $iLineNo;
22 protected $aComments;
23
24 public function __construct($sRule, $iLineNo = 0) {
25 $this->sRule = $sRule;
26 $this->mValue = null;
27 $this->bIsImportant = false;
28 $this->aIeHack = array();
29 $this->iLineNo = $iLineNo;
30 $this->aComments = array();
31 }
32
376eb156
MM
33 public static function parse(ParserState $oParserState) {
34 $aComments = $oParserState->consumeWhiteSpace();
35 $oRule = new Rule($oParserState->parseIdentifier(), $oParserState->currentLine());
36 $oRule->setComments($aComments);
37 $oRule->addComments($oParserState->consumeWhiteSpace());
38 $oParserState->consume(':');
39 $oValue = Value::parseValue($oParserState, self::listDelimiterForRule($oRule->getRule()));
40 $oRule->setValue($oValue);
41 if ($oParserState->getSettings()->bLenientParsing) {
42 while ($oParserState->comes('\\')) {
43 $oParserState->consume('\\');
44 $oRule->addIeHack($oParserState->consume());
45 $oParserState->consumeWhiteSpace();
46 }
47 }
48 $oParserState->consumeWhiteSpace();
49 if ($oParserState->comes('!')) {
50 $oParserState->consume('!');
51 $oParserState->consumeWhiteSpace();
52 $oParserState->consume('important');
53 $oRule->setIsImportant(true);
54 }
55 $oParserState->consumeWhiteSpace();
56 while ($oParserState->comes(';')) {
57 $oParserState->consume(';');
58 }
59 $oParserState->consumeWhiteSpace();
60
61 return $oRule;
62 }
63
64 private static function listDelimiterForRule($sRule) {
65 if (preg_match('/^font($|-)/', $sRule)) {
66 return array(',', '/', ' ');
67 }
68 return array(',', ' ', '/');
69 }
70
fbe18cc0
FM
71 /**
72 * @return int
73 */
74 public function getLineNo() {
75 return $this->iLineNo;
76 }
77
78 public function setRule($sRule) {
79 $this->sRule = $sRule;
80 }
81
82 public function getRule() {
83 return $this->sRule;
84 }
85
86 public function getValue() {
87 return $this->mValue;
88 }
89
90 public function setValue($mValue) {
91 $this->mValue = $mValue;
92 }
93
94 /**
95 * @deprecated Old-Style 2-dimensional array given. Retained for (some) backwards-compatibility. Use setValue() instead and wrapp the value inside a RuleValueList if necessary.
96 */
97 public function setValues($aSpaceSeparatedValues) {
98 $oSpaceSeparatedList = null;
99 if (count($aSpaceSeparatedValues) > 1) {
100 $oSpaceSeparatedList = new RuleValueList(' ', $this->iLineNo);
101 }
102 foreach ($aSpaceSeparatedValues as $aCommaSeparatedValues) {
103 $oCommaSeparatedList = null;
104 if (count($aCommaSeparatedValues) > 1) {
105 $oCommaSeparatedList = new RuleValueList(',', $this->iLineNo);
106 }
107 foreach ($aCommaSeparatedValues as $mValue) {
108 if (!$oSpaceSeparatedList && !$oCommaSeparatedList) {
109 $this->mValue = $mValue;
110 return $mValue;
111 }
112 if ($oCommaSeparatedList) {
113 $oCommaSeparatedList->addListComponent($mValue);
114 } else {
115 $oSpaceSeparatedList->addListComponent($mValue);
116 }
117 }
118 if (!$oSpaceSeparatedList) {
119 $this->mValue = $oCommaSeparatedList;
120 return $oCommaSeparatedList;
121 } else {
122 $oSpaceSeparatedList->addListComponent($oCommaSeparatedList);
123 }
124 }
125 $this->mValue = $oSpaceSeparatedList;
126 return $oSpaceSeparatedList;
127 }
128
129 /**
130 * @deprecated Old-Style 2-dimensional array returned. Retained for (some) backwards-compatibility. Use getValue() instead and check for the existance of a (nested set of) ValueList object(s).
131 */
132 public function getValues() {
133 if (!$this->mValue instanceof RuleValueList) {
134 return array(array($this->mValue));
135 }
136 if ($this->mValue->getListSeparator() === ',') {
137 return array($this->mValue->getListComponents());
138 }
139 $aResult = array();
140 foreach ($this->mValue->getListComponents() as $mValue) {
141 if (!$mValue instanceof RuleValueList || $mValue->getListSeparator() !== ',') {
142 $aResult[] = array($mValue);
143 continue;
144 }
145 if ($this->mValue->getListSeparator() === ' ' || count($aResult) === 0) {
146 $aResult[] = array();
147 }
148 foreach ($mValue->getListComponents() as $mValue) {
149 $aResult[count($aResult) - 1][] = $mValue;
150 }
151 }
152 return $aResult;
153 }
154
155 /**
156 * Adds a value to the existing value. Value will be appended if a RuleValueList exists of the given type. Otherwise, the existing value will be wrapped by one.
157 */
158 public function addValue($mValue, $sType = ' ') {
159 if (!is_array($mValue)) {
160 $mValue = array($mValue);
161 }
162 if (!$this->mValue instanceof RuleValueList || $this->mValue->getListSeparator() !== $sType) {
163 $mCurrentValue = $this->mValue;
164 $this->mValue = new RuleValueList($sType, $this->iLineNo);
165 if ($mCurrentValue) {
166 $this->mValue->addListComponent($mCurrentValue);
167 }
168 }
169 foreach ($mValue as $mValueItem) {
170 $this->mValue->addListComponent($mValueItem);
171 }
172 }
173
174 public function addIeHack($iModifier) {
175 $this->aIeHack[] = $iModifier;
176 }
177
178 public function setIeHack(array $aModifiers) {
179 $this->aIeHack = $aModifiers;
180 }
181
182 public function getIeHack() {
183 return $this->aIeHack;
184 }
185
186 public function setIsImportant($bIsImportant) {
187 $this->bIsImportant = $bIsImportant;
188 }
189
190 public function getIsImportant() {
191 return $this->bIsImportant;
192 }
193
194 public function __toString() {
195 return $this->render(new \Sabberworm\CSS\OutputFormat());
196 }
197
198 public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
199 $sResult = "{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}";
200 if ($this->mValue instanceof Value) { //Can also be a ValueList
201 $sResult .= $this->mValue->render($oOutputFormat);
202 } else {
203 $sResult .= $this->mValue;
204 }
205 if (!empty($this->aIeHack)) {
206 $sResult .= ' \\' . implode('\\', $this->aIeHack);
207 }
208 if ($this->bIsImportant) {
209 $sResult .= ' !important';
210 }
211 $sResult .= ';';
212 return $sResult;
213 }
214
215 /**
216 * @param array $aComments Array of comments.
217 */
218 public function addComments(array $aComments) {
219 $this->aComments = array_merge($this->aComments, $aComments);
220 }
221
222 /**
223 * @return array
224 */
225 public function getComments() {
226 return $this->aComments;
227 }
228
229 /**
230 * @param array $aComments Array containing Comment objects.
231 */
232 public function setComments(array $aComments) {
233 $this->aComments = $aComments;
234 }
235
236}