[BUGFIX] Generate thumbnails for files without width/height
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / Processing / LocalPreviewHelper.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource\Processing;
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\Resource\File;
18 use TYPO3\CMS\Core\Utility\CommandUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21 use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
22
23 /**
24 * Helper for creating local image previews using TYPO3s image processing classes.
25 */
26 class LocalPreviewHelper {
27 /**
28 * @var LocalImageProcessor
29 */
30 protected $processor;
31
32 /**
33 * @param LocalImageProcessor $processor
34 */
35 public function __construct(LocalImageProcessor $processor) {
36 $this->processor = $processor;
37 }
38
39 /**
40 * This method actually does the processing of files locally
41 *
42 * takes the original file (on remote storages this will be fetched from the remote server)
43 * does the IM magic on the local server by creating a temporary typo3temp/ file
44 * copies the typo3temp/ file to the processing folder of the target storage
45 * removes the typo3temp/ file
46 *
47 * The returned array has the following structure:
48 * width => 100
49 * height => 200
50 * filePath => /some/path
51 *
52 * If filePath isn't set but width and height are the original file is used as ProcessedFile
53 * with the returned width and height. This is for example useful for SVG images.
54 *
55 * @param TaskInterface $task
56 * @return array|NULL
57 */
58 public function process(TaskInterface $task) {
59 $sourceFile = $task->getSourceFile();
60
61 // Merge custom configuration with default configuration
62 $configuration = array_merge(array('width' => 64, 'height' => 64), $task->getConfiguration());
63 $configuration['width'] = MathUtility::forceIntegerInRange($configuration['width'], 1);
64 $configuration['height'] = MathUtility::forceIntegerInRange($configuration['height'], 1);
65
66 // Do not scale up if the source file has a size and the target size is larger
67 if ($sourceFile->getProperty('width') > 0 && $sourceFile->getProperty('height') > 0
68 && $configuration['width'] > $sourceFile->getProperty('width')
69 && $configuration['height'] > $sourceFile->getProperty('height')) {
70 return NULL;
71 }
72
73 return $this->generatePreviewFromFile($sourceFile, $configuration, $this->getTemporaryFilePath($task));
74 }
75
76 /**
77 * Returns the path to a temporary file for processing
78 *
79 * @param TaskInterface $task
80 * @return string
81 */
82 protected function getTemporaryFilePath(TaskInterface $task) {
83 return GeneralUtility::tempnam('preview_', '.' . $task->getTargetFileExtension());
84 }
85
86 /**
87 * Generates a preview for a file
88 *
89 * @param File $file The source file
90 * @param array $configuration Processing configuration
91 * @param string $targetFilePath Output file path
92 * @return array|NULL
93 */
94 protected function generatePreviewFromFile(File $file, array $configuration, $targetFilePath) {
95 $originalFileName = $file->getForLocalProcessing(FALSE);
96
97 // Check file extension
98 if ($file->getType() != File::FILETYPE_IMAGE &&
99 !GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $file->getExtension())) {
100 // Create a default image
101 $graphicalFunctions = GeneralUtility::makeInstance(GraphicalFunctions::class);
102 $graphicalFunctions->getTemporaryImageWithText(
103 $targetFilePath,
104 'Not imagefile!',
105 'No ext!',
106 $file->getName()
107 );
108 $result = array(
109 'filePath' => $targetFilePath,
110 );
111 } elseif ($file->getExtension() === 'svg') {
112 /** @var $gifBuilder \TYPO3\CMS\Frontend\Imaging\GifBuilder */
113 $gifBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Imaging\GifBuilder::class);
114 $gifBuilder->init();
115 $gifBuilder->absPrefix = PATH_site;
116 $info = $gifBuilder->getImageDimensions($originalFileName);
117 $newInfo = $gifBuilder->getImageScale($info, $configuration['width'], $configuration['height'], array());
118 $result = array(
119 'width' => $newInfo[0],
120 'height' => $newInfo[1],
121 'filePath' => '' // no file = use original
122 );
123 } else {
124 // Create the temporary file
125 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
126 $parameters = '-sample ' . $configuration['width'] . 'x' . $configuration['height'] . ' '
127 . CommandUtility::escapeShellArgument($originalFileName) . '[0] ' . CommandUtility::escapeShellArgument($targetFilePath);
128
129 $cmd = GeneralUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
130 CommandUtility::exec($cmd);
131
132 if (!file_exists($targetFilePath)) {
133 // Create a error gif
134 $graphicalFunctions = GeneralUtility::makeInstance(GraphicalFunctions::class);
135 $graphicalFunctions->getTemporaryImageWithText(
136 $targetFilePath,
137 'No thumb',
138 'generated!',
139 $file->getName()
140 );
141 }
142 }
143 $result = array(
144 'filePath' => $targetFilePath,
145 );
146 }
147
148 return $result;
149 }
150 }