See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
1 <?php 2 3 namespace Sabberworm\CSS\Rule; 4 5 use Sabberworm\CSS\Comment\Commentable; 6 use Sabberworm\CSS\Parsing\ParserState; 7 use Sabberworm\CSS\Renderable; 8 use Sabberworm\CSS\Value\RuleValueList; 9 use Sabberworm\CSS\Value\Value; 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 */ 15 class 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 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 60 return $oRule; 61 } 62 63 private static function listDelimiterForRule($sRule) { 64 if (preg_match('/^font($|-)/', $sRule)) { 65 return array(',', '/', ' '); 66 } 67 return array(',', ' ', '/'); 68 } 69 70 /** 71 * @return int 72 */ 73 public function getLineNo() { 74 return $this->iLineNo; 75 } 76 77 public function setRule($sRule) { 78 $this->sRule = $sRule; 79 } 80 81 public function getRule() { 82 return $this->sRule; 83 } 84 85 public function getValue() { 86 return $this->mValue; 87 } 88 89 public function setValue($mValue) { 90 $this->mValue = $mValue; 91 } 92 93 /** 94 * @deprecated Old-Style 2-dimensional array given. Retained for (some) backwards-compatibility. Use setValue() instead and wrapp the value inside a RuleValueList if necessary. 95 */ 96 public function setValues($aSpaceSeparatedValues) { 97 $oSpaceSeparatedList = null; 98 if (count($aSpaceSeparatedValues) > 1) { 99 $oSpaceSeparatedList = new RuleValueList(' ', $this->iLineNo); 100 } 101 foreach ($aSpaceSeparatedValues as $aCommaSeparatedValues) { 102 $oCommaSeparatedList = null; 103 if (count($aCommaSeparatedValues) > 1) { 104 $oCommaSeparatedList = new RuleValueList(',', $this->iLineNo); 105 } 106 foreach ($aCommaSeparatedValues as $mValue) { 107 if (!$oSpaceSeparatedList && !$oCommaSeparatedList) { 108 $this->mValue = $mValue; 109 return $mValue; 110 } 111 if ($oCommaSeparatedList) { 112 $oCommaSeparatedList->addListComponent($mValue); 113 } else { 114 $oSpaceSeparatedList->addListComponent($mValue); 115 } 116 } 117 if (!$oSpaceSeparatedList) { 118 $this->mValue = $oCommaSeparatedList; 119 return $oCommaSeparatedList; 120 } else { 121 $oSpaceSeparatedList->addListComponent($oCommaSeparatedList); 122 } 123 } 124 $this->mValue = $oSpaceSeparatedList; 125 return $oSpaceSeparatedList; 126 } 127 128 /** 129 * @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). 130 */ 131 public function getValues() { 132 if (!$this->mValue instanceof RuleValueList) { 133 return array(array($this->mValue)); 134 } 135 if ($this->mValue->getListSeparator() === ',') { 136 return array($this->mValue->getListComponents()); 137 } 138 $aResult = array(); 139 foreach ($this->mValue->getListComponents() as $mValue) { 140 if (!$mValue instanceof RuleValueList || $mValue->getListSeparator() !== ',') { 141 $aResult[] = array($mValue); 142 continue; 143 } 144 if ($this->mValue->getListSeparator() === ' ' || count($aResult) === 0) { 145 $aResult[] = array(); 146 } 147 foreach ($mValue->getListComponents() as $mValue) { 148 $aResult[count($aResult) - 1][] = $mValue; 149 } 150 } 151 return $aResult; 152 } 153 154 /** 155 * 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. 156 */ 157 public function addValue($mValue, $sType = ' ') { 158 if (!is_array($mValue)) { 159 $mValue = array($mValue); 160 } 161 if (!$this->mValue instanceof RuleValueList || $this->mValue->getListSeparator() !== $sType) { 162 $mCurrentValue = $this->mValue; 163 $this->mValue = new RuleValueList($sType, $this->iLineNo); 164 if ($mCurrentValue) { 165 $this->mValue->addListComponent($mCurrentValue); 166 } 167 } 168 foreach ($mValue as $mValueItem) { 169 $this->mValue->addListComponent($mValueItem); 170 } 171 } 172 173 public function addIeHack($iModifier) { 174 $this->aIeHack[] = $iModifier; 175 } 176 177 public function setIeHack(array $aModifiers) { 178 $this->aIeHack = $aModifiers; 179 } 180 181 public function getIeHack() { 182 return $this->aIeHack; 183 } 184 185 public function setIsImportant($bIsImportant) { 186 $this->bIsImportant = $bIsImportant; 187 } 188 189 public function getIsImportant() { 190 return $this->bIsImportant; 191 } 192 193 public function __toString() { 194 return $this->render(new \Sabberworm\CSS\OutputFormat()); 195 } 196 197 public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) { 198 $sResult = "{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}"; 199 if ($this->mValue instanceof Value) { //Can also be a ValueList 200 $sResult .= $this->mValue->render($oOutputFormat); 201 } else { 202 $sResult .= $this->mValue; 203 } 204 if (!empty($this->aIeHack)) { 205 $sResult .= ' \\' . implode('\\', $this->aIeHack); 206 } 207 if ($this->bIsImportant) { 208 $sResult .= ' !important'; 209 } 210 $sResult .= ';'; 211 return $sResult; 212 } 213 214 /** 215 * @param array $aComments Array of comments. 216 */ 217 public function addComments(array $aComments) { 218 $this->aComments = array_merge($this->aComments, $aComments); 219 } 220 221 /** 222 * @return array 223 */ 224 public function getComments() { 225 return $this->aComments; 226 } 227 228 /** 229 * @param array $aComments Array containing Comment objects. 230 */ 231 public function setComments(array $aComments) { 232 $this->aComments = $aComments; 233 } 234 235 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body