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

MyIntervals / PHP-CSS-Parser / 20448617153

23 Dec 2025 01:25AM UTC coverage: 68.284% (-0.9%) from 69.191%
20448617153

Pull #1441

github

web-flow
Merge 86a006c27 into 0ae1fde22
Pull Request #1441: [TASK] Add `getArrayRepresentation` method for testing

3 of 30 new or added lines in 11 files covered. (10.0%)

41 existing lines in 12 files now uncovered.

1337 of 1958 relevant lines covered (68.28%)

32.56 hits per line

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

47.14
/src/Rule/Rule.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Sabberworm\CSS\Rule;
6

7
use Sabberworm\CSS\Comment\Comment;
8
use Sabberworm\CSS\Comment\Commentable;
9
use Sabberworm\CSS\Comment\CommentContainer;
10
use Sabberworm\CSS\CSSElement;
11
use Sabberworm\CSS\OutputFormat;
12
use Sabberworm\CSS\Parsing\ParserState;
13
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
14
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
15
use Sabberworm\CSS\Position\Position;
16
use Sabberworm\CSS\Position\Positionable;
17
use Sabberworm\CSS\Value\RuleValueList;
18
use Sabberworm\CSS\Value\Value;
19

20
use function Safe\preg_match;
21

22
/**
23
 * `Rule`s just have a string key (the rule) and a 'Value'.
24
 *
25
 * In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
26
 */
27
class Rule implements Commentable, CSSElement, Positionable
28
{
29
    use CommentContainer;
30
    use Position;
31

32
    /**
33
     * @var non-empty-string
34
     */
35
    private $rule;
36

37
    /**
38
     * @var RuleValueList|string|null
39
     */
40
    private $value;
41

42
    /**
43
     * @var bool
44
     */
45
    private $isImportant = false;
46

47
    /**
48
     * @param non-empty-string $rule
49
     * @param int<1, max>|null $lineNumber
50
     * @param int<0, max>|null $columnNumber
51
     */
52
    public function __construct(string $rule, ?int $lineNumber = null, ?int $columnNumber = null)
2✔
53
    {
54
        $this->rule = $rule;
2✔
55
        $this->setPosition($lineNumber, $columnNumber);
2✔
56
    }
2✔
57

58
    /**
59
     * @param list<Comment> $commentsBeforeRule
60
     *
61
     * @throws UnexpectedEOFException
62
     * @throws UnexpectedTokenException
63
     *
64
     * @internal since V8.8.0
65
     */
66
    public static function parse(ParserState $parserState, array $commentsBeforeRule = []): Rule
1✔
67
    {
68
        $comments = \array_merge($commentsBeforeRule, $parserState->consumeWhiteSpace());
1✔
69
        $rule = new Rule(
1✔
70
            $parserState->parseIdentifier(!$parserState->comes('--')),
1✔
71
            $parserState->currentLine(),
1✔
72
            $parserState->currentColumn()
1✔
73
        );
74
        $rule->setComments($comments);
1✔
75
        $rule->addComments($parserState->consumeWhiteSpace());
1✔
76
        $parserState->consume(':');
1✔
77
        $value = Value::parseValue($parserState, self::listDelimiterForRule($rule->getRule()));
1✔
78
        $rule->setValue($value);
1✔
79
        $parserState->consumeWhiteSpace();
1✔
80
        if ($parserState->comes('!')) {
1✔
81
            $parserState->consume('!');
×
82
            $parserState->consumeWhiteSpace();
×
83
            $parserState->consume('important');
×
84
            $rule->setIsImportant(true);
×
85
        }
86
        $parserState->consumeWhiteSpace();
1✔
87
        while ($parserState->comes(';')) {
1✔
88
            $parserState->consume(';');
1✔
89
        }
90

91
        return $rule;
1✔
92
    }
93

94
    /**
95
     * Returns a list of delimiters (or separators).
96
     * The first item is the innermost separator (or, put another way, the highest-precedence operator).
97
     * The sequence continues to the outermost separator (or lowest-precedence operator).
98
     *
99
     * @param non-empty-string $rule
100
     *
101
     * @return list<non-empty-string>
102
     */
103
    private static function listDelimiterForRule(string $rule): array
1✔
104
    {
105
        if (preg_match('/^font($|-)/', $rule) === 1) {
1✔
106
            return [',', '/', ' '];
×
107
        }
108

109
        switch ($rule) {
1✔
110
            case 'src':
1✔
111
                return [' ', ','];
1✔
112
            default:
113
                return [',', ' ', '/'];
×
114
        }
115
    }
116

117
    /**
118
     * @param non-empty-string $rule
119
     */
120
    public function setRule(string $rule): void
×
121
    {
122
        $this->rule = $rule;
×
123
    }
×
124

125
    /**
126
     * @return non-empty-string
127
     */
128
    public function getRule(): string
1✔
129
    {
130
        return $this->rule;
1✔
131
    }
132

133
    /**
134
     * @return RuleValueList|string|null
135
     */
136
    public function getValue()
1✔
137
    {
138
        return $this->value;
1✔
139
    }
140

141
    /**
142
     * @param RuleValueList|string|null $value
143
     */
144
    public function setValue($value): void
1✔
145
    {
146
        $this->value = $value;
1✔
147
    }
1✔
148

149
    /**
150
     * Adds a value to the existing value. Value will be appended if a `RuleValueList` exists of the given type.
151
     * Otherwise, the existing value will be wrapped by one.
152
     *
153
     * @param RuleValueList|array<int, RuleValueList> $value
154
     */
155
    public function addValue($value, string $type = ' '): void
×
156
    {
157
        if (!\is_array($value)) {
×
158
            $value = [$value];
×
159
        }
160
        if (!($this->value instanceof RuleValueList) || $this->value->getListSeparator() !== $type) {
×
161
            $currentValue = $this->value;
×
162
            $this->value = new RuleValueList($type, $this->getLineNumber());
×
163
            if ($currentValue !== null && $currentValue !== '') {
×
164
                $this->value->addListComponent($currentValue);
×
165
            }
166
        }
167
        foreach ($value as $valueItem) {
×
168
            $this->value->addListComponent($valueItem);
×
169
        }
170
    }
×
171

172
    public function setIsImportant(bool $isImportant): void
×
173
    {
174
        $this->isImportant = $isImportant;
×
175
    }
×
176

177
    public function getIsImportant(): bool
×
178
    {
179
        return $this->isImportant;
×
180
    }
181

182
    /**
183
     * @return non-empty-string
184
     */
185
    public function render(OutputFormat $outputFormat): string
×
186
    {
187
        $formatter = $outputFormat->getFormatter();
×
188
        $result = "{$formatter->comments($this)}{$this->rule}:{$formatter->spaceAfterRuleName()}";
×
189
        if ($this->value instanceof Value) { // Can also be a ValueList
×
190
            $result .= $this->value->render($outputFormat);
×
191
        } else {
192
            $result .= $this->value;
×
193
        }
194
        if ($this->isImportant) {
×
195
            $result .= ' !important';
×
196
        }
197
        $result .= ';';
×
198
        return $result;
×
199
    }
200

201
    /**
202
     * @internal
203
     *
204
     * @return array<string, bool|int|float|string|list<array<string, mixed>>>
205
     */
NEW
UNCOV
206
    public function getArrayRepresentation(): array
×
207
    {
NEW
UNCOV
208
        throw new \BadMethodCallException('`getArrayRepresentation` is not yet implemented for `' . self::class . '`');
×
209
    }
210
}
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