82e1b6f458a199f822ff9286369f8aa269c99043
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Controller / Action / Tool / TestSetup.php
1 <?php
2 namespace TYPO3\CMS\Install\Controller\Action\Tool;
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\Imaging\GraphicalFunctions;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Core\Utility\StringUtility;
20 use TYPO3\CMS\Install\Controller\Action;
21
22 /**
23 * Test various system setup settings
24 */
25 class TestSetup extends Action\AbstractAction
26 {
27 /**
28 * @var string Absolute path to image folder
29 */
30 protected $imageBasePath = '';
31
32 /**
33 * Executes the tool
34 *
35 * @return string Rendered content
36 */
37 protected function executeAction()
38 {
39 $this->imageBasePath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
40
41 $actionMessages = [];
42 if (isset($this->postValues['set']['testMail'])) {
43 $actionMessages[] = $this->sendTestMail();
44 $this->view->assign('postAction', 'testMail');
45 }
46
47 if (isset($this->postValues['set']['testTrueTypeFont'])) {
48 $this->view->assign('trueTypeFontTested', true);
49 $actionMessages[] = $this->createTrueTypeFontTestImage();
50 }
51
52 if (isset($this->postValues['set']['testConvertImageFormatsToJpg'])) {
53 $this->view->assign('convertImageFormatsToJpgTested', true);
54 if ($this->isImageMagickEnabledAndConfigured()) {
55 $actionMessages[] = $this->convertImageFormatsToJpg();
56 } else {
57 $actionMessages[] = $this->imageMagickDisabledMessage();
58 }
59 }
60
61 if (isset($this->postValues['set']['testWriteGifAndPng'])) {
62 $this->view->assign('writeGifAndPngTested', true);
63 if ($this->isImageMagickEnabledAndConfigured()) {
64 $actionMessages[] = $this->writeGifAndPng();
65 } else {
66 $actionMessages[] = $this->imageMagickDisabledMessage();
67 }
68 }
69
70 if (isset($this->postValues['set']['testScalingImages'])) {
71 $this->view->assign('scalingImagesTested', true);
72 if ($this->isImageMagickEnabledAndConfigured()) {
73 $actionMessages[] = $this->scaleImages();
74 } else {
75 $actionMessages[] = $this->imageMagickDisabledMessage();
76 }
77 }
78
79 if (isset($this->postValues['set']['testCombiningImages'])) {
80 $this->view->assign('combiningImagesTested', true);
81 if ($this->isImageMagickEnabledAndConfigured()) {
82 $actionMessages[] = $this->combineImages();
83 } else {
84 $actionMessages[] = $this->imageMagickDisabledMessage();
85 }
86 }
87
88 if (isset($this->postValues['set']['testGdlib'])) {
89 $this->view->assign('gdlibTested', true);
90 $actionMessages[] = $this->gdlib();
91 }
92
93 $this->view->assign('actionMessages', $actionMessages);
94 $this->view->assign('senderEmailAddress', $this->getSenderEmailAddress());
95 $this->view->assign('imageConfiguration', $this->getImageConfiguration());
96
97 return $this->view->render();
98 }
99
100 /**
101 * Send a test mail to specified email address
102 *
103 * @return \TYPO3\CMS\Install\Status\StatusInterface
104 */
105 protected function sendTestMail()
106 {
107 if (
108 !isset($this->postValues['values']['testEmailRecipient'])
109 || !GeneralUtility::validEmail($this->postValues['values']['testEmailRecipient'])
110 ) {
111 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
112 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
113 $message->setTitle('Mail not sent');
114 $message->setMessage('Given address is not a valid email address.');
115 } else {
116 $recipient = $this->postValues['values']['testEmailRecipient'];
117 /** @var $mailMessage \TYPO3\CMS\Core\Mail\MailMessage */
118 $mailMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
119 $mailMessage
120 ->addTo($recipient)
121 ->addFrom($this->getSenderEmailAddress(), $this->getSenderEmailName())
122 ->setSubject($this->getEmailSubject())
123 ->setBody('<html><body>html test content</body></html>', 'text/html')
124 ->addPart('TEST CONTENT')
125 ->send();
126 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
127 $message->setTitle('Test mail sent');
128 $message->setMessage('Recipient: ' . $recipient);
129 }
130 return $message;
131 }
132
133 /**
134 * Get sender address from configuration
135 * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
136 * If this setting is empty fall back to 'no-reply@example.com'
137 *
138 * @return string Returns an email address
139 */
140 protected function getSenderEmailAddress()
141 {
142 return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'])
143 ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
144 : 'no-reply@example.com';
145 }
146
147 /**
148 * Gets sender name from configuration
149 * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
150 * If this setting is empty, it falls back to a default string.
151 *
152 * @return string
153 */
154 protected function getSenderEmailName()
155 {
156 return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'])
157 ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
158 : 'TYPO3 CMS install tool';
159 }
160
161 /**
162 * Gets email subject from configuration
163 * ['TYPO3_CONF_VARS']['SYS']['sitename']
164 * If this setting is empty, it falls back to a default string.
165 *
166 * @return string
167 */
168 protected function getEmailSubject()
169 {
170 $name = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'])
171 ? ' from site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"'
172 : '';
173 return 'Test TYPO3 CMS mail delivery' . $name;
174 }
175
176 /**
177 * Create true type font test image
178 *
179 * @return \TYPO3\CMS\Install\Status\StatusInterface
180 */
181 protected function createTrueTypeFontTestImage()
182 {
183 $parseTimeStart = GeneralUtility::milliseconds();
184
185 $image = @imagecreate(200, 50);
186 imagecolorallocate($image, 255, 255, 55);
187 $textColor = imagecolorallocate($image, 233, 14, 91);
188 @imagettftext(
189 $image,
190 GeneralUtility::freetypeDpiComp(20),
191 0,
192 10,
193 20,
194 $textColor,
195 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
196 'Testing true type'
197 );
198 $outputFile = PATH_site . 'typo3temp/assets/images/installTool-' . StringUtility::getUniqueId('createTrueTypeFontTestImage') . '.gif';
199 imagegif($image, $outputFile);
200
201 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
202 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\InfoStatus::class);
203 $message->setTitle('True type font');
204 $message->setMessage(
205 'If the two images below do not look the same, please check your FreeType 2 module.'
206 );
207
208 $testResults = [];
209 $testResults['ttf'] = [];
210 $testResults['ttf']['message'] = $message;
211 $testResults['ttf']['title'] = '';
212 $testResults['ttf']['outputFile'] = $outputFile;
213 $testResults['ttf']['referenceFile'] = $this->imageBasePath . 'TestReference/Font.gif';
214
215 $this->view->assign('testResults', $testResults);
216 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
217 }
218
219 /**
220 * Create jpg from various image formats using IM / GM
221 *
222 * @return \TYPO3\CMS\Install\Status\StatusInterface
223 */
224 protected function convertImageFormatsToJpg()
225 {
226 $this->setUpDatabaseConnectionMock();
227 $imageProcessor = $this->initializeImageProcessor();
228 $parseTimeStart = GeneralUtility::milliseconds();
229
230 $inputFormatsToTest = ['jpg', 'gif', 'png', 'tif', 'pdf', 'ai'];
231
232 $testResults = [];
233 foreach ($inputFormatsToTest as $formatToTest) {
234 $result = [];
235 if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $formatToTest)) {
236 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
237 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\WarningStatus::class);
238 $message->setTitle('Skipped test');
239 $message->setMessage('Handling format ' . $formatToTest . ' must be enabled in TYPO3_CONF_VARS[\'GFX\'][\'imagefile_ext\']');
240 $result['error'] = $message;
241 } else {
242 $imageProcessor->IM_commands = [];
243 $inputFile = $this->imageBasePath . 'TestInput/Test.' . $formatToTest;
244 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('read') . '-' . $formatToTest;
245 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '', '', [], true);
246 $result['title'] = 'Read ' . $formatToTest;
247 if ($imResult !== null) {
248 $result['outputFile'] = $imResult[3];
249 $result['referenceFile'] = $this->imageBasePath . 'TestReference/Read-' . $formatToTest . '.jpg';
250 $result['command'] = $imageProcessor->IM_commands;
251 } else {
252 $result['error'] = $this->imageGenerationFailedMessage();
253 }
254 }
255 $testResults[] = $result;
256 }
257
258 $this->view->assign('testResults', $testResults);
259 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
260 }
261
262 /**
263 * Write gif and png test
264 *
265 * @return \TYPO3\CMS\Install\Status\StatusInterface
266 */
267 protected function writeGifAndPng()
268 {
269 $this->setUpDatabaseConnectionMock();
270 $imageProcessor = $this->initializeImageProcessor();
271 $parseTimeStart = GeneralUtility::milliseconds();
272
273 $testResults = [
274 'gif' => [],
275 'png' => [],
276 ];
277
278 // Gif
279 $inputFile = $this->imageBasePath . 'TestInput/Test.gif';
280 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-gif');
281 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
282 if ($imResult !== null && is_file($imResult[3])) {
283 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress']) {
284 clearstatcache();
285 $previousSize = GeneralUtility::formatSize(filesize($imResult[3]));
286 $methodUsed = GraphicalFunctions::gifCompress($imResult[3], '');
287 clearstatcache();
288 $compressedSize = GeneralUtility::formatSize(filesize($imResult[3]));
289 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
290 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\InfoStatus::class);
291 $message->setTitle('Compressed gif');
292 $message->setMessage(
293 'Method used by compress: ' . $methodUsed . LF
294 . ' Previous filesize: ' . $previousSize . '. Current filesize:' . $compressedSize
295 );
296 } else {
297 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
298 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\InfoStatus::class);
299 $message->setTitle('Gif compression not enabled by [GFX][gif_compress]');
300 }
301 $testResults['gif']['message'] = $message;
302 $testResults['gif']['title'] = 'Write gif';
303 $testResults['gif']['outputFile'] = $imResult[3];
304 $testResults['gif']['referenceFile'] = $this->imageBasePath . 'TestReference/Write-gif.gif';
305 $testResults['gif']['command'] = $imageProcessor->IM_commands;
306 } else {
307 $testResults['gif']['error'] = $this->imageGenerationFailedMessage();
308 }
309
310 // Png
311 $inputFile = $this->imageBasePath . 'TestInput/Test.png';
312 $imageProcessor->IM_commands = [];
313 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-png');
314 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
315 if ($imResult !== null) {
316 $testResults['png']['title'] = 'Write png';
317 $testResults['png']['outputFile'] = $imResult[3];
318 $testResults['png']['referenceFile'] = $this->imageBasePath . 'TestReference/Write-png.png';
319 $testResults['png']['command'] = $imageProcessor->IM_commands;
320 } else {
321 $testResults['png']['error'] = $this->imageGenerationFailedMessage();
322 }
323
324 $this->view->assign('testResults', $testResults);
325 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
326 }
327
328 /**
329 * Write gif and png test
330 *
331 * @return \TYPO3\CMS\Install\Status\StatusInterface
332 */
333 protected function scaleImages()
334 {
335 $this->setUpDatabaseConnectionMock();
336 $imageProcessor = $this->initializeImageProcessor();
337 $parseTimeStart = GeneralUtility::milliseconds();
338
339 $testResults = [
340 'gif-to-gif' => [],
341 'png-to-png' => [],
342 'gif-to-jpg' => [],
343 ];
344
345 $imageProcessor->IM_commands = [];
346 $inputFile = $this->imageBasePath . 'TestInput/Transparent.gif';
347 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-gif');
348 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
349 if ($imResult !== null) {
350 $testResults['gif-to-gif']['title'] = 'gif to gif';
351 $testResults['gif-to-gif']['outputFile'] = $imResult[3];
352 $testResults['gif-to-gif']['referenceFile'] = $this->imageBasePath . 'TestReference/Scale-gif.gif';
353 $testResults['gif-to-gif']['command'] = $imageProcessor->IM_commands;
354 } else {
355 $testResults['gif-to-gif']['error'] = $this->imageGenerationFailedMessage();
356 }
357
358 $imageProcessor->IM_commands = [];
359 $inputFile = $this->imageBasePath . 'TestInput/Transparent.png';
360 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-png');
361 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
362 if ($imResult !== null) {
363 $testResults['png-to-png']['title'] = 'png to png';
364 $testResults['png-to-png']['outputFile'] = $imResult[3];
365 $testResults['png-to-png']['referenceFile'] = $this->imageBasePath . 'TestReference/Scale-png.png';
366 $testResults['png-to-png']['command'] = $imageProcessor->IM_commands;
367 } else {
368 $testResults['png-to-png']['error'] = $this->imageGenerationFailedMessage();
369 }
370
371 $imageProcessor->IM_commands = [];
372 $inputFile = $this->imageBasePath . 'TestInput/Transparent.gif';
373 $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-jpg');
374 $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '-opaque white -background white -flatten', '', [], true);
375 if ($imResult !== null) {
376 $testResults['gif-to-jpg']['title'] = 'gif to jpg';
377 $testResults['gif-to-jpg']['outputFile'] = $imResult[3];
378 $testResults['gif-to-jpg']['referenceFile'] = $this->imageBasePath . 'TestReference/Scale-jpg.jpg';
379 $testResults['gif-to-jpg']['command'] = $imageProcessor->IM_commands;
380 } else {
381 $testResults['gif-to-jpg']['error'] = $this->imageGenerationFailedMessage();
382 }
383
384 $this->view->assign('testResults', $testResults);
385 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
386 }
387
388 /**
389 * Combine multiple images into one test
390 *
391 * @return \TYPO3\CMS\Install\Status\StatusInterface
392 */
393 protected function combineImages()
394 {
395 $this->setUpDatabaseConnectionMock();
396 $imageProcessor = $this->initializeImageProcessor();
397 $parseTimeStart = GeneralUtility::milliseconds();
398
399 $testResults = [
400 'combine1' => [],
401 'combine2' => [],
402 ];
403
404 $inputFile = $this->imageBasePath . 'TestInput/BackgroundOrange.gif';
405 $overlayFile = $this->imageBasePath . 'TestInput/Test.jpg';
406 $maskFile = $this->imageBasePath . 'TestInput/MaskBlackWhite.gif';
407 $resultFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix
408 . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine1') . '.jpg';
409 $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
410 $result = $imageProcessor->getImageDimensions($resultFile);
411 if ($result) {
412 $testResults['combine1']['title'] = 'Combine using a GIF mask with only black and white';
413 $testResults['combine1']['outputFile'] = $result[3];
414 $testResults['combine1']['referenceFile'] = $this->imageBasePath . 'TestReference/Combine-1.jpg';
415 $testResults['combine1']['command'] = $imageProcessor->IM_commands;
416 } else {
417 $testResults['combine1']['error'] = $this->imageGenerationFailedMessage();
418 }
419
420 $imageProcessor->IM_commands = [];
421 $inputFile = $this->imageBasePath . 'TestInput/BackgroundCombine.jpg';
422 $overlayFile = $this->imageBasePath . 'TestInput/Test.jpg';
423 $maskFile = $this->imageBasePath . 'TestInput/MaskCombine.jpg';
424 $resultFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix
425 . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine2') . '.jpg';
426 $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
427 $result = $imageProcessor->getImageDimensions($resultFile);
428 if ($result) {
429 $testResults['combine2']['title'] = 'Combine using a JPG mask with graylevels';
430 $testResults['combine2']['outputFile'] = $result[3];
431 $testResults['combine2']['referenceFile'] = $this->imageBasePath . 'TestReference/Combine-2.jpg';
432 $testResults['combine2']['command'] = $imageProcessor->IM_commands;
433 } else {
434 $testResults['combine2']['error'] = $this->imageGenerationFailedMessage();
435 }
436
437 $this->view->assign('testResults', $testResults);
438 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
439 }
440
441 /**
442 * Test gdlib functions
443 *
444 * @return \TYPO3\CMS\Install\Status\StatusInterface
445 */
446 protected function gdlib()
447 {
448 $this->setUpDatabaseConnectionMock();
449 $imageProcessor = $this->initializeImageProcessor();
450 $parseTimeStart = GeneralUtility::milliseconds();
451 $gifOrPng = $imageProcessor->gifExtension;
452 $testResults = [];
453
454 // GD with simple box
455 $imageProcessor->IM_commands = [];
456 $image = imagecreatetruecolor(300, 225);
457 $backgroundColor = imagecolorallocate($image, 0, 0, 0);
458 imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
459 $workArea = [0, 0, 300, 225];
460 $conf = [
461 'dimensions' => '10,50,280,50',
462 'color' => 'olive',
463 ];
464 $imageProcessor->makeBox($image, $conf, $workArea);
465 $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdSimple') . '.' . $gifOrPng;
466 $imageProcessor->ImageWrite($image, $outputFile);
467 $result = $imageProcessor->getImageDimensions($outputFile);
468 $testResults['simple'] = [];
469 $testResults['simple']['title'] = 'Create simple image';
470 $testResults['simple']['outputFile'] = $result[3];
471 $testResults['simple']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-simple.' . $gifOrPng;
472 $testResults['simple']['command'] = $imageProcessor->IM_commands;
473
474 // GD from image with box
475 $imageProcessor->IM_commands = [];
476 $inputFile = $this->imageBasePath . 'TestInput/Test.' . $gifOrPng;
477 $image = $imageProcessor->imageCreateFromFile($inputFile);
478
479 $workArea = [0, 0, 400, 300];
480 $conf = [
481 'dimensions' => '10,50,380,50',
482 'color' => 'olive',
483 ];
484 $imageProcessor->makeBox($image, $conf, $workArea);
485 $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdBox') . '.' . $gifOrPng;
486 $imageProcessor->ImageWrite($image, $outputFile);
487 $result = $imageProcessor->getImageDimensions($outputFile);
488 $testResults['box'] = [];
489 $testResults['box']['title'] = 'Create image from file';
490 $testResults['box']['outputFile'] = $result[3];
491 $testResults['box']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-box.' . $gifOrPng;
492 $testResults['box']['command'] = $imageProcessor->IM_commands;
493
494 // GD with text
495 $imageProcessor->IM_commands = [];
496 $image = imagecreatetruecolor(300, 225);
497 $backgroundColor = imagecolorallocate($image, 128, 128, 150);
498 imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
499 $workArea = [0, 0, 300, 225];
500 $conf = [
501 'iterations' => 1,
502 'angle' => 0,
503 'antiAlias' => 1,
504 'text' => 'HELLO WORLD',
505 'fontColor' => '#003366',
506 'fontSize' => 30,
507 'fontFile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
508 'offset' => '30,80',
509 ];
510 $conf['BBOX'] = $imageProcessor->calcBBox($conf);
511 $imageProcessor->makeText($image, $conf, $workArea);
512 $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
513 $imageProcessor->ImageWrite($image, $outputFile);
514 $result = $imageProcessor->getImageDimensions($outputFile);
515 $testResults['text'] = [];
516 $testResults['text']['title'] = 'Render text with TrueType font';
517 $testResults['text']['outputFile'] = $result[3];
518 $testResults['text']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-text.' . $gifOrPng;
519 $testResults['text']['command'] = $imageProcessor->IM_commands;
520
521 // GD with text, niceText
522 $testResults['niceText'] = [];
523 if ($this->isImageMagickEnabledAndConfigured()) {
524 // Warning: Re-uses $conf from above!
525 $conf['offset'] = '30,120';
526 $conf['niceText'] = 1;
527 $imageProcessor->makeText($image, $conf, $workArea);
528 $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
529 $imageProcessor->ImageWrite($image, $outputFile);
530 $result = $imageProcessor->getImageDimensions($outputFile);
531 $testResults['niceText']['title'] = 'Render text with TrueType font using \'niceText\' option';
532 $testResults['niceText']['outputFile'] = $result[3];
533 $testResults['niceText']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-niceText.' . $gifOrPng;
534 $testResults['niceText']['command'] = $imageProcessor->IM_commands;
535 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
536 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\InfoStatus::class);
537 $message->setTitle('Note on \'niceText\'');
538 $message->setMessage(
539 '\'niceText\' is a concept that tries to improve the antialiasing of the rendered type by'
540 . ' actually rendering the textstring in double size on a black/white mask, downscaling the mask'
541 . ' and masking the text onto the image through this mask. This involves'
542 . ' ImageMagick \'combine\'/\'composite\' and \'convert\'.'
543 );
544 $testResults['niceText']['message'] = $message;
545 } else {
546 $result['niceText']['error'] = $this->imageGenerationFailedMessage();
547 }
548
549 // GD with text, niceText, shadow
550 $testResults['shadow'] = [];
551 if ($this->isImageMagickEnabledAndConfigured()) {
552 // Warning: Re-uses $conf from above!
553 $conf['offset'] = '30,160';
554 $conf['niceText'] = 1;
555 $conf['shadow.'] = [
556 'offset' => '2,2',
557 'blur' => $imageProcessor->V5_EFFECTS ? '20' : '90',
558 'opacity' => '50',
559 'color' => 'black'
560 ];
561 // Warning: Re-uses $image from above!
562 $imageProcessor->makeShadow($image, $conf['shadow.'], $workArea, $conf);
563 $imageProcessor->makeText($image, $conf, $workArea);
564 $outputFile = $imageProcessor->tempPath . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('GDwithText-niceText-shadow') . '.' . $gifOrPng;
565 $imageProcessor->ImageWrite($image, $outputFile);
566 $result = $imageProcessor->getImageDimensions($outputFile);
567 $testResults['shadow']['title'] = 'Render \'niceText\' with a shadow under';
568 $testResults['shadow']['outputFile'] = $result[3];
569 $testResults['shadow']['referenceFile'] = $this->imageBasePath . 'TestReference/Gdlib-shadow.' . $gifOrPng;
570 $testResults['shadow']['command'] = $imageProcessor->IM_commands;
571 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
572 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\InfoStatus::class);
573 $message->setTitle('Note on \'shadow\'');
574 $message->setMessage(
575 'This test makes sense only if the above test had a correct output. But if so, you may not see'
576 . ' a soft dropshadow from the third text string as you should. In that case you are most likely'
577 . ' using ImageMagick 5 and should set the flag TYPO3_CONF_VARS[GFX][processor_effects].'
578 );
579 $testResults['shadow']['message'] = $message;
580 } else {
581 $result['shadow']['error'] = $this->imageGenerationFailedMessage();
582 }
583
584 $this->view->assign('testResults', $testResults);
585 return $this->imageTestDoneMessage(GeneralUtility::milliseconds() - $parseTimeStart);
586 }
587
588 /**
589 * Create a 'image test was done' message
590 *
591 * @param int $parseTime Parse time
592 * @return \TYPO3\CMS\Install\Status\StatusInterface
593 */
594 protected function imageTestDoneMessage($parseTime = 0)
595 {
596 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
597 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
598 $message->setTitle('Executed image tests');
599 $message->setMessage('Parse time: ' . $parseTime . ' ms');
600 return $message;
601 }
602
603 /**
604 * Create a 'imageMagick disabled' message
605 *
606 * @return \TYPO3\CMS\Install\Status\StatusInterface
607 */
608 protected function imageMagickDisabledMessage()
609 {
610 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
611 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
612 $message->setTitle('Tests not executed');
613 $message->setMessage('ImageMagick / GraphicsMagick handling is disabled or not configured correctly.');
614 return $message;
615 }
616
617 /**
618 * Create a 'image generation failed' message
619 *
620 * @return \TYPO3\CMS\Install\Status\StatusInterface
621 */
622 protected function imageGenerationFailedMessage()
623 {
624 /** @var \TYPO3\CMS\Install\Status\StatusInterface $message */
625 $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
626 $message->setTitle('Image generation failed');
627 $message->setMessage(
628 'ImageMagick / GraphicsMagick handling is enabled, but the execute'
629 . ' command returned an error. Please check your settings, especially'
630 . ' [\'GFX\'][\'processor_path\'] and [\'GFX\'][\'processor_path_lzw\'] and ensure Ghostscript is installed on your server.'
631 );
632 return $message;
633 }
634
635 /**
636 * Gather image configuration overview
637 *
638 * @return array Result array
639 */
640 protected function getImageConfiguration()
641 {
642 $result = [];
643 $result['processor'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor'] === 'GraphicsMagick' ? 'GraphicsMagick' : 'ImageMagick';
644 $result['processorEnabled'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'];
645 $result['processorPath'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'];
646 $result['processorVersion'] = $this->determineImageMagickVersion();
647 $result['processorEffects'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_effects'];
648 $result['gdlibEnabled'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
649 $result['gdlibPng'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'];
650 $result['fileFormats'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
651 return $result;
652 }
653
654 /**
655 * Initialize image processor
656 *
657 * @return GraphicalFunctions Initialized image processor
658 */
659 protected function initializeImageProcessor()
660 {
661 /** @var GraphicalFunctions $imageProcessor */
662 $imageProcessor = GeneralUtility::makeInstance(GraphicalFunctions::class);
663 $imageProcessor->init();
664 $imageProcessor->tempPath = PATH_site . 'typo3temp/';
665 $imageProcessor->dontCheckForExistingTempFile = 1;
666 $imageProcessor->filenamePrefix = 'installTool-';
667 $imageProcessor->dontCompress = 1;
668 $imageProcessor->alternativeOutputKey = 'typo3InstallTest';
669 $imageProcessor->noFramePrepended = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_allowFrameSelection'];
670 return $imageProcessor;
671 }
672
673 /**
674 * Find out if ImageMagick or GraphicsMagick is enabled and set up
675 *
676 * @return bool TRUE if enabled and path is set
677 */
678 protected function isImageMagickEnabledAndConfigured()
679 {
680 $enabled = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'];
681 $path = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'];
682 return $enabled && $path;
683 }
684
685 /**
686 * Determine ImageMagick / GraphicsMagick version
687 *
688 * @return string Version
689 */
690 protected function determineImageMagickVersion()
691 {
692 $command = \TYPO3\CMS\Core\Utility\CommandUtility::imageMagickCommand('identify', '-version');
693 \TYPO3\CMS\Core\Utility\CommandUtility::exec($command, $result);
694 $string = $result[0];
695 list(, $version) = explode('Magick', $string);
696 list($version) = explode(' ', trim($version));
697 return trim($version);
698 }
699
700 /**
701 * Instantiate a dummy instance for $GLOBALS['TYPO3_DB'] to
702 * prevent real database calls
703 *
704 * @return void
705 */
706 protected function setUpDatabaseConnectionMock()
707 {
708 $database = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Database\DatabaseConnectionMock::class);
709 $GLOBALS['TYPO3_DB'] = $database;
710 }
711 }