-
Notifications
You must be signed in to change notification settings - Fork 4
/
ImageService.php
192 lines (171 loc) · 7.08 KB
/
ImageService.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Extbase\Service;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Imaging\ImageResource;
use TYPO3\CMS\Core\LinkHandling\LinkService;
use TYPO3\CMS\Core\Page\AssetCollector;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Resource\ProcessedFile;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* Service for processing images
*/
class ImageService implements SingletonInterface
{
/**
* @var ResourceFactory
*/
protected $resourceFactory;
/**
* ImageService constructor.
*/
public function __construct(ResourceFactory $resourceFactory)
{
$this->resourceFactory = $resourceFactory;
}
/**
* Create a processed file
*
* @param FileInterface|FileReference $image
*/
public function applyProcessingInstructions($image, array $processingInstructions): ProcessedFile
{
/*
* todo: this method should be split to be able to have a proper method signature.
* todo: actually, this method only really works with objects of type \TYPO3\CMS\Core\Resource\File, as this
* todo: is the only implementation that supports the support method.
*/
if (is_callable([$image, 'getOriginalFile'])) {
// Get the original file from the file reference
$image = $image->getOriginalFile();
}
$processedImage = $image->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingInstructions);
$this->setCompatibilityValues($processedImage);
return $processedImage;
}
/**
* Get public url of image depending on the environment
*
* @param bool|false $absolute Force absolute URL
*/
public function getImageUri(FileInterface $image, bool $absolute = false): string
{
$imageUrl = $image->getPublicUrl();
if (!$absolute || $imageUrl === null) {
return (string)$imageUrl;
}
return GeneralUtility::locationHeaderUrl($imageUrl);
}
/**
* Get File or FileReference object
*
* This method is a factory and compatibility method that does not belong to
* this service, but is put here for pragmatic reasons for the time being.
* It should be removed once we do not support string sources for images anymore.
*
* @param string $src
* @param FileInterface|\TYPO3\CMS\Extbase\Domain\Model\FileReference|null $image
* @param bool $treatIdAsReference
* @throws \UnexpectedValueException
* @internal
*/
public function getImage(string $src, $image, bool $treatIdAsReference): FileInterface
{
if ($image instanceof File || $image instanceof FileReference) {
// We already received a valid file and therefore just return it
return $image;
}
if (is_callable([$image, 'getOriginalResource'])) {
// We have a domain model, so we need to fetch the FAL resource object from there
$originalResource = $image->getOriginalResource();
if (!($originalResource instanceof File || $originalResource instanceof FileReference)) {
throw new \UnexpectedValueException('No original resource could be resolved for supplied file ' . get_class($image), 1625838481);
}
return $originalResource;
}
if ($image !== null) {
// Some value is given for $image, but it's not a valid type
throw new \UnexpectedValueException(
'Supplied file must be File or FileReference, ' . get_debug_type($image) . ' given.',
1625585157
);
}
// Since image is not given, try to resolve an image from the source string
$resolvedImage = $this->getImageFromSourceString($src, $treatIdAsReference);
if ($resolvedImage instanceof File || $resolvedImage instanceof FileReference) {
return $resolvedImage;
}
if ($resolvedImage === null) {
// No image could be resolved using the given source string
throw new \UnexpectedValueException('Supplied ' . $src . ' could not be resolved to a File or FileReference.', 1625585158);
}
// A FileInterface was found, however only File and FileReference are valid
throw new \UnexpectedValueException(
'Resolved file object type ' . get_class($resolvedImage) . ' for ' . $src . ' must be File or FileReference.',
1382687163
);
}
/**
* Get File or FileReference object by src
*/
protected function getImageFromSourceString(string $src, bool $treatIdAsReference): ?FileInterface
{
if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()
&& str_starts_with($src, '../')
) {
$src = substr($src, 3);
}
if (MathUtility::canBeInterpretedAsInteger($src)) {
if ($treatIdAsReference) {
$image = $this->resourceFactory->getFileReferenceObject((int)$src);
} else {
$image = $this->resourceFactory->getFileObject($src);
}
} elseif (str_starts_with($src, 't3://file')) {
// We have a t3://file link to a file in FAL
$linkService = GeneralUtility::makeInstance(LinkService::class);
$data = $linkService->resolveByStringRepresentation($src);
$image = $data['file'];
} else {
// We have a combined identifier or legacy (storage 0) path
$image = $this->resourceFactory->retrieveFileOrFolderObject($src);
}
// Check the resolved image as this could also be a FolderInterface
return $image instanceof FileInterface ? $image : null;
}
/**
* Set compatibility values to frontend controller object
* in case we are in frontend environment.
*/
protected function setCompatibilityValues(ProcessedFile $processedImage): void
{
$imageResource = ImageResource::createFromProcessedFile($processedImage);
if ($imageResource->getPublicUrl() !== null) {
// only add the processed image to AssetCollector if the public url is not NULL
GeneralUtility::makeInstance(AssetCollector::class)->addMedia(
$imageResource->getPublicUrl(),
$imageResource->getLegacyImageResourceInformation()
);
}
}
}