Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.76% covered (warning)
87.76%
43 / 49
77.78% covered (warning)
77.78%
14 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
Files
87.76% covered (warning)
87.76%
43 / 49
77.78% covered (warning)
77.78%
14 / 18
38.38
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rewind
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 current
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 next
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
1
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 first
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 raw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 json
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 isset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 len
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 files
85.71% covered (warning)
85.71%
12 / 14
0.00% covered (danger)
0.00%
0 / 1
9.24
 fileItem
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 effectiveFiles
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
4.03
 hasFile
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
5.93
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Value;
6
7use Cosray\Field\Capability\Translatable;
8use Cosray\Field\Field;
9use Cosray\Field\Owner;
10use Cosray\Schema\TranslateMode;
11use Iterator;
12use Override;
13
14/**
15 * @property-read Field&Translatable $field
16 */
17class Files extends Value implements Iterator
18{
19    protected int $pointer = 0;
20
21    public function __construct(
22        Owner $owner,
23        Field&Translatable $field,
24        ValueContext $context,
25        protected int $index = 0,
26    ) {
27        parent::__construct($owner, $field, $context);
28    }
29
30    #[Override]
31    public function __toString(): string
32    {
33        return 'Files: count(' . count($this->raw()) . ')';
34    }
35
36    #[Override]
37    public function rewind(): void
38    {
39        $this->pointer = 0;
40    }
41
42    #[Override]
43    public function current(): File
44    {
45        return $this->get($this->pointer);
46    }
47
48    #[Override]
49    public function key(): int
50    {
51        return $this->pointer;
52    }
53
54    public function count(): int
55    {
56        return count($this->files());
57    }
58
59    #[Override]
60    public function next(): void
61    {
62        $this->pointer++;
63    }
64
65    #[Override]
66    public function valid(): bool
67    {
68        return $this->fileItem($this->pointer) !== null;
69    }
70
71    public function get(int $index): File
72    {
73        return new File($this->owner, $this->field, $this->context, $index);
74    }
75
76    public function first(): File
77    {
78        return new File($this->owner, $this->field, $this->context, 0);
79    }
80
81    /** @return array<mixed> */
82    #[Override]
83    public function raw(): array
84    {
85        return $this->files();
86    }
87
88    /** @return list<array<string, mixed>> the files whose assets exist */
89    #[Override]
90    public function json(): array
91    {
92        $items = [];
93
94        for ($index = 0; $index < $this->count(); $index++) {
95            $item = $this->get($index)->json();
96
97            if ($item !== null) {
98                $items[] = $item;
99            }
100        }
101
102        return $items;
103    }
104
105    #[Override]
106    public function isset(): bool
107    {
108        return $this->fileItem(0) !== null;
109    }
110
111    protected function len(): int
112    {
113        return count($this->files());
114    }
115
116    /** @return array<mixed> */
117    protected function files(): array
118    {
119        $value = $this->data['value'] ?? [];
120
121        if (
122            !isset($this->data['type'])
123            && isset($this->data['files'])
124            && is_array($this->data['files'])
125        ) {
126            if (
127                $this->field->translateMode() === TranslateMode::Asymmetric
128                && !array_is_list($this->data['files'])
129            ) {
130                return $this->effectiveFiles($this->data['files']);
131            }
132
133            return $this->data['files'];
134        }
135
136        if (!is_array($value)) {
137            return [];
138        }
139
140        if ($this->field->translateMode() === TranslateMode::Asymmetric) {
141            return $this->effectiveFiles($value);
142        }
143
144        $files = $value[Field::NEUTRAL_LOCALE] ?? [];
145
146        return is_array($files) ? $files : [];
147    }
148
149    /** @return ?array<mixed> */
150    protected function fileItem(int $index): ?array
151    {
152        $item = $this->files()[$index] ?? null;
153
154        return is_array($item) ? $item : null;
155    }
156
157    /**
158     * @param array<string, mixed> $map
159     * @return array<mixed>
160     */
161    protected function effectiveFiles(array $map): array
162    {
163        $locale = $this->locale;
164
165        while ($locale) {
166            $files = $map[$locale->id] ?? null;
167
168            if ($this->hasFile($files)) {
169                return $files;
170            }
171
172            $locale = $locale->fallback();
173        }
174
175        $files = $map[Field::NEUTRAL_LOCALE] ?? null;
176
177        return $this->hasFile($files) ? $files : [];
178    }
179
180    protected function hasFile(mixed $files): bool
181    {
182        if (!is_array($files)) {
183            return false;
184        }
185
186        foreach ($files as $file) {
187            if (is_array($file) && ($file['uid'] ?? null)) {
188                return true;
189            }
190        }
191
192        return false;
193    }
194}