Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
21 / 21
93.75% covered (success)
93.75%
15 / 16
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
Result
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
21 / 21
93.75% covered (success)
93.75%
15 / 16
100.00% covered (success)
100.00%
10 / 10
16.06
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
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 valid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 issues
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 values
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 messages
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
6 / 6
75.00% covered (warning)
75.00%
3 / 4
100.00% covered (success)
100.00%
1 / 1
3.14
 first
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 has
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 jsonSerialize
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 path
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 normalizePath
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
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 Celemas\Sire;
6
7use JsonSerializable;
8use Override;
9
10/** @api */
11final readonly class Result implements JsonSerializable
12{
13    /**
14     * @param list<Issue> $issues
15     * @param array<array-key, mixed> $values
16     */
17    public function __construct(
18        private array $issues,
19        private array $values,
20    ) {}
21
22    public function valid(): bool
23    {
24        return $this->issues === [];
25    }
26
27    /** @return list<Issue> */
28    public function issues(): array
29    {
30        return $this->issues;
31    }
32
33    /** @return array<array-key, mixed> */
34    public function values(): array
35    {
36        return $this->values;
37    }
38
39    /**
40     * @param string|int|list<string|int> $path
41     * @return list<string>
42     */
43    public function messages(string|int|array $path = []): array
44    {
45        $path = self::path($path);
46        $messages = [];
47
48        foreach ($this->issues as $issue) {
49            if ($issue->path !== $path) {
50                continue;
51            }
52
53            $messages[] = $issue->message;
54        }
55
56        return $messages;
57    }
58
59    /** @param string|int|list<string|int> $path */
60    public function first(string|int|array $path = []): ?string
61    {
62        return $this->messages($path)[0] ?? null;
63    }
64
65    /** @param string|int|list<string|int> $path */
66    public function has(string|int|array $path = []): bool
67    {
68        return $this->messages($path) !== [];
69    }
70
71    /** @return array{valid: bool, issues: list<Issue>} */
72    #[Override]
73    public function jsonSerialize(): array
74    {
75        return [
76            'valid' => $this->valid(),
77            'issues' => $this->issues,
78        ];
79    }
80
81    /**
82     * @param string|int|list<string|int> $path
83     * @return list<string|int>
84     */
85    private static function path(string|int|array $path): array
86    {
87        if (is_int($path)) {
88            return [$path];
89        }
90
91        if (is_string($path)) {
92            if ($path === '') {
93                return [];
94            }
95
96            return self::normalizePath(explode('.', $path));
97        }
98
99        return $path;
100    }
101
102    /**
103     * @param list<string> $path
104     * @return list<string|int>
105     */
106    private static function normalizePath(array $path): array
107    {
108        return array_map(
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
110            $path,
111        );
112    }
113}