5fca6505c8a9bfa4a38814d0fcb8d4b28ce27b15
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Service / ImageService.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Service;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\LinkHandling\LinkService;
18 use TYPO3\CMS\Core\Resource\File;
19 use TYPO3\CMS\Core\Resource\FileInterface;
20 use TYPO3\CMS\Core\Resource\FileReference;
21 use TYPO3\CMS\Core\Resource\ProcessedFile;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23 use TYPO3\CMS\Core\Utility\MathUtility;
24
25 /**
26 * Service for processing images
27 */
28 class ImageService implements \TYPO3\CMS\Core\SingletonInterface
29 {
30 /**
31 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
32 */
33 protected $resourceFactory;
34
35 /**
36 * @var \TYPO3\CMS\Extbase\Service\EnvironmentService
37 */
38 protected $environmentService;
39
40 /**
41 * @param \TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory
42 */
43 public function injectResourceFactory(\TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory)
44 {
45 $this->resourceFactory = $resourceFactory;
46 }
47
48 /**
49 * @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
50 */
51 public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
52 {
53 $this->environmentService = $environmentService;
54 }
55
56 /**
57 * Create a processed file
58 *
59 * @param FileInterface|FileReference $image
60 * @param array $processingInstructions
61 * @return ProcessedFile
62 * @api
63 */
64 public function applyProcessingInstructions($image, $processingInstructions)
65 {
66 if (is_callable([$image, 'getOriginalFile'])) {
67 // Get the original file from the file reference
68 $image = $image->getOriginalFile();
69 }
70
71 $processedImage = $image->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingInstructions);
72 $this->setCompatibilityValues($processedImage);
73
74 return $processedImage;
75 }
76
77 /**
78 * Get public url of image depending on the environment
79 *
80 * @param FileInterface $image
81 * @param bool|FALSE $absolute Force absolute URL
82 * @return string
83 * @api
84 */
85 public function getImageUri(FileInterface $image, $absolute = false)
86 {
87 $imageUrl = $image->getPublicUrl();
88 $parsedUrl = parse_url($imageUrl);
89 // no prefix in case of an already fully qualified URL
90 if (isset($parsedUrl['host'])) {
91 $uriPrefix = '';
92 } elseif ($this->environmentService->isEnvironmentInFrontendMode()) {
93 $uriPrefix = $GLOBALS['TSFE']->absRefPrefix;
94 } else {
95 $uriPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
96 }
97
98 if ($absolute) {
99 // If full URL has no scheme we add the same scheme as used by the site
100 // so we have an absolute URL also usable outside of browser scope (e.g. in an email message)
101 if (isset($parsedUrl['host']) && !isset($parsedUrl['scheme'])) {
102 $uriPrefix = (GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https:' : 'http:') . $uriPrefix;
103 }
104 return GeneralUtility::locationHeaderUrl($uriPrefix . $imageUrl);
105 }
106 return $uriPrefix . $imageUrl;
107 }
108
109 /**
110 * Get File or FileReference object
111 *
112 * This method is a factory and compatibility method that does not belong to
113 * this service, but is put here for pragmatic reasons for the time being.
114 * It should be removed once we do not support string sources for images anymore.
115 *
116 * @param string $src
117 * @param mixed $image
118 * @param bool $treatIdAsReference
119 * @return FileInterface|FileReference
120 * @throws \UnexpectedValueException
121 * @internal
122 */
123 public function getImage($src, $image, $treatIdAsReference)
124 {
125 if (is_null($image)) {
126 $image = $this->getImageFromSourceString($src, $treatIdAsReference);
127 } elseif (is_callable([$image, 'getOriginalResource'])) {
128 // We have a domain model, so we need to fetch the FAL resource object from there
129 $image = $image->getOriginalResource();
130 }
131
132 if (!($image instanceof File || $image instanceof FileReference)) {
133 throw new \UnexpectedValueException('Supplied file object type ' . get_class($image) . ' for ' . $src . ' must be File or FileReference.', 1382687163);
134 }
135
136 return $image;
137 }
138
139 /**
140 * Get File or FileReference object by src
141 *
142 * @param string $src
143 * @param bool $treatIdAsReference
144 * @return FileInterface|FileReference|\TYPO3\CMS\Core\Resource\Folder
145 */
146 protected function getImageFromSourceString($src, $treatIdAsReference)
147 {
148 if ($this->environmentService->isEnvironmentInBackendMode() && substr($src, 0, 3) === '../') {
149 $src = substr($src, 3);
150 }
151 if (MathUtility::canBeInterpretedAsInteger($src)) {
152 if ($treatIdAsReference) {
153 $image = $this->resourceFactory->getFileReferenceObject($src);
154 } else {
155 $image = $this->resourceFactory->getFileObject($src);
156 }
157 } elseif (strpos($src, 't3://file') === 0) {
158 // We have a t3://file link to a file in FAL
159 $linkService = GeneralUtility::makeInstance(LinkService::class);
160 $data = $linkService->resolveByStringRepresentation($src);
161 $image = $data['file'];
162 } else {
163 // We have a combined identifier or legacy (storage 0) path
164 $image = $this->resourceFactory->retrieveFileOrFolderObject($src);
165 }
166 return $image;
167 }
168
169 /**
170 * Set compatibility values to frontend controller object
171 * in case we are in frontend environment.
172 *
173 * @param ProcessedFile $processedImage
174 */
175 protected function setCompatibilityValues(ProcessedFile $processedImage)
176 {
177 if ($this->environmentService->isEnvironmentInFrontendMode()) {
178 $imageInfo = $this->getCompatibilityImageResourceValues($processedImage);
179 $GLOBALS['TSFE']->lastImageInfo = $imageInfo;
180 $GLOBALS['TSFE']->imagesOnPage[] = $imageInfo[3];
181 }
182 }
183
184 /**
185 * Calculates the compatibility values
186 * This is duplicate code taken from ContentObjectRenderer::getImgResource()
187 * Ideally we should get rid of this code in both places.
188 *
189 * @param ProcessedFile $processedImage
190 * @return array
191 */
192 protected function getCompatibilityImageResourceValues(ProcessedFile $processedImage)
193 {
194 $hash = $processedImage->calculateChecksum();
195 if (isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) {
196 $compatibilityImageResourceValues = $GLOBALS['TSFE']->tmpl->fileCache[$hash];
197 } else {
198 $compatibilityImageResourceValues = [
199 0 => $processedImage->getProperty('width'),
200 1 => $processedImage->getProperty('height'),
201 2 => $processedImage->getExtension(),
202 3 => $processedImage->getPublicUrl(),
203 'origFile' => $processedImage->getOriginalFile()->getPublicUrl(),
204 'origFile_mtime' => $processedImage->getOriginalFile()->getModificationTime(),
205 // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder,
206 // in order for the setup-array to create a unique filename hash.
207 'originalFile' => $processedImage->getOriginalFile(),
208 'processedFile' => $processedImage,
209 'fileCacheHash' => $hash
210 ];
211 }
212 return $compatibilityImageResourceValues;
213 }
214 }