Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
CascadedValues
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
7 / 7
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 set
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 has
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 get
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 all
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 customProperties
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 normalise
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Phpdftk\Css\Cascade;
6
7use Phpdftk\Css\Value\Value;
8
9/**
10 * Per-element bag of resolved property → value pairs after the cascade
11 * has been applied. Phase 1D.3 ships this as a simple map; once the full
12 * `ComputedStyle` accessor surface lands (per `contracts.md`), this becomes
13 * the underlying storage backing those getters.
14 *
15 * `get($name)` falls back to the registry's initial value when the property
16 * was never set, so callers can treat the map as if every registered
17 * property is present.
18 */
19final class CascadedValues
20{
21    /** @var array<string, Value> */
22    private array $values = [];
23
24    /** @var array<string, Value> */
25    private array $customProperties = [];
26
27    public function __construct(private readonly PropertyRegistry $registry) {}
28
29    public function set(string $name, Value $value): void
30    {
31        $key = $this->normalise($name);
32        if (str_starts_with($key, '--')) {
33            $this->customProperties[$key] = $value;
34            return;
35        }
36        $this->values[$key] = $value;
37    }
38
39    public function has(string $name): bool
40    {
41        $key = $this->normalise($name);
42        if (str_starts_with($key, '--')) {
43            return isset($this->customProperties[$key]);
44        }
45        return isset($this->values[$key]);
46    }
47
48    public function get(string $name): ?Value
49    {
50        $key = $this->normalise($name);
51        if (str_starts_with($key, '--')) {
52            return $this->customProperties[$key] ?? null;
53        }
54        if (isset($this->values[$key])) {
55            return $this->values[$key];
56        }
57        return $this->registry->get($key)?->initial;
58    }
59
60    /** @return array<string, Value> standard properties only */
61    public function all(): array
62    {
63        return $this->values;
64    }
65
66    /** @return array<string, Value> declared custom properties only */
67    public function customProperties(): array
68    {
69        return $this->customProperties;
70    }
71
72    /**
73     * Custom-property names are case-sensitive per the spec; standard
74     * properties are lower-cased.
75     */
76    private function normalise(string $name): string
77    {
78        return str_starts_with($name, '--') ? $name : strtolower($name);
79    }
80}