Commit | Line | Data |
---|---|---|
fbe18cc0 FM |
1 | <?php |
2 | ||
3 | namespace Sabberworm\CSS\CSSList; | |
4 | ||
5 | use Sabberworm\CSS\Renderable; | |
6 | use Sabberworm\CSS\RuleSet\DeclarationBlock; | |
7 | use Sabberworm\CSS\RuleSet\RuleSet; | |
8 | use Sabberworm\CSS\Property\Selector; | |
9 | use Sabberworm\CSS\Comment\Commentable; | |
10 | ||
11 | /** | |
12 | * A CSSList is the most generic container available. Its contents include RuleSet as well as other CSSList objects. | |
13 | * Also, it may contain Import and Charset objects stemming from @-rules. | |
14 | */ | |
15 | abstract class CSSList implements Renderable, Commentable { | |
16 | ||
17 | protected $aComments; | |
18 | protected $aContents; | |
19 | protected $iLineNo; | |
20 | ||
21 | public function __construct($iLineNo = 0) { | |
22 | $this->aComments = array(); | |
23 | $this->aContents = array(); | |
24 | $this->iLineNo = $iLineNo; | |
25 | } | |
26 | ||
27 | /** | |
28 | * @return int | |
29 | */ | |
30 | public function getLineNo() { | |
31 | return $this->iLineNo; | |
32 | } | |
33 | ||
34 | public function append($oItem) { | |
35 | $this->aContents[] = $oItem; | |
36 | } | |
37 | ||
38 | /** | |
39 | * Removes an item from the CSS list. | |
40 | * @param RuleSet|Import|Charset|CSSList $oItemToRemove May be a RuleSet (most likely a DeclarationBlock), a Import, a Charset or another CSSList (most likely a MediaQuery) | |
41 | */ | |
42 | public function remove($oItemToRemove) { | |
43 | $iKey = array_search($oItemToRemove, $this->aContents, true); | |
44 | if ($iKey !== false) { | |
45 | unset($this->aContents[$iKey]); | |
46 | return true; | |
47 | } | |
48 | return false; | |
49 | } | |
50 | ||
51 | /** | |
52 | * Set the contents. | |
53 | * @param array $aContents Objects to set as content. | |
54 | */ | |
55 | public function setContents(array $aContents) { | |
56 | $this->aContents = array(); | |
57 | foreach ($aContents as $content) { | |
58 | $this->append($content); | |
59 | } | |
60 | } | |
61 | ||
62 | /** | |
63 | * Removes a declaration block from the CSS list if it matches all given selectors. | |
64 | * @param array|string $mSelector The selectors to match. | |
65 | * @param boolean $bRemoveAll Whether to stop at the first declaration block found or remove all blocks | |
66 | */ | |
67 | public function removeDeclarationBlockBySelector($mSelector, $bRemoveAll = false) { | |
68 | if ($mSelector instanceof DeclarationBlock) { | |
69 | $mSelector = $mSelector->getSelectors(); | |
70 | } | |
71 | if (!is_array($mSelector)) { | |
72 | $mSelector = explode(',', $mSelector); | |
73 | } | |
74 | foreach ($mSelector as $iKey => &$mSel) { | |
75 | if (!($mSel instanceof Selector)) { | |
76 | $mSel = new Selector($mSel); | |
77 | } | |
78 | } | |
79 | foreach ($this->aContents as $iKey => $mItem) { | |
80 | if (!($mItem instanceof DeclarationBlock)) { | |
81 | continue; | |
82 | } | |
83 | if ($mItem->getSelectors() == $mSelector) { | |
84 | unset($this->aContents[$iKey]); | |
85 | if (!$bRemoveAll) { | |
86 | return; | |
87 | } | |
88 | } | |
89 | } | |
90 | } | |
91 | ||
92 | public function __toString() { | |
93 | return $this->render(new \Sabberworm\CSS\OutputFormat()); | |
94 | } | |
95 | ||
96 | public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) { | |
97 | $sResult = ''; | |
98 | $bIsFirst = true; | |
99 | $oNextLevel = $oOutputFormat; | |
100 | if(!$this->isRootList()) { | |
101 | $oNextLevel = $oOutputFormat->nextLevel(); | |
102 | } | |
103 | foreach ($this->aContents as $oContent) { | |
104 | $sRendered = $oOutputFormat->safely(function() use ($oNextLevel, $oContent) { | |
105 | return $oContent->render($oNextLevel); | |
106 | }); | |
107 | if($sRendered === null) { | |
108 | continue; | |
109 | } | |
110 | if($bIsFirst) { | |
111 | $bIsFirst = false; | |
112 | $sResult .= $oNextLevel->spaceBeforeBlocks(); | |
113 | } else { | |
114 | $sResult .= $oNextLevel->spaceBetweenBlocks(); | |
115 | } | |
116 | $sResult .= $sRendered; | |
117 | } | |
118 | ||
119 | if(!$bIsFirst) { | |
120 | // Had some output | |
121 | $sResult .= $oOutputFormat->spaceAfterBlocks(); | |
122 | } | |
123 | ||
124 | return $sResult; | |
125 | } | |
126 | ||
127 | /** | |
128 | * Return true if the list can not be further outdented. Only important when rendering. | |
129 | */ | |
130 | public abstract function isRootList(); | |
131 | ||
132 | public function getContents() { | |
133 | return $this->aContents; | |
134 | } | |
135 | ||
136 | /** | |
137 | * @param array $aComments Array of comments. | |
138 | */ | |
139 | public function addComments(array $aComments) { | |
140 | $this->aComments = array_merge($this->aComments, $aComments); | |
141 | } | |
142 | ||
143 | /** | |
144 | * @return array | |
145 | */ | |
146 | public function getComments() { | |
147 | return $this->aComments; | |
148 | } | |
149 | ||
150 | /** | |
151 | * @param array $aComments Array containing Comment objects. | |
152 | */ | |
153 | public function setComments(array $aComments) { | |
154 | $this->aComments = $aComments; | |
155 | } | |
156 | ||
157 | } |