Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.30% covered (success)
91.30%
42 / 46
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
File
91.30% covered (success)
91.30%
42 / 46
66.67% covered (warning)
66.67%
4 / 6
15.15
0.00% covered (danger)
0.00%
0 / 1
 control
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 supportedTranslateModes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 value
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 structure
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 shape
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
6
 fileListShape
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Field;
6
7use Celema\Sire\Extra;
8use Celema\Sire\Shape;
9use Cosray\Schema\TranslateMode;
10use Cosray\Validation\Prepare;
11use Cosray\Validation\Shapes;
12use Cosray\Value;
13use Override;
14
15class File extends Field implements Capability\Limitable, Capability\Translatable
16{
17    use Capability\IsLimitable;
18    use Capability\IsTranslatable;
19
20    #[Override]
21    public function control(): Control
22    {
23        return Control::file();
24    }
25
26    /** @return list<TranslateMode> */
27    protected function supportedTranslateModes(): array
28    {
29        return [TranslateMode::Symmetric, TranslateMode::Asymmetric];
30    }
31
32    #[Override]
33    public function value(): Value\File|Value\Files
34    {
35        if ($this->allowsMultipleItems()) {
36            if ($this->isAsymmetricallyTranslated()) {
37                return new Value\TranslatedFiles($this->owner, $this, $this->valueContext);
38            }
39
40            return new Value\Files($this->owner, $this, $this->valueContext);
41        }
42
43        if ($this->isAsymmetricallyTranslated()) {
44            return new Value\TranslatedFile($this->owner, $this, $this->valueContext);
45        }
46
47        return new Value\File($this->owner, $this, $this->valueContext);
48    }
49
50    #[Override]
51    public function structure(mixed $value = null): array
52    {
53        if ($this->isAsymmetricallyTranslated()) {
54            return $this->getTranslatableFileStructure('file', $value);
55        }
56
57        return $this->getFileStructure('file', $value);
58    }
59
60    #[Override]
61    public function shape(): Shape
62    {
63        $limitValidators = $this->limitValidators();
64        $shape = Shapes::create();
65        $this->addType($shape);
66        $fileShape = $this->fileListShape();
67
68        if ($this->isAsymmetricallyTranslated()) {
69            $i18nShape = Shapes::create();
70            $locales = $this->owner->locales();
71            $defaultLocale = $locales->getDefault()->id;
72
73            foreach ($locales as $locale) {
74                $localeValidators = $limitValidators;
75                $localeField = $i18nShape
76                    ->add($locale->id, $fileShape)
77                    ->label($this->valueLabel($locale))
78                    ->prepare(Prepare::nullAsEmpty(...));
79
80                if ($this->isRequired() && $locale->id === $defaultLocale) {
81                    $localeValidators[] = 'required';
82                } else {
83                    $localeField->optional()->nullable();
84                }
85
86                $localeField->rules(...$localeValidators);
87            }
88
89            $value = $shape
90                ->add('value', $i18nShape)
91                ->rules(...$this->validators)
92                ->prepare(Prepare::nullAsEmpty(...));
93        } else {
94            $value = $shape
95                ->add('value', $this->zxxShape($fileShape, $limitValidators))
96                ->rules(...$this->validators)
97                ->prepare(Prepare::nullAsEmpty(...));
98        }
99
100        if (!$this->isRequired()) {
101            $value->optional()->nullable();
102        }
103
104        $this->addMeta($shape);
105
106        return $shape;
107    }
108
109    protected function fileListShape(): Shape
110    {
111        $fileShape = Shapes::list();
112        $fileShape->add('uid', 'string')->rules('required');
113        $fileShape->add('meta', Shapes::create()->extra(Extra::Allow))->optional()->nullable();
114
115        return $fileShape;
116    }
117}