[FEATURE] Add new imageManipulation supporting multiple crop variants
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Imaging / ImageManipulation / CropVariant.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Imaging\ImageManipulation;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 class CropVariant
19 {
20 /**
21 * @var string
22 */
23 protected $id;
24
25 /**
26 * @var string
27 */
28 protected $title;
29
30 /**
31 * @var Area
32 */
33 protected $cropArea;
34
35 /**
36 * @var Ratio[]
37 */
38 protected $allowedAspectRatios;
39
40 /**
41 * @var string
42 */
43 protected $selectedRatio;
44
45 /**
46 * @var Area|null
47 */
48 protected $focusArea;
49
50 /**
51 * @var Area[]|null
52 */
53 protected $coverAreas;
54
55 /**
56 * @param string $id
57 * @param string $title
58 * @param Area $cropArea
59 * @param Ratio[] $allowedAspectRatios
60 * @param string|null $selectedRatio
61 * @param Area|null $focusArea
62 * @param Area[]|null $coverAreas
63 * @throws InvalidConfigurationException
64 */
65 public function __construct(
66 string $id,
67 string $title,
68 Area $cropArea,
69 array $allowedAspectRatios = null,
70 string $selectedRatio = null,
71 Area $focusArea = null,
72 array $coverAreas = null
73 ) {
74 $this->id = $id;
75 $this->title = $title;
76 $this->cropArea = $cropArea;
77 if ($allowedAspectRatios) {
78 $this->setAllowedAspectRatios(...$allowedAspectRatios);
79 }
80 $this->selectedRatio = $selectedRatio;
81 $this->focusArea = $focusArea;
82 if ($coverAreas !== null) {
83 $this->setCoverAreas(...$coverAreas);
84 }
85 }
86
87 /**
88 * @param string $id
89 * @param array $config
90 * @return CropVariant
91 * @throws InvalidConfigurationException
92 */
93 public static function createFromConfiguration(string $id, array $config): CropVariant
94 {
95 try {
96 return new self(
97 $id,
98 $config['title'] ?? '',
99 Area::createFromConfiguration($config['cropArea']),
100 isset($config['allowedAspectRatios']) ? Ratio::createMultipleFromConfiguration($config['allowedAspectRatios']) : null,
101 $config['selectedRatio'] ?? null,
102 isset($config['focusArea']) ? Area::createFromConfiguration($config['focusArea']) : null,
103 isset($config['coverAreas']) ? Area::createMultipleFromConfiguration($config['coverAreas']) : null
104 );
105 } catch (\Throwable $throwable) {
106 throw new InvalidConfigurationException(sprintf('Invalid type in configuration for crop variant: %s', $throwable->getMessage()), 1485278693, $throwable);
107 }
108 }
109
110 /**
111 * @return array
112 * @internal
113 */
114 public function asArray(): array
115 {
116 $allowedAspectRatiosAsArray = [];
117 foreach ($this->allowedAspectRatios as $id => $allowedAspectRatio) {
118 $allowedAspectRatiosAsArray[$id] = $allowedAspectRatio->asArray();
119 }
120 if ($this->coverAreas !== null) {
121 $coverAreasAsArray = [];
122 foreach ($this->coverAreas as $coverArea) {
123 $coverAreasAsArray[] = $coverArea->asArray();
124 }
125 }
126 return [
127 'id' => $this->id,
128 'title' => $this->title,
129 'cropArea' => $this->cropArea->asArray(),
130 'allowedAspectRatios' => $allowedAspectRatiosAsArray,
131 'selectedRatio' => $this->selectedRatio,
132 'focusArea' => $this->focusArea ? $this->focusArea->asArray() : null,
133 'coverAreas' => $coverAreasAsArray ?? null,
134 ];
135 }
136
137 /**
138 * @return string
139 */
140 public function getId(): string
141 {
142 return $this->id;
143 }
144
145 /**
146 * @return Area
147 */
148 public function getCropArea(): Area
149 {
150 return $this->cropArea;
151 }
152
153 /**
154 * @return Area|null
155 */
156 public function getFocusArea()
157 {
158 return $this->focusArea;
159 }
160
161 /**
162 * @param Ratio[] $ratios
163 * @throws InvalidConfigurationException
164 */
165 protected function setAllowedAspectRatios(Ratio ...$ratios)
166 {
167 $this->allowedAspectRatios = [];
168 foreach ($ratios as $ratio) {
169 $this->addAllowedAspectRatio($ratio);
170 }
171 }
172
173 /**
174 * @param Ratio $ratio
175 * @throws InvalidConfigurationException
176 */
177 protected function addAllowedAspectRatio(Ratio $ratio)
178 {
179 if (isset($this->allowedAspectRatios[$ratio->getId()])) {
180 throw new InvalidConfigurationException(sprintf('Ratio with with duplicate ID (%s) is configured. Make sure all configured ratios have different ids.', $ratio->getId()), 1485274618);
181 }
182 $this->allowedAspectRatios[$ratio->getId()] = $ratio;
183 }
184
185 /**
186 * @param Area[] $areas
187 * @throws InvalidConfigurationException
188 */
189 protected function setCoverAreas(Area ...$areas)
190 {
191 $this->coverAreas = [];
192 foreach ($areas as $area) {
193 $this->addCoverArea($area);
194 }
195 }
196
197 /**
198 * @param Area $area
199 * @throws InvalidConfigurationException
200 */
201 protected function addCoverArea(Area $area)
202 {
203 $this->coverAreas[] = $area;
204 }
205 }