PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.0.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.0.1
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
acymailing / back / Libraries / Sabberworm / CSS / src / CSSList / CSSBlockList.php

CSSBlockList.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 11.0.1, at back/Libraries/Sabberworm/CSS/src/CSSList/CSSBlockList.php

185 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace AcyMailing\Libraries\Sabberworm\CSS\CSSList;
6
7 use AcyMailing\Libraries\Sabberworm\CSS\CSSElement;
8 use AcyMailing\Libraries\Sabberworm\CSS\Property\Selector;
9 use AcyMailing\Libraries\Sabberworm\CSS\Rule\Rule;
10 use AcyMailing\Libraries\Sabberworm\CSS\RuleSet\DeclarationBlock;
11 use AcyMailing\Libraries\Sabberworm\CSS\RuleSet\RuleContainer;
12 use AcyMailing\Libraries\Sabberworm\CSS\RuleSet\RuleSet;
13 use AcyMailing\Libraries\Sabberworm\CSS\Value\CSSFunction;
14 use AcyMailing\Libraries\Sabberworm\CSS\Value\Value;
15 use AcyMailing\Libraries\Sabberworm\CSS\Value\ValueList;
16
17 /**
18 * A `CSSBlockList` is a `CSSList` whose `DeclarationBlock`s are guaranteed to contain valid declaration blocks or
19 * at-rules.
20 *
21 * Most `CSSList`s conform to this category but some at-rules (such as `@keyframes`) do not.
22 */
23 abstract class CSSBlockList extends CSSList
24 {
25 /**
26 * Gets all `DeclarationBlock` objects recursively, no matter how deeply nested the selectors are.
27 *
28 * @return list<DeclarationBlock>
29 */
30 public function getAllDeclarationBlocks(): array
31 {
32 $result = [];
33
34 foreach ($this->contents as $item) {
35 if ($item instanceof DeclarationBlock) {
36 $result[] = $item;
37 } elseif ($item instanceof CSSBlockList) {
38 $result = \array_merge($result, $item->getAllDeclarationBlocks());
39 }
40 }
41
42 return $result;
43 }
44
45 /**
46 * Returns all `RuleSet` objects recursively found in the tree, no matter how deeply nested the rule sets are.
47 *
48 * @return list<RuleSet>
49 */
50 public function getAllRuleSets(): array
51 {
52 $result = [];
53
54 foreach ($this->contents as $item) {
55 if ($item instanceof RuleSet) {
56 $result[] = $item;
57 } elseif ($item instanceof CSSBlockList) {
58 $result = \array_merge($result, $item->getAllRuleSets());
59 } elseif ($item instanceof DeclarationBlock) {
60 $result[] = $item->getRuleSet();
61 }
62 }
63
64 return $result;
65 }
66
67 /**
68 * Returns all `Value` objects found recursively in `Rule`s in the tree.
69 *
70 * @param CSSElement|null $element
71 * This is the `CSSList` or `RuleSet` to start the search from (defaults to the whole document).
72 * @param string|null $ruleSearchPattern
73 * This allows filtering rules by property name
74 * (e.g. if "color" is passed, only `Value`s from `color` properties will be returned,
75 * or if "font-" is provided, `Value`s from all font rules, like `font-size`, and including `font` itself,
76 * will be returned).
77 * @param bool $searchInFunctionArguments whether to also return `Value` objects used as `CSSFunction` arguments.
78 *
79 * @return list<Value>
80 *
81 * @see RuleSet->getRules()
82 */
83 public function getAllValues(
84 ?CSSElement $element = null,
85 ?string $ruleSearchPattern = null,
86 bool $searchInFunctionArguments = false
87 ): array {
88 $element = $element ?? $this;
89
90 $result = [];
91 if ($element instanceof CSSBlockList) {
92 foreach ($element->getContents() as $contentItem) {
93 // Statement at-rules are skipped since they do not contain values.
94 if ($contentItem instanceof CSSElement) {
95 $result = \array_merge(
96 $result,
97 $this->getAllValues($contentItem, $ruleSearchPattern, $searchInFunctionArguments)
98 );
99 }
100 }
101 } elseif ($element instanceof RuleContainer) {
102 foreach ($element->getRules($ruleSearchPattern) as $rule) {
103 $result = \array_merge(
104 $result,
105 $this->getAllValues($rule, $ruleSearchPattern, $searchInFunctionArguments)
106 );
107 }
108 } elseif ($element instanceof Rule) {
109 $value = $element->getValue();
110 // `string` values are discarded.
111 if ($value instanceof CSSElement) {
112 $result = \array_merge(
113 $result,
114 $this->getAllValues($value, $ruleSearchPattern, $searchInFunctionArguments)
115 );
116 }
117 } elseif ($element instanceof ValueList) {
118 if ($searchInFunctionArguments || !($element instanceof CSSFunction)) {
119 foreach ($element->getListComponents() as $component) {
120 // `string` components are discarded.
121 if ($component instanceof CSSElement) {
122 $result = \array_merge(
123 $result,
124 $this->getAllValues($component, $ruleSearchPattern, $searchInFunctionArguments)
125 );
126 }
127 }
128 }
129 } elseif ($element instanceof Value) {
130 $result[] = $element;
131 }
132
133 return $result;
134 }
135
136 /**
137 * @return list<Selector>
138 */
139 protected function getAllSelectors(?string $specificitySearch = null): array
140 {
141 $result = [];
142
143 foreach ($this->getAllDeclarationBlocks() as $declarationBlock) {
144 foreach ($declarationBlock->getSelectors() as $selector) {
145 if ($specificitySearch === null) {
146 $result[] = $selector;
147 } else {
148 $comparator = '===';
149 $expressionParts = \explode(' ', $specificitySearch);
150 $targetSpecificity = $expressionParts[0];
151 if (\count($expressionParts) > 1) {
152 $comparator = $expressionParts[0];
153 $targetSpecificity = $expressionParts[1];
154 }
155 $targetSpecificity = (int) $targetSpecificity;
156 $selectorSpecificity = $selector->getSpecificity();
157 $comparatorMatched = false;
158 switch ($comparator) {
159 case '<=':
160 $comparatorMatched = $selectorSpecificity <= $targetSpecificity;
161 break;
162 case '<':
163 $comparatorMatched = $selectorSpecificity < $targetSpecificity;
164 break;
165 case '>=':
166 $comparatorMatched = $selectorSpecificity >= $targetSpecificity;
167 break;
168 case '>':
169 $comparatorMatched = $selectorSpecificity > $targetSpecificity;
170 break;
171 default:
172 $comparatorMatched = $selectorSpecificity === $targetSpecificity;
173 break;
174 }
175 if ($comparatorMatched) {
176 $result[] = $selector;
177 }
178 }
179 }
180 }
181
182 return $result;
183 }
184 }
185