‪TYPO3CMS  10.4
ImageContentObject.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
24 
29 {
36  public function ‪render($conf = [])
37  {
38  if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
39  return '';
40  }
41 
42  $theValue = $this->‪cImage($conf['file'], $conf);
43  if (isset($conf['stdWrap.'])) {
44  $theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
45  }
46  return $theValue;
47  }
48 
57  protected function ‪cImage($file, $conf)
58  {
59  $tsfe = $this->‪getTypoScriptFrontendController();
60  $info = $this->cObj->getImgResource($file, $conf['file.']);
61  $tsfe->lastImageInfo = $info;
62  if (!is_array($info)) {
63  return '';
64  }
65  if (is_file(‪Environment::getPublicPath() . '/' . $info['3'])) {
66  $source = $tsfe->absRefPrefix . str_replace('%2F', '/', rawurlencode($info['3']));
67  } else {
68  $source = $info[3];
69  }
70  // Remove file objects for AssetCollector, as it only allows to store scalar values
71  unset($info['originalFile'], $info['processedFile']);
72  GeneralUtility::makeInstance(AssetCollector::class)->addMedia(
73  $source,
74  $info
75  );
76 
77  $layoutKey = $this->cObj->stdWrap($conf['layoutKey'], $conf['layoutKey.']);
78  $imageTagTemplate = $this->‪getImageTagTemplate($layoutKey, $conf);
79  $sourceCollection = $this->‪getImageSourceCollection($layoutKey, $conf, $file);
80 
81  // This array is used to collect the image-refs on the page...
82  $tsfe->imagesOnPage[] = $source;
83  $altParam = $this->‪getAltParam($conf);
84  $params = $this->cObj->stdWrapValue('params', $conf);
85  if ($params !== '' && $params[0] !== ' ') {
86  $params = ' ' . $params;
87  }
88 
89  $imageTagValues = [
90  'width' => (int)$info[0],
91  'height' => (int)$info[1],
92  'src' => htmlspecialchars($source),
93  'params' => $params,
94  'altParams' => $altParam,
95  'border' => $this->‪getBorderAttr(' border="' . (int)$conf['border'] . '"'),
96  'sourceCollection' => $sourceCollection,
97  'selfClosingTagSlash' => !empty($tsfe->xhtmlDoctype) ? ' /' : '',
98  ];
99 
100  $markerTemplateEngine = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
101  $theValue = $markerTemplateEngine->substituteMarkerArray($imageTagTemplate, $imageTagValues, '###|###', true, true);
102 
103  $linkWrap = isset($conf['linkWrap.']) ? $this->cObj->stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
104  if ($linkWrap) {
105  $theValue = $this->‪linkWrap($theValue, $linkWrap);
106  } elseif ($conf['imageLinkWrap']) {
107  $originalFile = !empty($info['originalFile']) ? $info['originalFile'] : $info['origFile'];
108  $theValue = $this->cObj->imageLinkWrap($theValue, $originalFile, $conf['imageLinkWrap.']);
109  }
110  $wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
111  if ((string)$wrap !== '') {
112  $theValue = $this->cObj->wrap($theValue, $conf['wrap']);
113  }
114  return $theValue;
115  }
116 
124  protected function ‪getBorderAttr($borderAttr)
125  {
126  $tsfe = $this->‪getTypoScriptFrontendController();
127  $docType = $tsfe->xhtmlDoctype;
128  if (
129  $docType !== 'xhtml_strict' && $docType !== 'xhtml_11'
130  && $tsfe->config['config']['doctype'] !== 'html5'
131  && !$tsfe->config['config']['disableImgBorderAttr']
132  ) {
133  return $borderAttr;
134  }
135  return '';
136  }
137 
146  protected function ‪getImageTagTemplate($layoutKey, $conf): string
147  {
148  if ($layoutKey && isset($conf['layout.']) && isset($conf['layout.'][$layoutKey . '.'])) {
149  return $this->cObj->stdWrap(
150  $conf['layout.'][$layoutKey . '.']['element'] ?? '',
151  $conf['layout.'][$layoutKey . '.']['element.'] ?? []
152  );
153  }
154  return '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
155  }
156 
166  protected function ‪getImageSourceCollection($layoutKey, $conf, $file)
167  {
168  $sourceCollection = '';
169  if ($layoutKey
170  && isset($conf['sourceCollection.']) && $conf['sourceCollection.']
171  && (
172  isset($conf['layout.'][$layoutKey . '.']['source']) && $conf['layout.'][$layoutKey . '.']['source']
173  || isset($conf['layout.'][$layoutKey . '.']['source.']) && $conf['layout.'][$layoutKey . '.']['source.']
174  )
175  ) {
176 
177  // find active sourceCollection
178  $activeSourceCollections = [];
179  foreach ($conf['sourceCollection.'] as $sourceCollectionKey => $sourceCollectionConfiguration) {
180  if (substr($sourceCollectionKey, -1) === '.') {
181  if (empty($sourceCollectionConfiguration['if.']) || $this->cObj->checkIf($sourceCollectionConfiguration['if.'])) {
182  $activeSourceCollections[] = $sourceCollectionConfiguration;
183  }
184  }
185  }
186 
187  // apply option split to configurations
188  $tsfe = $this->‪getTypoScriptFrontendController();
189  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
190  $srcLayoutOptionSplitted = $typoScriptService->explodeConfigurationForOptionSplit((array)$conf['layout.'][$layoutKey . '.'], count($activeSourceCollections));
191 
192  // render sources
193  foreach ($activeSourceCollections as $key => $sourceConfiguration) {
194  $sourceLayout = $this->cObj->stdWrap(
195  $srcLayoutOptionSplitted[$key]['source'] ?? '',
196  $srcLayoutOptionSplitted[$key]['source.'] ?? []
197  );
198 
199  $sourceRenderConfiguration = [
200  'file' => $file,
201  'file.' => $conf['file.'] ?? null
202  ];
203 
204  if (isset($sourceConfiguration['quality']) || isset($sourceConfiguration['quality.'])) {
205  $imageQuality = $sourceConfiguration['quality'] ?? '';
206  if (isset($sourceConfiguration['quality.'])) {
207  $imageQuality = $this->cObj->stdWrap($sourceConfiguration['quality'], $sourceConfiguration['quality.']);
208  }
209  if ($imageQuality) {
210  $sourceRenderConfiguration['file.']['params'] = '-quality ' . (int)$imageQuality;
211  }
212  }
213 
214  if (isset($sourceConfiguration['pixelDensity'])) {
215  $pixelDensity = (int)$this->cObj->stdWrap(
216  $sourceConfiguration['pixelDensity'] ?? '',
217  $sourceConfiguration['pixelDensity.'] ?? []
218  );
219  } else {
220  $pixelDensity = 1;
221  }
222  $dimensionKeys = ['width', 'height', 'maxW', 'minW', 'maxH', 'minH', 'maxWidth', 'maxHeight', 'XY'];
223  foreach ($dimensionKeys as $dimensionKey) {
224  $dimension = $this->cObj->stdWrap(
225  $sourceConfiguration[$dimensionKey] ?? '',
226  $sourceConfiguration[$dimensionKey . '.'] ?? []
227  );
228  if (!$dimension) {
229  $dimension = $this->cObj->stdWrap(
230  $conf['file.'][$dimensionKey] ?? '',
231  $conf['file.'][$dimensionKey . '.'] ?? []
232  );
233  }
234  if ($dimension !== '') {
235  if (strpos($dimension, 'c') !== false && ($dimensionKey === 'width' || $dimensionKey === 'height')) {
236  $dimensionParts = explode('c', $dimension, 2);
237  $dimension = ((int)$dimensionParts[0] * $pixelDensity) . 'c';
238  if ($dimensionParts[1]) {
239  $dimension .= $dimensionParts[1];
240  }
241  } elseif ($dimensionKey === 'XY') {
242  $dimensionParts = ‪GeneralUtility::intExplode(',', $dimension, false, 2);
243  $dimension = $dimensionParts[0] * $pixelDensity;
244  if ($dimensionParts[1]) {
245  $dimension .= ',' . $dimensionParts[1] * $pixelDensity;
246  }
247  } else {
248  $dimension = (int)$dimension * $pixelDensity;
249  }
250  $sourceRenderConfiguration['file.'][$dimensionKey] = $dimension;
251  // Remove the stdWrap properties for dimension as they have been processed already above.
252  unset($sourceRenderConfiguration['file.'][$dimensionKey . '.']);
253  }
254  }
255  $sourceInfo = $this->cObj->getImgResource($sourceRenderConfiguration['file'], $sourceRenderConfiguration['file.']);
256  if ($sourceInfo) {
257  $sourceConfiguration['width'] = $sourceInfo[0];
258  $sourceConfiguration['height'] = $sourceInfo[1];
259  $urlPrefix = '';
260  if (parse_url($sourceInfo[3], PHP_URL_HOST) === null) {
261  $urlPrefix = $tsfe->absRefPrefix;
262  }
263  $sourceConfiguration['src'] = htmlspecialchars($urlPrefix . $sourceInfo[3]);
264  $sourceConfiguration['selfClosingTagSlash'] = !empty($tsfe->xhtmlDoctype) ? ' /' : '';
265 
266  $markerTemplateEngine = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
267  $oneSourceCollection = $markerTemplateEngine->substituteMarkerArray($sourceLayout, $sourceConfiguration, '###|###', true, true);
268 
269  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'] ?? [] as $className) {
270  $hookObject = GeneralUtility::makeInstance($className);
271  if (!$hookObject instanceof ‪ContentObjectOneSourceCollectionHookInterface) {
272  throw new \UnexpectedValueException(
273  '$hookObject must implement interface ' . ContentObjectOneSourceCollectionHookInterface::class,
274  1380017853
275  );
276  }
277  $oneSourceCollection = $hookObject->getOneSourceCollection((array)$sourceRenderConfiguration, (array)$sourceConfiguration, $oneSourceCollection, $this->cObj);
278  }
279 
280  $sourceCollection .= $oneSourceCollection;
281  }
282  }
283  }
284  return $sourceCollection;
285  }
286 
297  protected function ‪linkWrap($content, $wrap)
298  {
299  $wrapArr = explode('|', $wrap);
300  if (preg_match('/\\{([0-9]*)\\}/', $wrapArr[0], $reg)) {
301  $uid = $this->‪getTypoScriptFrontendController()->tmpl->rootLine[$reg[1]]['uid'] ?? null;
302  if ($uid) {
303  $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
304  }
305  }
306  return trim($wrapArr[0] ?? '') . $content . trim($wrapArr[1] ?? '');
307  }
308 
318  public function ‪getAltParam($conf, $longDesc = true)
319  {
320  $altText = isset($conf['altText.']) ? trim($this->cObj->stdWrap($conf['altText'], $conf['altText.'])) : trim($conf['altText']);
321  $titleText = isset($conf['titleText.']) ? trim($this->cObj->stdWrap($conf['titleText'], $conf['titleText.'])) : trim($conf['titleText']);
322  if (isset($conf['longdescURL.']) && $this->‪getTypoScriptFrontendController()->config['config']['doctype'] !== 'html5') {
323  $longDescUrl = $this->cObj->typoLink_URL($conf['longdescURL.']);
324  } else {
325  $longDescUrl = trim($conf['longdescURL']);
326  }
327  $longDescUrl = strip_tags($longDescUrl);
328 
329  // "alt":
330  $altParam = ' alt="' . htmlspecialchars($altText) . '"';
331  // "title":
332  $emptyTitleHandling = isset($conf['emptyTitleHandling.']) ? $this->cObj->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) : $conf['emptyTitleHandling'];
333  // Choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
334  if ($titleText || $emptyTitleHandling === 'keepEmpty') {
335  $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
336  } elseif (!$titleText && $emptyTitleHandling === 'useAlt') {
337  $altParam .= ' title="' . htmlspecialchars($altText) . '"';
338  }
339  // "longDesc" URL
340  if ($longDesc && !empty($longDescUrl)) {
341  $altParam .= ' longdesc="' . htmlspecialchars($longDescUrl) . '"';
342  }
343  return $altParam;
344  }
345 
350  {
351  return ‪$GLOBALS['TSFE'];
352  }
353 }
‪TYPO3\CMS\Core\Page\AssetCollector
Definition: AssetCollector.php:44
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject
Definition: ImageContentObject.php:29
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\getBorderAttr
‪string getBorderAttr($borderAttr)
Definition: ImageContentObject.php:124
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\cImage
‪string cImage($file, $conf)
Definition: ImageContentObject.php:57
‪TYPO3\CMS\Frontend\ContentObject
Definition: AbstractContentObject.php:16
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\render
‪string render($conf=[])
Definition: ImageContentObject.php:36
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\linkWrap
‪string linkWrap($content, $wrap)
Definition: ImageContentObject.php:297
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\getImageSourceCollection
‪string getImageSourceCollection($layoutKey, $conf, $file)
Definition: ImageContentObject.php:166
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\getAltParam
‪string getAltParam($conf, $longDesc=true)
Definition: ImageContentObject.php:318
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\getImageTagTemplate
‪string getImageTagTemplate($layoutKey, $conf)
Definition: ImageContentObject.php:146
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject
Definition: AbstractContentObject.php:25
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:25
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:98
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectOneSourceCollectionHookInterface
Definition: ContentObjectOneSourceCollectionHookInterface.php:22
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Core\Service\MarkerBasedTemplateService
Definition: MarkerBasedTemplateService.php:27
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Frontend\ContentObject\ImageContentObject\getTypoScriptFrontendController
‪TypoScriptFrontendController getTypoScriptFrontendController()
Definition: ImageContentObject.php:349