• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MyIntervals / PHP-CSS-Parser / 14363870590

09 Apr 2025 05:59PM UTC coverage: 50.582% (-3.8%) from 54.382%
14363870590

Pull #1194

github

web-flow
Merge 6d9620462 into f0360052d
Pull Request #1194: [TASK] Use delegation for `DeclarationBlock` -> `RuleSet`

16 of 26 new or added lines in 3 files covered. (61.54%)

70 existing lines in 1 file now uncovered.

912 of 1803 relevant lines covered (50.58%)

7.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

24.0
/src/CSSList/CSSBlockList.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Sabberworm\CSS\CSSList;
6

7
use Sabberworm\CSS\CSSElement;
8
use Sabberworm\CSS\Property\Selector;
9
use Sabberworm\CSS\Rule\Rule;
10
use Sabberworm\CSS\RuleSet\DeclarationBlock;
11
use Sabberworm\CSS\RuleSet\RuleSet;
12
use Sabberworm\CSS\Value\CSSFunction;
13
use Sabberworm\CSS\Value\Value;
14
use Sabberworm\CSS\Value\ValueList;
15

16
/**
17
 * A `CSSBlockList` is a `CSSList` whose `DeclarationBlock`s are guaranteed to contain valid declaration blocks or
18
 * at-rules.
19
 *
20
 * Most `CSSList`s conform to this category but some at-rules (such as `@keyframes`) do not.
21
 */
22
abstract class CSSBlockList extends CSSList
23
{
24
    /**
25
     * Gets all `DeclarationBlock` objects recursively, no matter how deeply nested the selectors are.
26
     *
27
     * @return list<DeclarationBlock>
28
     */
29
    public function getAllDeclarationBlocks(): array
6✔
30
    {
31
        $result = [];
6✔
32

33
        foreach ($this->contents as $item) {
6✔
34
            if ($item instanceof DeclarationBlock) {
5✔
35
                $result[] = $item;
3✔
36
            } elseif ($item instanceof CSSBlockList) {
3✔
37
                $result = \array_merge($result, $item->getAllDeclarationBlocks());
1✔
38
            }
39
        }
40

41
        return $result;
6✔
42
    }
43

44
    /**
45
     * @param list<DeclarationBlock> $result
46
     */
47
    protected function allDeclarationBlocks(array &$result): void
×
48
    {
49
        foreach ($this->contents as $item) {
×
50
            if ($item instanceof DeclarationBlock) {
×
51
                $result[] = $item;
×
52
            } elseif ($item instanceof CSSBlockList) {
×
53
                $item->allDeclarationBlocks($result);
×
54
            }
55
        }
56
    }
×
57

58
    /**
59
     * Returns all `RuleSet` objects recursively found in the tree, no matter how deeply nested the rule sets are.
60
     *
61
     * @return list<RuleSet>
62
     */
63
    public function getAllRuleSets(): array
9✔
64
    {
65
        $result = [];
9✔
66

67
        foreach ($this->contents as $item) {
9✔
68
            if ($item instanceof RuleSet) {
8✔
69
                $result[] = $item;
3✔
70
            } elseif ($item instanceof CSSBlockList) {
6✔
71
                $result = \array_merge($result, $item->getAllRuleSets());
2✔
72
            } elseif ($item instanceof DeclarationBlock) {
5✔
73
                $result[] = $item->getRuleSet();
3✔
74
            }
75
        }
76

77
        return $result;
9✔
78
    }
79

80
    /**
81
     * @param CSSElement|string $element
82
     * @param list<Value> $result
83
     */
84
    protected function allValues(
×
85
        $element,
86
        array &$result,
87
        ?string $searchString = null,
88
        bool $searchInFunctionArguments = false
89
    ): void {
90
        if ($element instanceof CSSBlockList) {
×
91
            foreach ($element->getContents() as $content) {
×
92
                $this->allValues($content, $result, $searchString, $searchInFunctionArguments);
×
93
            }
NEW
94
        } elseif ($element instanceof RuleSet || $element instanceof DeclarationBlock) {
×
95
            foreach ($element->getRules($searchString) as $rule) {
×
96
                $this->allValues($rule, $result, $searchString, $searchInFunctionArguments);
×
97
            }
98
        } elseif ($element instanceof Rule) {
×
99
            $this->allValues($element->getValue(), $result, $searchString, $searchInFunctionArguments);
×
100
        } elseif ($element instanceof ValueList) {
×
101
            if ($searchInFunctionArguments || !($element instanceof CSSFunction)) {
×
102
                foreach ($element->getListComponents() as $component) {
×
103
                    $this->allValues($component, $result, $searchString, $searchInFunctionArguments);
×
104
                }
105
            }
106
        } elseif ($element instanceof Value) {
×
107
            $result[] = $element;
×
108
        }
109
    }
×
110

111
    /**
112
     * @param list<Selector> $result
113
     */
114
    protected function allSelectors(array &$result, ?string $specificitySearch = null): void
×
115
    {
116
        $declarationBlocks = [];
×
117
        $this->allDeclarationBlocks($declarationBlocks);
×
118
        foreach ($declarationBlocks as $declarationBlock) {
×
119
            foreach ($declarationBlock->getSelectors() as $selector) {
×
120
                if ($specificitySearch === null) {
×
121
                    $result[] = $selector;
×
122
                } else {
123
                    $comparator = '===';
×
124
                    $expressionParts = \explode(' ', $specificitySearch);
×
125
                    $targetSpecificity = $expressionParts[0];
×
126
                    if (\count($expressionParts) > 1) {
×
127
                        $comparator = $expressionParts[0];
×
128
                        $targetSpecificity = $expressionParts[1];
×
129
                    }
130
                    $targetSpecificity = (int) $targetSpecificity;
×
131
                    $selectorSpecificity = $selector->getSpecificity();
×
132
                    $comparatorMatched = false;
×
133
                    switch ($comparator) {
×
134
                        case '<=':
×
135
                            $comparatorMatched = $selectorSpecificity <= $targetSpecificity;
×
136
                            break;
×
137
                        case '<':
×
138
                            $comparatorMatched = $selectorSpecificity < $targetSpecificity;
×
139
                            break;
×
140
                        case '>=':
×
141
                            $comparatorMatched = $selectorSpecificity >= $targetSpecificity;
×
142
                            break;
×
143
                        case '>':
×
144
                            $comparatorMatched = $selectorSpecificity > $targetSpecificity;
×
145
                            break;
×
146
                        default:
147
                            $comparatorMatched = $selectorSpecificity === $targetSpecificity;
×
148
                            break;
×
149
                    }
150
                    if ($comparatorMatched) {
×
151
                        $result[] = $selector;
×
152
                    }
153
                }
154
            }
155
        }
156
    }
×
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc