Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
21 / 22
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Image
95.45% covered (success)
95.45%
21 / 22
83.33% covered (warning)
83.33%
5 / 6
10
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
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 value
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 structure
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 metaShape
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 neutralShape
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Field;
6
7use Celema\Sire\Shape;
8use Cosray\Schema\TranslateMode;
9use Cosray\Validation\Shapes;
10use Cosray\Value;
11use Override;
12
13class Image extends File
14{
15    /** The tile aspect ratios a gallery may choose; `auto` keeps each image's own. */
16    public const array RATIOS = ['auto', '1/1', '4/3', '3/2', '16/9', '3/4', '2/3'];
17
18    #[Override]
19    public function control(): Control
20    {
21        return Control::image();
22    }
23
24    /** @return list<TranslateMode> */
25    #[Override]
26    protected function supportedTranslateModes(): array
27    {
28        return [TranslateMode::Symmetric, TranslateMode::Asymmetric];
29    }
30
31    #[Override]
32    public function value(): Value\Images|Value\Image
33    {
34        if ($this->allowsMultipleItems()) {
35            if ($this->isAsymmetricallyTranslated()) {
36                return new Value\TranslatedImages($this->owner, $this, $this->valueContext);
37            }
38
39            return new Value\Images($this->owner, $this, $this->valueContext);
40        }
41
42        if ($this->isAsymmetricallyTranslated()) {
43            return new Value\TranslatedImage($this->owner, $this, $this->valueContext);
44        }
45
46        return new Value\Image($this->owner, $this, $this->valueContext);
47    }
48
49    #[Override]
50    public function structure(mixed $value = null): array
51    {
52        if ($this->isAsymmetricallyTranslated()) {
53            return $this->getTranslatableFileStructure('image', $value);
54        }
55
56        return $this->getFileStructure('image', $value);
57    }
58
59    /**
60     * The gallery settings the image element keeps as field meta: the
61     * tiles' aspect ratio and whether they crop to it. Other meta keys
62     * pass through as before.
63     */
64    #[Override]
65    protected function metaShape(): Shape
66    {
67        $shape = parent::metaShape();
68        $shape
69            ->add('ratio', $this->neutralShape('string', ['in:' . implode(',', self::RATIOS)]))
70            ->optional()
71            ->nullable();
72        $shape->add('crop', $this->neutralShape('bool'))->optional()->nullable();
73
74        return $shape;
75    }
76
77    /** @param list<string> $rules */
78    private function neutralShape(string $type, array $rules = []): Shape
79    {
80        $shape = Shapes::create();
81        $shape->add(self::NEUTRAL_LOCALE, $type)->rules(...$rules)->optional()->nullable();
82
83        return $shape;
84    }
85}