[FEATURE] Add new imageManipulation supporting multiple crop variants
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Imaging / ImageManipulation / CropVariantCollection.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 CropVariantCollection
19 {
20 /**
21 * @var CropVariant[]
22 */
23 protected $cropVariants;
24
25 /**
26 * @param CropVariant[] cropVariants
27 * @throws \TYPO3\CMS\Core\Imaging\ImageManipulation\InvalidConfigurationException
28 */
29 public function __construct(array $cropVariants)
30 {
31 $this->setCropVariants(...$cropVariants);
32 }
33
34 /**
35 * @param string $jsonString
36 * @param array $tcaConfig
37 * @return CropVariantCollection
38 */
39 public static function create(string $jsonString, array $tcaConfig = []): CropVariantCollection
40 {
41 if (empty($jsonString) && empty($tcaConfig)) {
42 return self::createEmpty();
43 }
44 $persistedCollectionConfig = json_decode($jsonString, true);
45 if (!is_array($persistedCollectionConfig)) {
46 $persistedCollectionConfig = [];
47 }
48 try {
49 if ($tcaConfig === []) {
50 $tcaConfig = $persistedCollectionConfig;
51 } else {
52 // Merge selected areas with crop tool configuration
53 reset($persistedCollectionConfig);
54 foreach ($tcaConfig as $id => &$cropVariantConfig) {
55 if (!isset($persistedCollectionConfig[$id])) {
56 $id = key($persistedCollectionConfig);
57 next($persistedCollectionConfig);
58 }
59 if (isset($persistedCollectionConfig[$id]['cropArea'], $cropVariantConfig['cropArea'])) {
60 $cropVariantConfig['cropArea'] = $persistedCollectionConfig[$id]['cropArea'];
61 }
62 if (isset($persistedCollectionConfig[$id]['focusArea'], $cropVariantConfig['focusArea'])) {
63 $cropVariantConfig['focusArea'] = $persistedCollectionConfig[$id]['focusArea'];
64 }
65 if (isset($persistedCollectionConfig[$id]['selectedRatio'], $cropVariantConfig['selectedRatio'])) {
66 $cropVariantConfig['selectedRatio'] = $persistedCollectionConfig[$id]['selectedRatio'];
67 }
68 }
69 unset($cropVariantConfig);
70 }
71 $cropVariants = [];
72 foreach ($tcaConfig as $id => $cropVariantConfig) {
73 $cropVariants[] = CropVariant::createFromConfiguration($id, $cropVariantConfig);
74 }
75 return new self($cropVariants);
76 } catch (\Throwable $throwable) {
77 return self::createEmpty();
78 }
79 }
80
81 /**
82 * @return array
83 * @internal
84 */
85 public function asArray(): array
86 {
87 $cropVariantsAsArray = [];
88 foreach ($this->cropVariants as $id => $cropVariant) {
89 $cropVariantsAsArray[$id] = $cropVariant->asArray();
90 }
91 return $cropVariantsAsArray;
92 }
93
94 /**
95 * @param string $id
96 * @return Area
97 */
98 public function getCropArea(string $id = 'default'): Area
99 {
100 if (isset($this->cropVariants[$id])) {
101 return $this->cropVariants[$id]->getCropArea();
102 } else {
103 return Area::createEmpty();
104 }
105 }
106
107 /**
108 * @param string $id
109 * @return Area
110 */
111 public function getFocusArea(string $id = 'default'): Area
112 {
113 if (isset($this->cropVariants[$id]) && $this->cropVariants[$id]->getFocusArea() !== null) {
114 return $this->cropVariants[$id]->getFocusArea();
115 } else {
116 return Area::createEmpty();
117 }
118 }
119
120 /**
121 * @return CropVariantCollection
122 */
123 protected static function createEmpty(): CropVariantCollection
124 {
125 return new self([]);
126 }
127
128 /**
129 * @param CropVariant[] ...$cropVariants
130 * @throws \TYPO3\CMS\Core\Imaging\ImageManipulation\InvalidConfigurationException
131 */
132 protected function setCropVariants(CropVariant ...$cropVariants)
133 {
134 $this->cropVariants = [];
135 foreach ($cropVariants as $cropVariant) {
136 $this->addCropVariant($cropVariant);
137 }
138 }
139
140 /**
141 * @param CropVariant $cropVariant
142 * @throws InvalidConfigurationException
143 */
144 protected function addCropVariant(CropVariant $cropVariant)
145 {
146 if (isset($this->cropVariants[$cropVariant->getId()])) {
147 throw new InvalidConfigurationException(sprintf('Crop variant with with duplicate ID (%s) is configured. Make sure all configured cropVariants have different ids.', $cropVariant->getId()), 1485284352);
148 }
149 $this->cropVariants[$cropVariant->getId()] = $cropVariant;
150 }
151 }