Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.00% covered (success)
92.00%
23 / 25
77.78% covered (warning)
77.78%
7 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Entry
92.00% covered (success)
92.00%
23 / 25
77.78% covered (warning)
77.78%
7 / 9
13.09
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 json
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 uid
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 unwrap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fieldValues
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 isset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __get
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 initFields
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Value;
6
7use Cosray\Exception\NoSuchProperty;
8use Cosray\Exception\RuntimeException;
9use Cosray\Field;
10
11/**
12 * @property-read Field\Entries $field
13 */
14class Entry extends Value
15{
16    /** @var array<string, Field\Field> */
17    protected array $fields = [];
18
19    public function __construct(
20        Field\Owner $owner,
21        Field\Entries $field,
22        ValueContext $context,
23        public readonly string $type,
24    ) {
25        parent::__construct($owner, $field, $context);
26
27        $this->initFields();
28    }
29
30    public function __toString(): string
31    {
32        throw new RuntimeException(
33            "An entry row of '{$this->fieldName}' has no string representation. Read its fields in the template.",
34        );
35    }
36
37    public function json(): array
38    {
39        return $this->fieldValues(static fn(Value $value): mixed => $value->json());
40    }
41
42    public function uid(): ?string
43    {
44        $uid = $this->data['uid'] ?? null;
45
46        return is_string($uid) ? $uid : null;
47    }
48
49    public function unwrap(): array
50    {
51        return $this->fieldValues(static fn(Value $value): mixed => $value->unwrap());
52    }
53
54    /**
55     * Entry fields resolve through the value layer — `structure()` is the
56     * editor's storage shape and belongs to the serializer.
57     *
58     * @param callable(Value): mixed $resolve
59     * @return array{uid: ?string, type: string, fields: array<string, mixed>}
60     */
61    private function fieldValues(callable $resolve): array
62    {
63        $result = [];
64
65        foreach ($this->fields as $name => $field) {
66            $result[$name] = $resolve($field->value());
67        }
68
69        return [
70            'uid' => $this->uid(),
71            'type' => $this->type,
72            'fields' => $result,
73        ];
74    }
75
76    public function isset(): bool
77    {
78        return count($this->fields) > 0;
79    }
80
81    public function __get(string $name): mixed
82    {
83        if (isset($this->fields[$name])) {
84            return $this->fields[$name]->value();
85        }
86
87        throw new NoSuchProperty("Entry doesn't have field '{$name}'");
88    }
89
90    protected function initFields(): void
91    {
92        $data = $this->data['fields'] ?? [];
93
94        if (!is_array($data)) {
95            $data = [];
96        }
97
98        $this->fields = $this->field->entryFieldsFor($this->type, $data);
99    }
100}