Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
80.00% covered (warning)
80.00%
12 / 15
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
AttributeSelector
80.00% covered (warning)
80.00%
12 / 15
66.67% covered (warning)
66.67%
2 / 3
10.80
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 specificity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toString
76.92% covered (warning)
76.92%
10 / 13
0.00% covered (danger)
0.00%
0 / 1
8.79
1<?php
2
3declare(strict_types=1);
4
5namespace Phpdftk\Css\Selector;
6
7/**
8 * Attribute selector per Selectors 4 §6.5: `[name op value flag]`.
9 *
10 * Specificity (0, 1, 0). The optional flag is tri-state:
11 *
12 *   - `i` → `caseInsensitive = true` — force ASCII-case-insensitive.
13 *   - `s` → `caseInsensitive = false` — force case-sensitive.
14 *   - no flag → `caseInsensitive = null` — defer to host language
15 *     defaults (HTML lists certain attribute names as case-
16 *     insensitive per §6.6).
17 */
18final readonly class AttributeSelector extends SimpleSelector
19{
20    public function __construct(
21        public string $name,
22        public AttributeMatchType $matchType = AttributeMatchType::Exists,
23        public ?string $value = null,
24        public ?string $namespacePrefix = null,
25        public ?bool $caseInsensitive = null,
26    ) {}
27
28    public function specificity(): Specificity
29    {
30        return new Specificity(0, 1, 0);
31    }
32
33    public function toString(): string
34    {
35        $name = $this->namespacePrefix !== null
36            ? $this->namespacePrefix . '|' . $this->name
37            : $this->name;
38        if ($this->matchType === AttributeMatchType::Exists) {
39            return '[' . $name . ']';
40        }
41        $value = $this->value ?? '';
42        $needsQuoting = preg_match('/[^A-Za-z0-9_-]/', $value) === 1 || $value === '';
43        $quoted = $needsQuoting ? '"' . str_replace('"', '\\"', $value) . '"' : $value;
44        $flag = match ($this->caseInsensitive) {
45            true => ' i',
46            false => ' s',
47            null => '',
48        };
49        return '[' . $name . $this->matchType->value . $quoted . $flag . ']';
50    }
51}