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}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

Result->__construct
18        private array $issues,
19        private array $values,
20    ) {}
Result->first
60    public function first(string|int|array $path = []): ?string
61    {
62        return $this->messages($path)[0] ?? null;
63    }
Result->has
66    public function has(string|int|array $path = []): bool
67    {
68        return $this->messages($path) !== [];
69    }
Result->issues
30        return $this->issues;
31    }
Result->jsonSerialize
76            'valid' => $this->valid(),
77            'issues' => $this->issues,
78        ];
79    }
Result->messages
43    public function messages(string|int|array $path = []): array
44    {
45        $path = self::path($path);
46        $messages = [];
47
48        foreach ($this->issues as $issue) {
 
48        foreach ($this->issues as $issue) {
 
49            if ($issue->path !== $path) {
 
50                continue;
 
48        foreach ($this->issues as $issue) {
 
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    }
43    public function messages(string|int|array $path = []): array
44    {
45        $path = self::path($path);
46        $messages = [];
47
48        foreach ($this->issues as $issue) {
 
48        foreach ($this->issues as $issue) {
 
49            if ($issue->path !== $path) {
 
48        foreach ($this->issues as $issue) {
49            if ($issue->path !== $path) {
50                continue;
51            }
52
53            $messages[] = $issue->message;
 
48        foreach ($this->issues as $issue) {
 
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    }
43    public function messages(string|int|array $path = []): array
44    {
45        $path = self::path($path);
46        $messages = [];
47
48        foreach ($this->issues as $issue) {
 
48        foreach ($this->issues as $issue) {
 
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    }
43    public function messages(string|int|array $path = []): array
44    {
45        $path = self::path($path);
46        $messages = [];
47
48        foreach ($this->issues as $issue) {
 
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    }
Result->normalizePath
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    }
Result->path
85    private static function path(string|int|array $path): array
86    {
87        if (is_int($path)) {
 
88            return [$path];
85    private static function path(string|int|array $path): array
86    {
87        if (is_int($path)) {
 
91        if (is_string($path)) {
 
92            if ($path === '') {
 
93                return [];
85    private static function path(string|int|array $path): array
86    {
87        if (is_int($path)) {
 
91        if (is_string($path)) {
 
92            if ($path === '') {
 
96            return self::normalizePath(explode('.', $path));
85    private static function path(string|int|array $path): array
86    {
87        if (is_int($path)) {
 
91        if (is_string($path)) {
 
99        return $path;
100    }
Result->valid
24        return $this->issues === [];
25    }
Result->values
36        return $this->values;
37    }
{closure:/workspace/celemas/sire/src/Result.php:109-109}
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
 
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
 
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
 
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,
 
109            static fn(string $part): string|int => ctype_digit($part) ? (int) $part : $part,