MDL-55497 mod_forum: Converted quick forum search to a renderable
[moodle.git] / lib / php-css-parser / CSSList / CSSList.php
CommitLineData
fbe18cc0
FM
1<?php
2
3namespace Sabberworm\CSS\CSSList;
4
5use Sabberworm\CSS\Renderable;
6use Sabberworm\CSS\RuleSet\DeclarationBlock;
7use Sabberworm\CSS\RuleSet\RuleSet;
8use Sabberworm\CSS\Property\Selector;
9use 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 */
15abstract 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}