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