TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
GalleryProcessor.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Frontend\DataProcessing;
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 
21 
96 {
103 
110 
117  'horizontal' => [
118  'center' => [0, 8],
119  'right' => [1, 9, 17, 25],
120  'left' => [2, 10, 18, 26]
121  ],
122  'vertical' => [
123  'above' => [0, 1, 2],
124  'intext' => [17, 18, 25, 26],
125  'below' => [8, 9, 10]
126  ]
127  ];
128 
134  protected $galleryData = [
135  'position' => [
136  'horizontal' => '',
137  'vertical' => '',
138  'noWrap' => false
139  ],
140  'width' => 0,
141  'count' => [
142  'files' => 0,
143  'columns' => 0,
144  'rows' => 0,
145  ],
146  'columnSpacing' => 0,
147  'border' => [
148  'enabled' => false,
149  'width' => 0,
150  'padding' => 0,
151  ],
152  'rows' => []
153  ];
154 
158  protected $numberOfColumns;
159 
163  protected $mediaOrientation;
164 
168  protected $maxGalleryWidth;
169 
174 
178  protected $equalMediaHeight;
179 
183  protected $equalMediaWidth;
184 
188  protected $columnSpacing;
189 
193  protected $borderEnabled;
194 
198  protected $borderWidth;
199 
203  protected $borderPadding;
204 
210  protected $fileObjects = [];
211 
217  protected $mediaDimensions = [];
218 
229  public function process(
230  ContentObjectRenderer $cObj,
231  array $contentObjectConfiguration,
233  array $processedData
234  ) {
235  if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) {
236  return $processedData;
237  }
238 
239  $this->contentObjectRenderer = $cObj;
240  $this->processorConfiguration = $processorConfiguration;
241 
242  $filesProcessedDataKey = (string)$cObj->stdWrapValue(
243  'filesProcessedDataKey',
244  $processorConfiguration,
245  'files'
246  );
247  if (isset($processedData[$filesProcessedDataKey]) && is_array($processedData[$filesProcessedDataKey])) {
248  $this->fileObjects = $processedData[$filesProcessedDataKey];
249  $this->galleryData['count']['files'] = count($this->fileObjects);
250  } else {
251  throw new ContentRenderingException('No files found for key ' . $filesProcessedDataKey . ' in $processedData.', 1436809789);
252  }
253 
254  $this->numberOfColumns = (int)$this->getConfigurationValue('numberOfColumns', 'imagecols');
255  $this->mediaOrientation = (int)$this->getConfigurationValue('mediaOrientation', 'imageorient');
256  $this->maxGalleryWidth = (int)$this->getConfigurationValue('maxGalleryWidth') ?: 600;
257  $this->maxGalleryWidthInText = (int)$this->getConfigurationValue('maxGalleryWidthInText') ?: 300;
258  $this->equalMediaHeight = (int)$this->getConfigurationValue('equalMediaHeight', 'imageheight');
259  $this->equalMediaWidth = (int)$this->getConfigurationValue('equalMediaWidth', 'imagewidth');
260  $this->columnSpacing = (int)$this->getConfigurationValue('columnSpacing');
261  $this->borderEnabled = (bool)$this->getConfigurationValue('borderEnabled', 'imageborder');
262  $this->borderWidth = (int)$this->getConfigurationValue('borderWidth');
263  $this->borderPadding = (int)$this->getConfigurationValue('borderPadding');
264 
265  $this->determineGalleryPosition();
267 
268  $this->calculateRowsAndColumns();
270 
271  $this->prepareGalleryData();
272 
273  $targetFieldName = (string)$cObj->stdWrapValue(
274  'as',
275  $processorConfiguration,
276  'gallery'
277  );
278 
279  $processedData[$targetFieldName] = $this->galleryData;
280 
281  return $processedData;
282  }
283 
292  protected function getConfigurationValue($key, $dataArrayKey = null)
293  {
294  $defaultValue = '';
295  if ($dataArrayKey && isset($this->contentObjectRenderer->data[$dataArrayKey])) {
296  $defaultValue = $this->contentObjectRenderer->data[$dataArrayKey];
297  }
298  return $this->contentObjectRenderer->stdWrapValue(
299  $key,
300  $this->processorConfiguration,
301  $defaultValue
302  );
303  }
304 
313  protected function determineGalleryPosition()
314  {
315  foreach ($this->availableGalleryPositions as $positionDirectionKey => $positionDirectionValue) {
316  foreach ($positionDirectionValue as $positionKey => $positionArray) {
317  if (in_array($this->mediaOrientation, $positionArray, true)) {
318  $this->galleryData['position'][$positionDirectionKey] = $positionKey;
319  }
320  }
321  }
322 
323  if ($this->mediaOrientation === 25 || $this->mediaOrientation === 26) {
324  $this->galleryData['position']['noWrap'] = true;
325  }
326  }
327 
333  protected function determineMaximumGalleryWidth()
334  {
335  if ($this->galleryData['position']['vertical'] === 'intext') {
336  $this->galleryData['width'] = $this->maxGalleryWidthInText;
337  } else {
338  $this->galleryData['width'] = $this->maxGalleryWidth;
339  }
340  }
341 
347  protected function calculateRowsAndColumns()
348  {
349 
350  // If no columns defined, set it to 1
351  $columns = max((int)$this->numberOfColumns, 1);
352 
353  // When more columns than media elements, set the columns to the amount of media elements
354  if ($columns > $this->galleryData['count']['files']) {
355  $columns = $this->galleryData['count']['files'];
356  }
357 
358  if ($columns === 0) {
359  $columns = 1;
360  }
361 
362  // Calculate the rows from the amount of files and the columns
363  $rows = ceil($this->galleryData['count']['files'] / $columns);
364 
365  $this->galleryData['count']['columns'] = $columns;
366  $this->galleryData['count']['rows'] = (int)$rows;
367  }
368 
379  protected function calculateMediaWidthsAndHeights()
380  {
381  $columnSpacingTotal = ($this->galleryData['count']['columns'] - 1) * $this->columnSpacing;
382 
383  $galleryWidthMinusBorderAndSpacing = max($this->galleryData['width'] - $columnSpacingTotal, 1);
384 
385  if ($this->borderEnabled) {
386  $borderPaddingTotal = ($this->galleryData['count']['columns'] * 2) * $this->borderPadding;
387  $borderWidthTotal = ($this->galleryData['count']['columns'] * 2) * $this->borderWidth;
388  $galleryWidthMinusBorderAndSpacing = $galleryWidthMinusBorderAndSpacing - $borderPaddingTotal - $borderWidthTotal;
389  }
390 
391  // User entered a predefined height
392  if ($this->equalMediaHeight) {
393  $mediaScalingCorrection = 1;
394  $maximumRowWidth = 0;
395 
396  // Calculate the scaling correction when the total of media elements is wider than the gallery width
397  for ($row = 1; $row <= $this->galleryData['count']['rows']; $row++) {
398  $totalRowWidth = 0;
399  for ($column = 1; $column <= $this->galleryData['count']['columns']; $column++) {
400  $fileKey = (($row - 1) * $this->galleryData['count']['columns']) + $column - 1;
401  if ($fileKey > $this->galleryData['count']['files'] - 1) {
402  break 2;
403  }
404  $currentMediaScaling = $this->equalMediaHeight / max($this->getCroppedDimensionalProperty($this->fileObjects[$fileKey], 'height'), 1);
405  $totalRowWidth += $this->getCroppedDimensionalProperty($this->fileObjects[$fileKey], 'width') * $currentMediaScaling;
406  }
407  $maximumRowWidth = max($totalRowWidth, $maximumRowWidth);
408  $mediaInRowScaling = $totalRowWidth / $galleryWidthMinusBorderAndSpacing;
409  $mediaScalingCorrection = max($mediaInRowScaling, $mediaScalingCorrection);
410  }
411 
412  // Set the corrected dimensions for each media element
413  foreach ($this->fileObjects as $key => $fileObject) {
414  $mediaHeight = floor($this->equalMediaHeight / $mediaScalingCorrection);
415  $mediaWidth = floor(
416  $this->getCroppedDimensionalProperty($fileObject, 'width') * ($mediaHeight / max($this->getCroppedDimensionalProperty($fileObject, 'height'), 1))
417  );
418  $this->mediaDimensions[$key] = [
419  'width' => $mediaWidth,
420  'height' => $mediaHeight
421  ];
422  }
423 
424  // Recalculate gallery width
425  $this->galleryData['width'] = floor($maximumRowWidth / $mediaScalingCorrection);
426 
427  // User entered a predefined width
428  } elseif ($this->equalMediaWidth) {
429  $mediaScalingCorrection = 1;
430 
431  // Calculate the scaling correction when the total of media elements is wider than the gallery width
432  $totalRowWidth = $this->galleryData['count']['columns'] * $this->equalMediaWidth;
433  $mediaInRowScaling = $totalRowWidth / $galleryWidthMinusBorderAndSpacing;
434  $mediaScalingCorrection = max($mediaInRowScaling, $mediaScalingCorrection);
435 
436  // Set the corrected dimensions for each media element
437  foreach ($this->fileObjects as $key => $fileObject) {
438  $mediaWidth = floor($this->equalMediaWidth / $mediaScalingCorrection);
439  $mediaHeight = floor(
440  $this->getCroppedDimensionalProperty($fileObject, 'height') * ($mediaWidth / max($this->getCroppedDimensionalProperty($fileObject, 'width'), 1))
441  );
442  $this->mediaDimensions[$key] = [
443  'width' => $mediaWidth,
444  'height' => $mediaHeight
445  ];
446  }
447 
448  // Recalculate gallery width
449  $this->galleryData['width'] = floor($totalRowWidth / $mediaScalingCorrection);
450 
451  // Automatic setting of width and height
452  } else {
453  $maxMediaWidth = (int)($galleryWidthMinusBorderAndSpacing / $this->galleryData['count']['columns']);
454 
455  foreach ($this->fileObjects as $key => $fileObject) {
456  $mediaWidth = min($maxMediaWidth, $this->getCroppedDimensionalProperty($fileObject, 'width'));
457  $mediaHeight = floor(
458  $this->getCroppedDimensionalProperty($fileObject, 'height') * ($mediaWidth / max($this->getCroppedDimensionalProperty($fileObject, 'width'), 1))
459  );
460  $this->mediaDimensions[$key] = [
461  'width' => $mediaWidth,
462  'height' => $mediaHeight
463  ];
464  }
465  }
466  }
467 
476  protected function getCroppedDimensionalProperty(FileInterface $fileObject, $dimensionalProperty)
477  {
478  if (!$fileObject->hasProperty('crop') || empty($fileObject->getProperty('crop'))) {
479  return $fileObject->getProperty($dimensionalProperty);
480  }
481  $croppingConfiguration = json_decode($fileObject->getProperty('crop'), true);
482  return (int)$croppingConfiguration[$dimensionalProperty];
483  }
484 
492  protected function prepareGalleryData()
493  {
494  for ($row = 1; $row <= $this->galleryData['count']['rows']; $row++) {
495  for ($column = 1; $column <= $this->galleryData['count']['columns']; $column++) {
496  $fileKey = (($row - 1) * $this->galleryData['count']['columns']) + $column - 1;
497 
498  $this->galleryData['rows'][$row]['columns'][$column] = [
499  'media' => $this->fileObjects[$fileKey],
500  'dimensions' => [
501  'width' => $this->mediaDimensions[$fileKey]['width'],
502  'height' => $this->mediaDimensions[$fileKey]['height']
503  ]
504  ];
505  }
506  }
507 
508  $this->galleryData['columnSpacing'] = $this->columnSpacing;
509  $this->galleryData['border']['enabled'] = $this->borderEnabled;
510  $this->galleryData['border']['width'] = $this->borderWidth;
511  $this->galleryData['border']['padding'] = $this->borderPadding;
512  }
513 }