Passed
Push — master ( 8eb464...bbd7a3 )
by
unknown
13:15
created

imageProcessingJpgToWebpAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
c 0
b 0
f 0
dl 0
loc 26
rs 9.6333
cc 3
nc 3
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Install\Controller;
19
20
use Psr\Http\Message\ResponseInterface;
21
use Psr\Http\Message\ServerRequestInterface;
22
use Symfony\Component\Mime\Address;
23
use Symfony\Component\Mime\Exception\RfcComplianceException;
24
use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
25
use TYPO3\CMS\Core\Core\Environment;
26
use TYPO3\CMS\Core\Database\ConnectionPool;
27
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
28
use TYPO3\CMS\Core\FormProtection\InstallToolFormProtection;
29
use TYPO3\CMS\Core\Http\JsonResponse;
30
use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
31
use TYPO3\CMS\Core\Mail\FluidEmail;
32
use TYPO3\CMS\Core\Mail\Mailer;
33
use TYPO3\CMS\Core\Messaging\FlashMessage;
34
use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
35
use TYPO3\CMS\Core\Utility\CommandUtility;
36
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
use TYPO3\CMS\Core\Utility\MathUtility;
39
use TYPO3\CMS\Core\Utility\StringUtility;
40
use TYPO3\CMS\Install\FolderStructure\DefaultFactory;
41
use TYPO3\CMS\Install\FolderStructure\DefaultPermissionsCheck;
42
use TYPO3\CMS\Install\Service\LateBootService;
43
use TYPO3\CMS\Install\SystemEnvironment\Check;
44
use TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck;
45
use TYPO3\CMS\Install\SystemEnvironment\ServerResponse\ServerResponseCheck;
46
use TYPO3\CMS\Install\SystemEnvironment\SetupCheck;
47
48
/**
49
 * Environment controller
50
 * @internal This class is a specific controller implementation and is not considered part of the Public TYPO3 API.
51
 */
52
class EnvironmentController extends AbstractController
53
{
54
    private const IMAGE_FILE_EXT = ['gif', 'jpg', 'png', 'tif', 'ai', 'pdf', 'webp'];
55
56
    /**
57
     * @var LateBootService
58
     */
59
    private $lateBootService;
60
61
    public function __construct(
62
        LateBootService $lateBootService
63
    ) {
64
        $this->lateBootService = $lateBootService;
65
    }
66
67
    /**
68
     * Main "show the cards" view
69
     *
70
     * @param ServerRequestInterface $request
71
     * @return ResponseInterface
72
     */
73
    public function cardsAction(ServerRequestInterface $request): ResponseInterface
74
    {
75
        $view = $this->initializeStandaloneView($request, 'Environment/Cards.html');
76
        return new JsonResponse([
77
            'success' => true,
78
            'html' => $view->render(),
79
        ]);
80
    }
81
82
    /**
83
     * System Information Get Data action
84
     *
85
     * @param ServerRequestInterface $request
86
     * @return ResponseInterface
87
     */
88
    public function systemInformationGetDataAction(ServerRequestInterface $request): ResponseInterface
89
    {
90
        $view = $this->initializeStandaloneView($request, 'Environment/SystemInformation.html');
91
        $view->assignMultiple([
92
            'systemInformationCgiDetected' => Environment::isRunningOnCgiServer(),
93
            'systemInformationDatabaseConnections' => $this->getDatabaseConnectionInformation(),
94
            'systemInformationOperatingSystem' => Environment::isWindows() ? 'Windows' : 'Unix',
95
            'systemInformationApplicationContext' => $this->getApplicationContextInformation(),
96
            'phpVersion' => PHP_VERSION,
97
        ]);
98
        return new JsonResponse([
99
            'success' => true,
100
            'html' => $view->render(),
101
        ]);
102
    }
103
104
    /**
105
     * System Information Get Data action
106
     *
107
     * @param ServerRequestInterface $request
108
     * @return ResponseInterface
109
     */
110
    public function phpInfoGetDataAction(ServerRequestInterface $request): ResponseInterface
111
    {
112
        $view = $this->initializeStandaloneView($request, 'Environment/PhpInfo.html');
113
        return new JsonResponse([
114
            'success' => true,
115
            'html' => $view->render(),
116
        ]);
117
    }
118
119
    /**
120
     * Get environment status
121
     *
122
     * @param ServerRequestInterface $request
123
     * @return ResponseInterface
124
     */
125
    public function environmentCheckGetStatusAction(ServerRequestInterface $request): ResponseInterface
126
    {
127
        $view = $this->initializeStandaloneView($request, 'Environment/EnvironmentCheck.html');
128
        $messageQueue = new FlashMessageQueue('install');
129
        $checkMessages = (new Check())->getStatus();
130
        foreach ($checkMessages as $message) {
131
            $messageQueue->enqueue($message);
132
        }
133
        $setupMessages = (new SetupCheck())->getStatus();
134
        foreach ($setupMessages as $message) {
135
            $messageQueue->enqueue($message);
136
        }
137
        $databaseMessages = (new DatabaseCheck())->getStatus();
138
        foreach ($databaseMessages as $message) {
139
            $messageQueue->enqueue($message);
140
        }
141
        $serverResponseMessages = (new ServerResponseCheck(false))->getStatus();
142
        foreach ($serverResponseMessages as $message) {
143
            $messageQueue->enqueue($message);
144
        }
145
        return new JsonResponse([
146
            'success' => true,
147
            'status' => [
148
                'error' => $messageQueue->getAllMessages(FlashMessage::ERROR),
149
                'warning' => $messageQueue->getAllMessages(FlashMessage::WARNING),
150
                'ok' => $messageQueue->getAllMessages(FlashMessage::OK),
151
                'information' => $messageQueue->getAllMessages(FlashMessage::INFO),
152
                'notice' => $messageQueue->getAllMessages(FlashMessage::NOTICE),
153
            ],
154
            'html' => $view->render(),
155
            'buttons' => [
156
                [
157
                    'btnClass' => 'btn-default t3js-environmentCheck-execute',
158
                    'text' => 'Run tests again',
159
                ],
160
            ],
161
        ]);
162
    }
163
164
    /**
165
     * Get folder structure status
166
     *
167
     * @param ServerRequestInterface $request
168
     * @return ResponseInterface
169
     */
170
    public function folderStructureGetStatusAction(ServerRequestInterface $request): ResponseInterface
171
    {
172
        $view = $this->initializeStandaloneView($request, 'Environment/FolderStructure.html');
173
        $folderStructureFactory = GeneralUtility::makeInstance(DefaultFactory::class);
174
        $structureFacade = $folderStructureFactory->getStructure();
175
176
        $structureMessages = $structureFacade->getStatus();
177
        $errorQueue = new FlashMessageQueue('install');
178
        $okQueue = new FlashMessageQueue('install');
179
        foreach ($structureMessages as $message) {
180
            if ($message->getSeverity() === FlashMessage::ERROR
181
                || $message->getSeverity() === FlashMessage::WARNING
182
            ) {
183
                $errorQueue->enqueue($message);
184
            } else {
185
                $okQueue->enqueue($message);
186
            }
187
        }
188
189
        $permissionCheck = GeneralUtility::makeInstance(DefaultPermissionsCheck::class);
190
191
        $view->assign('publicPath', Environment::getPublicPath());
192
193
        $buttons = [];
194
        if ($errorQueue->count() > 0) {
195
            $buttons[] = [
196
                'btnClass' => 'btn-default t3js-folderStructure-errors-fix',
197
                'text' => 'Try to fix file and folder permissions',
198
            ];
199
        }
200
201
        return new JsonResponse([
202
            'success' => true,
203
            'errorStatus' => $errorQueue,
204
            'okStatus' => $okQueue,
205
            'folderStructureFilePermissionStatus' => $permissionCheck->getMaskStatus('fileCreateMask'),
206
            'folderStructureDirectoryPermissionStatus' => $permissionCheck->getMaskStatus('folderCreateMask'),
207
            'html' => $view->render(),
208
            'buttons' => $buttons,
209
        ]);
210
    }
211
212
    /**
213
     * Try to fix folder structure errors
214
     *
215
     * @return ResponseInterface
216
     */
217
    public function folderStructureFixAction(): ResponseInterface
218
    {
219
        $folderStructureFactory = GeneralUtility::makeInstance(DefaultFactory::class);
220
        $structureFacade = $folderStructureFactory->getStructure();
221
        $fixedStatusObjects = $structureFacade->fix();
222
        return new JsonResponse([
223
            'success' => true,
224
            'fixedStatus' => $fixedStatusObjects,
225
        ]);
226
    }
227
228
    /**
229
     * System Information Get Data action
230
     *
231
     * @param ServerRequestInterface $request
232
     * @return ResponseInterface
233
     */
234
    public function mailTestGetDataAction(ServerRequestInterface $request): ResponseInterface
235
    {
236
        $view = $this->initializeStandaloneView($request, 'Environment/MailTest.html');
237
        $formProtection = FormProtectionFactory::get(InstallToolFormProtection::class);
238
        $view->assignMultiple([
239
            'mailTestToken' => $formProtection->generateToken('installTool', 'mailTest'),
240
            'mailTestSenderAddress' => $this->getSenderEmailAddress(),
241
        ]);
242
        return new JsonResponse([
243
            'success' => true,
244
            'html' => $view->render(),
245
            'buttons' => [
246
                [
247
                    'btnClass' => 'btn-default t3js-mailTest-execute',
248
                    'text' => 'Send test mail',
249
                ],
250
            ],
251
        ]);
252
    }
253
254
    /**
255
     *  Send a test mail
256
     *
257
     * @param ServerRequestInterface $request
258
     * @return ResponseInterface
259
     */
260
    public function mailTestAction(ServerRequestInterface $request): ResponseInterface
261
    {
262
        $container = $this->lateBootService->getContainer();
263
        $backup = $this->lateBootService->makeCurrent($container);
264
        $messages = new FlashMessageQueue('install');
265
        $recipient = $request->getParsedBody()['install']['email'];
266
        if (empty($recipient) || !GeneralUtility::validEmail($recipient)) {
267
            $messages->enqueue(new FlashMessage(
268
                'Given address is not a valid email address.',
269
                'Mail not sent',
270
                FlashMessage::ERROR
271
            ));
272
        } else {
273
            try {
274
                $variables = [
275
                    'headline' => 'TYPO3 Test Mail',
276
                    'introduction' => 'Hey TYPO3 Administrator',
277
                    'content' => 'Seems like your favorite TYPO3 installation can send out emails!'
278
                ];
279
                $mailMessage = GeneralUtility::makeInstance(FluidEmail::class);
280
                $mailMessage
281
                    ->to($recipient)
282
                    ->from(new Address($this->getSenderEmailAddress(), $this->getSenderEmailName()))
283
                    ->subject($this->getEmailSubject())
284
                    ->setRequest($request)
285
                    ->assignMultiple($variables);
286
287
                GeneralUtility::makeInstance(Mailer::class)->send($mailMessage);
288
                $messages->enqueue(new FlashMessage(
289
                    'Recipient: ' . $recipient,
290
                    'Test mail sent'
291
                ));
292
            } catch (RfcComplianceException $exception) {
293
                $messages->enqueue(new FlashMessage(
294
                    'Please verify $GLOBALS[\'TYPO3_CONF_VARS\'][\'MAIL\'][\'defaultMailFromAddress\'] is a valid mail address.'
295
                    . ' Error message: ' . $exception->getMessage(),
296
                    'RFC compliance problem',
297
                    FlashMessage::ERROR
298
                ));
299
            } catch (\Throwable $throwable) {
300
                $messages->enqueue(new FlashMessage(
301
                    'Please verify $GLOBALS[\'TYPO3_CONF_VARS\'][\'MAIL\'][*] settings are valid.'
302
                    . ' Error message: ' . $throwable->getMessage(),
303
                    'Could not deliver mail',
304
                    FlashMessage::ERROR
305
                ));
306
            }
307
        }
308
        $this->lateBootService->makeCurrent(null, $backup);
309
        return new JsonResponse([
310
            'success' => true,
311
            'status' => $messages,
312
        ]);
313
    }
314
315
    /**
316
     * System Information Get Data action
317
     *
318
     * @param ServerRequestInterface $request
319
     * @return ResponseInterface
320
     */
321
    public function imageProcessingGetDataAction(ServerRequestInterface $request): ResponseInterface
322
    {
323
        $view = $this->initializeStandaloneView($request, 'Environment/ImageProcessing.html');
324
        $view->assignMultiple([
325
            'imageProcessingProcessor' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor'] === 'GraphicsMagick' ? 'GraphicsMagick' : 'ImageMagick',
326
            'imageProcessingEnabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'],
327
            'imageProcessingPath' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'],
328
            'imageProcessingVersion' => $this->determineImageMagickVersion(),
329
            'imageProcessingEffects' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_effects'],
330
            'imageProcessingGdlibEnabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'],
331
            'imageProcessingGdlibPng' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'],
332
            'imageProcessingFileFormats' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
333
        ]);
334
        return new JsonResponse([
335
            'success' => true,
336
            'html' => $view->render(),
337
            'buttons' => [
338
                [
339
                    'btnClass' => 'btn-default disabled t3js-imageProcessing-execute',
340
                    'text' => 'Run image tests again',
341
                ],
342
            ],
343
        ]);
344
    }
345
346
    /**
347
     * Create true type font test image
348
     *
349
     * @return ResponseInterface
350
     */
351
    public function imageProcessingTrueTypeAction(): ResponseInterface
352
    {
353
        $image = @imagecreate(200, 50);
354
        imagecolorallocate($image, 255, 255, 55);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagecolorallocate() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

354
        imagecolorallocate(/** @scrutinizer ignore-type */ $image, 255, 255, 55);
Loading history...
355
        $textColor = imagecolorallocate($image, 233, 14, 91);
356
        @imagettftext(
357
            $image,
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagettftext() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

357
            /** @scrutinizer ignore-type */ $image,
Loading history...
358
            20 / 96.0 * 72, // As in  compensateFontSizeBasedOnFreetypeDpi
359
            0,
360
            10,
361
            20,
362
            $textColor,
363
            ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
364
            'Testing true type'
365
        );
366
        $outputFile = Environment::getPublicPath() . '/typo3temp/assets/images/installTool-' . StringUtility::getUniqueId('createTrueTypeFontTestImage') . '.gif';
367
        imagegif($image, $outputFile);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagegif() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

367
        imagegif(/** @scrutinizer ignore-type */ $image, $outputFile);
Loading history...
368
        $fileExists = file_exists($outputFile);
369
        if ($fileExists) {
370
            GeneralUtility::fixPermissions($outputFile);
371
        }
372
        return $this->getImageTestResponse([
373
            'fileExists' => $fileExists,
374
            'outputFile' => $outputFile,
375
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Font.gif',
376
        ]);
377
    }
378
379
    /**
380
     * Convert to jpg from jpg
381
     *
382
     * @return ResponseInterface
383
     */
384
    public function imageProcessingReadJpgAction(): ResponseInterface
385
    {
386
        return $this->convertImageFormatsToJpg('jpg');
387
    }
388
389
    /**
390
     * Convert to jpg from gif
391
     *
392
     * @return ResponseInterface
393
     */
394
    public function imageProcessingReadGifAction(): ResponseInterface
395
    {
396
        return $this->convertImageFormatsToJpg('gif');
397
    }
398
399
    /**
400
     * Convert to jpg from png
401
     *
402
     * @return ResponseInterface
403
     */
404
    public function imageProcessingReadPngAction(): ResponseInterface
405
    {
406
        return $this->convertImageFormatsToJpg('png');
407
    }
408
409
    /**
410
     * Convert to jpg from tif
411
     *
412
     * @return ResponseInterface
413
     */
414
    public function imageProcessingReadTifAction(): ResponseInterface
415
    {
416
        return $this->convertImageFormatsToJpg('tif');
417
    }
418
419
    /**
420
     * Convert to jpg from pdf
421
     *
422
     * @return ResponseInterface
423
     */
424
    public function imageProcessingReadPdfAction(): ResponseInterface
425
    {
426
        return $this->convertImageFormatsToJpg('pdf');
427
    }
428
429
    /**
430
     * Convert to jpg from ai
431
     *
432
     * @return ResponseInterface
433
     */
434
    public function imageProcessingReadAiAction(): ResponseInterface
435
    {
436
        return $this->convertImageFormatsToJpg('ai');
437
    }
438
439
    /**
440
     * Writing gif test
441
     *
442
     * @return ResponseInterface
443
     */
444
    public function imageProcessingWriteGifAction(): ResponseInterface
445
    {
446
        if (!$this->isImageMagickEnabledAndConfigured()) {
447
            return new JsonResponse([
448
                'status' => [$this->imageMagickDisabledMessage()],
449
            ]);
450
        }
451
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
452
        $inputFile = $imageBasePath . 'TestInput/Test.gif';
453
        $imageProcessor = $this->initializeImageProcessor();
454
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-gif');
455
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
456
        $messages = new FlashMessageQueue('install');
457
        if ($imResult !== null && is_file($imResult[3])) {
458
            if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress']) {
459
                clearstatcache();
460
                $previousSize = GeneralUtility::formatSize((int)filesize($imResult[3]));
461
                $methodUsed = GraphicalFunctions::gifCompress($imResult[3], '');
462
                clearstatcache();
463
                $compressedSize = GeneralUtility::formatSize((int)filesize($imResult[3]));
464
                $messages->enqueue(new FlashMessage(
465
                    'Method used by compress: ' . $methodUsed . LF
466
                    . ' Previous filesize: ' . $previousSize . '. Current filesize:' . $compressedSize,
467
                    'Compressed gif',
468
                    FlashMessage::INFO
469
                ));
470
            } else {
471
                $messages->enqueue(new FlashMessage(
472
                    '',
473
                    'Gif compression not enabled by [GFX][gif_compress]',
474
                    FlashMessage::INFO
475
                ));
476
            }
477
            $result = [
478
                'status' => $messages,
479
                'fileExists' => true,
480
                'outputFile' => $imResult[3],
481
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Write-gif.gif',
482
                'command' => $imageProcessor->IM_commands,
483
            ];
484
        } else {
485
            $result = [
486
                'status' => [$this->imageGenerationFailedMessage()],
487
                'command' => $imageProcessor->IM_commands,
488
            ];
489
        }
490
        return $this->getImageTestResponse($result);
491
    }
492
493
    /**
494
     * Writing png test
495
     *
496
     * @return ResponseInterface
497
     */
498
    public function imageProcessingWritePngAction(): ResponseInterface
499
    {
500
        if (!$this->isImageMagickEnabledAndConfigured()) {
501
            return new JsonResponse([
502
                'status' => [$this->imageMagickDisabledMessage()],
503
            ]);
504
        }
505
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
506
        $inputFile = $imageBasePath . 'TestInput/Test.png';
507
        $imageProcessor = $this->initializeImageProcessor();
508
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-png');
509
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
510
        if ($imResult !== null && is_file($imResult[3])) {
511
            $result = [
512
                'fileExists' => true,
513
                'outputFile' => $imResult[3],
514
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Write-png.png',
515
                'command' => $imageProcessor->IM_commands,
516
            ];
517
        } else {
518
            $result = [
519
                'status' => [$this->imageGenerationFailedMessage()],
520
                'command' => $imageProcessor->IM_commands,
521
            ];
522
        }
523
        return $this->getImageTestResponse($result);
524
    }
525
    /**
526
     * Writing webp test
527
     *
528
     * @return ResponseInterface
529
     */
530
    public function imageProcessingWriteWebpAction(): ResponseInterface
531
    {
532
        if (!$this->isImageMagickEnabledAndConfigured()) {
533
            return new JsonResponse([
534
                'status' => [$this->imageMagickDisabledMessage()],
535
            ]);
536
        }
537
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
538
        $inputFile = $imageBasePath . 'TestInput/Test.webp';
539
        $imageProcessor = $this->initializeImageProcessor();
540
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-webp');
541
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'webp', '300', '', '', '', [], true);
542
        if ($imResult !== null && is_file($imResult[3])) {
543
            $result = [
544
                'fileExists' => true,
545
                'outputFile' => $imResult[3],
546
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Write-webp.webp',
547
                'command' => $imageProcessor->IM_commands,
548
            ];
549
        } else {
550
            $result = [
551
                'status' => [$this->imageGenerationFailedMessage()],
552
                'command' => $imageProcessor->IM_commands,
553
            ];
554
        }
555
        return $this->getImageTestResponse($result);
556
    }
557
558
    /**
559
     * Scaling transparent files - gif to gif
560
     *
561
     * @return ResponseInterface
562
     */
563
    public function imageProcessingGifToGifAction(): ResponseInterface
564
    {
565
        if (!$this->isImageMagickEnabledAndConfigured()) {
566
            return new JsonResponse([
567
                'status' => [$this->imageMagickDisabledMessage()],
568
            ]);
569
        }
570
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
571
        $imageProcessor = $this->initializeImageProcessor();
572
        $inputFile = $imageBasePath . 'TestInput/Transparent.gif';
573
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-gif');
574
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
575
        if ($imResult !== null && file_exists($imResult[3])) {
576
            $result = [
577
                'fileExists' => true,
578
                'outputFile' => $imResult[3],
579
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-gif.gif',
580
                'command' => $imageProcessor->IM_commands,
581
            ];
582
        } else {
583
            $result = [
584
                'status' => [$this->imageGenerationFailedMessage()],
585
                'command' => $imageProcessor->IM_commands,
586
            ];
587
        }
588
        return $this->getImageTestResponse($result);
589
    }
590
591
    /**
592
     * Scaling transparent files - png to png
593
     *
594
     * @return ResponseInterface
595
     */
596
    public function imageProcessingPngToPngAction(): ResponseInterface
597
    {
598
        if (!$this->isImageMagickEnabledAndConfigured()) {
599
            return new JsonResponse([
600
                'status' => [$this->imageMagickDisabledMessage()],
601
            ]);
602
        }
603
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
604
        $imageProcessor = $this->initializeImageProcessor();
605
        $inputFile = $imageBasePath . 'TestInput/Transparent.png';
606
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-png');
607
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
608
        if ($imResult !== null && file_exists($imResult[3])) {
609
            $result = [
610
                'fileExists' => true,
611
                'outputFile' => $imResult[3],
612
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-png.png',
613
                'command' => $imageProcessor->IM_commands,
614
            ];
615
        } else {
616
            $result = [
617
                'status' => [$this->imageGenerationFailedMessage()],
618
                'command' => $imageProcessor->IM_commands,
619
            ];
620
        }
621
        return $this->getImageTestResponse($result);
622
    }
623
624
    /**
625
     * Scaling transparent files - gif to jpg
626
     *
627
     * @return ResponseInterface
628
     */
629
    public function imageProcessingGifToJpgAction(): ResponseInterface
630
    {
631
        if (!$this->isImageMagickEnabledAndConfigured()) {
632
            return new JsonResponse([
633
                'status' => [$this->imageMagickDisabledMessage()],
634
            ]);
635
        }
636
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
637
        $imageProcessor = $this->initializeImageProcessor();
638
        $inputFile = $imageBasePath . 'TestInput/Transparent.gif';
639
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-jpg');
640
        $jpegQuality = MathUtility::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'], 10, 100, 85);
641
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '-quality ' . $jpegQuality . ' -opaque white -background white -flatten', '', [], true);
642
        if ($imResult !== null && file_exists($imResult[3])) {
643
            $result = [
644
                'fileExists' => true,
645
                'outputFile' => $imResult[3],
646
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-jpg.jpg',
647
                'command' => $imageProcessor->IM_commands,
648
            ];
649
        } else {
650
            $result = [
651
                'status' => [$this->imageGenerationFailedMessage()],
652
                'command' => $imageProcessor->IM_commands,
653
            ];
654
        }
655
        return $this->getImageTestResponse($result);
656
    }
657
658
    /**
659
     * Converting jpg to webp
660
     *
661
     * @return ResponseInterface
662
     */
663
    public function imageProcessingJpgToWebpAction(): ResponseInterface
664
    {
665
        if (!$this->isImageMagickEnabledAndConfigured()) {
666
            return new JsonResponse([
667
                'status' => [$this->imageMagickDisabledMessage()],
668
            ]);
669
        }
670
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
671
        $imageProcessor = $this->initializeImageProcessor();
672
        $inputFile = $imageBasePath . 'TestInput/Test.jpg';
673
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('read-webp');
674
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'webp', '300', '', '', '', [], true);
675
        if ($imResult !== null) {
676
            $result = [
677
                'fileExists' => file_exists($imResult[3]),
678
                'outputFile' => $imResult[3],
679
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Convert-webp.webp',
680
                'command' => $imageProcessor->IM_commands,
681
            ];
682
        } else {
683
            $result = [
684
                'status' => [$this->imageGenerationFailedMessage()],
685
                'command' => $imageProcessor->IM_commands,
686
            ];
687
        }
688
        return $this->getImageTestResponse($result);
689
    }
690
691
    /**
692
     * Combine images with gif mask
693
     *
694
     * @return ResponseInterface
695
     */
696
    public function imageProcessingCombineGifMaskAction(): ResponseInterface
697
    {
698
        if (!$this->isImageMagickEnabledAndConfigured()) {
699
            return new JsonResponse([
700
                'status' => [$this->imageMagickDisabledMessage()],
701
            ]);
702
        }
703
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
704
        $imageProcessor = $this->initializeImageProcessor();
705
        $inputFile = $imageBasePath . 'TestInput/BackgroundOrange.gif';
706
        $overlayFile = $imageBasePath . 'TestInput/Test.jpg';
707
        $maskFile = $imageBasePath . 'TestInput/MaskBlackWhite.gif';
708
        $resultFile = $this->getImagesPath() . $imageProcessor->filenamePrefix
709
            . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine1') . '.jpg';
710
        $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
711
        $imResult = $imageProcessor->getImageDimensions($resultFile);
712
        if ($imResult) {
713
            $result = [
714
                'fileExists' => true,
715
                'outputFile' => $imResult[3],
716
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Combine-1.jpg',
717
                'command' => $imageProcessor->IM_commands,
718
            ];
719
        } else {
720
            $result = [
721
                'status' => [$this->imageGenerationFailedMessage()],
722
                'command' => $imageProcessor->IM_commands,
723
            ];
724
        }
725
        return $this->getImageTestResponse($result);
726
    }
727
728
    /**
729
     * Combine images with jpg mask
730
     *
731
     * @return ResponseInterface
732
     */
733
    public function imageProcessingCombineJpgMaskAction(): ResponseInterface
734
    {
735
        if (!$this->isImageMagickEnabledAndConfigured()) {
736
            return new JsonResponse([
737
                'status' => [$this->imageMagickDisabledMessage()],
738
            ]);
739
        }
740
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
741
        $imageProcessor = $this->initializeImageProcessor();
742
        $inputFile = $imageBasePath . 'TestInput/BackgroundCombine.jpg';
743
        $overlayFile = $imageBasePath . 'TestInput/Test.jpg';
744
        $maskFile = $imageBasePath . 'TestInput/MaskCombine.jpg';
745
        $resultFile = $this->getImagesPath() . $imageProcessor->filenamePrefix
746
            . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine2') . '.jpg';
747
        $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
748
        $imResult = $imageProcessor->getImageDimensions($resultFile);
749
        if ($imResult) {
750
            $result = [
751
                'fileExists' => true,
752
                'outputFile' => $imResult[3],
753
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Combine-2.jpg',
754
                'command' => $imageProcessor->IM_commands,
755
            ];
756
        } else {
757
            $result = [
758
                'status' => [$this->imageGenerationFailedMessage()],
759
                'command' => $imageProcessor->IM_commands,
760
            ];
761
        }
762
        return $this->getImageTestResponse($result);
763
    }
764
765
    /**
766
     * GD with simple box
767
     *
768
     * @return ResponseInterface
769
     */
770
    public function imageProcessingGdlibSimpleAction(): ResponseInterface
771
    {
772
        $imageProcessor = $this->initializeImageProcessor();
773
        $gifOrPng = $imageProcessor->gifExtension;
774
        $image = imagecreatetruecolor(300, 225);
775
        $backgroundColor = imagecolorallocate($image, 0, 0, 0);
776
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
777
        $workArea = [0, 0, 300, 225];
778
        $conf = [
779
            'dimensions' => '10,50,280,50',
780
            'color' => 'olive',
781
        ];
782
        $imageProcessor->makeBox($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type GdImage; however, parameter $im of TYPO3\CMS\Core\Imaging\G...calFunctions::makeBox() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

782
        $imageProcessor->makeBox(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
783
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdSimple') . '.' . $gifOrPng;
784
        $imageProcessor->ImageWrite($image, $outputFile);
785
        $imResult = $imageProcessor->getImageDimensions($outputFile);
786
        $result = [
787
            'fileExists' => true,
788
            'outputFile' => $imResult[3],
789
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-simple.' . $gifOrPng,
790
            'command' => $imageProcessor->IM_commands,
791
        ];
792
        return $this->getImageTestResponse($result);
793
    }
794
795
    /**
796
     * GD from image with box
797
     *
798
     * @return ResponseInterface
799
     */
800
    public function imageProcessingGdlibFromFileAction(): ResponseInterface
801
    {
802
        $imageProcessor = $this->initializeImageProcessor();
803
        $gifOrPng = $imageProcessor->gifExtension;
804
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
805
        $inputFile = $imageBasePath . 'TestInput/Test.' . $gifOrPng;
806
        $image = $imageProcessor->imageCreateFromFile($inputFile);
807
        $workArea = [0, 0, 400, 300];
808
        $conf = [
809
            'dimensions' => '10,50,380,50',
810
            'color' => 'olive',
811
        ];
812
        $imageProcessor->makeBox($image, $conf, $workArea);
813
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdBox') . '.' . $gifOrPng;
814
        $imageProcessor->ImageWrite($image, $outputFile);
815
        $imResult = $imageProcessor->getImageDimensions($outputFile);
816
        $result = [
817
            'fileExists' => true,
818
            'outputFile' => $imResult[3],
819
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-box.' . $gifOrPng,
820
            'command' => $imageProcessor->IM_commands,
821
        ];
822
        return $this->getImageTestResponse($result);
823
    }
824
825
    /**
826
     * GD with text
827
     *
828
     * @return ResponseInterface
829
     */
830
    public function imageProcessingGdlibRenderTextAction(): ResponseInterface
831
    {
832
        $imageProcessor = $this->initializeImageProcessor();
833
        $gifOrPng = $imageProcessor->gifExtension;
834
        $image = imagecreatetruecolor(300, 225);
835
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
836
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
837
        $workArea = [0, 0, 300, 225];
838
        $conf = [
839
            'iterations' => 1,
840
            'angle' => 0,
841
            'antiAlias' => 1,
842
            'text' => 'HELLO WORLD',
843
            'fontColor' => '#003366',
844
            'fontSize' => 30,
845
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
846
            'offset' => '30,80',
847
        ];
848
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
849
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type GdImage; however, parameter $im of TYPO3\CMS\Core\Imaging\G...alFunctions::makeText() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

849
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
850
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
851
        $imageProcessor->ImageWrite($image, $outputFile);
852
        $imResult = $imageProcessor->getImageDimensions($outputFile);
853
        $result = [
854
            'fileExists' => true,
855
            'outputFile' => $imResult[3],
856
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-text.' . $gifOrPng,
857
            'command' => $imageProcessor->IM_commands,
858
        ];
859
        return $this->getImageTestResponse($result);
860
    }
861
862
    /**
863
     * GD with text, niceText
864
     *
865
     * @return ResponseInterface
866
     */
867
    public function imageProcessingGdlibNiceTextAction(): ResponseInterface
868
    {
869
        if (!$this->isImageMagickEnabledAndConfigured()) {
870
            return new JsonResponse([
871
                'status' => [$this->imageMagickDisabledMessage()],
872
            ]);
873
        }
874
        $imageProcessor = $this->initializeImageProcessor();
875
        $gifOrPng = $imageProcessor->gifExtension;
876
        $image = imagecreatetruecolor(300, 225);
877
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
878
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
879
        $workArea = [0, 0, 300, 225];
880
        $conf = [
881
            'iterations' => 1,
882
            'angle' => 0,
883
            'antiAlias' => 1,
884
            'text' => 'HELLO WORLD',
885
            'fontColor' => '#003366',
886
            'fontSize' => 30,
887
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
888
            'offset' => '30,80',
889
        ];
890
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
891
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type GdImage; however, parameter $im of TYPO3\CMS\Core\Imaging\G...alFunctions::makeText() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

891
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
892
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
893
        $imageProcessor->ImageWrite($image, $outputFile);
894
        $conf['offset'] = '30,120';
895
        $conf['niceText'] = 1;
896
        $imageProcessor->makeText($image, $conf, $workArea);
897
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
898
        $imageProcessor->ImageWrite($image, $outputFile);
899
        $imResult = $imageProcessor->getImageDimensions($outputFile);
900
        $result = [
901
            'fileExists' => true,
902
            'outputFile' => $imResult[3],
903
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-niceText.' . $gifOrPng,
904
            'command' => $imageProcessor->IM_commands,
905
        ];
906
        return $this->getImageTestResponse($result);
907
    }
908
909
    /**
910
     * GD with text, niceText, shadow
911
     *
912
     * @return ResponseInterface
913
     */
914
    public function imageProcessingGdlibNiceTextShadowAction(): ResponseInterface
915
    {
916
        if (!$this->isImageMagickEnabledAndConfigured()) {
917
            return new JsonResponse([
918
                'status' => [$this->imageMagickDisabledMessage()],
919
            ]);
920
        }
921
        $imageProcessor = $this->initializeImageProcessor();
922
        $gifOrPng = $imageProcessor->gifExtension;
923
        $image = imagecreatetruecolor(300, 225);
924
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
925
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
926
        $workArea = [0, 0, 300, 225];
927
        $conf = [
928
            'iterations' => 1,
929
            'angle' => 0,
930
            'antiAlias' => 1,
931
            'text' => 'HELLO WORLD',
932
            'fontColor' => '#003366',
933
            'fontSize' => 30,
934
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
935
            'offset' => '30,80',
936
        ];
937
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
938
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type GdImage; however, parameter $im of TYPO3\CMS\Core\Imaging\G...alFunctions::makeText() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

938
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
939
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
940
        $imageProcessor->ImageWrite($image, $outputFile);
941
        $conf['offset'] = '30,120';
942
        $conf['niceText'] = 1;
943
        $imageProcessor->makeText($image, $conf, $workArea);
944
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
945
        $imageProcessor->ImageWrite($image, $outputFile);
946
        $conf['offset'] = '30,160';
947
        $conf['niceText'] = 1;
948
        $conf['shadow.'] = [
949
            'offset' => '2,2',
950
            'blur' => '20',
951
            'opacity' => '50',
952
            'color' => 'black'
953
        ];
954
        // Warning: Re-uses $image from above!
955
        $imageProcessor->makeShadow($image, $conf['shadow.'], $workArea, $conf);
956
        $imageProcessor->makeText($image, $conf, $workArea);
957
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('GDwithText-niceText-shadow') . '.' . $gifOrPng;
958
        $imageProcessor->ImageWrite($image, $outputFile);
959
        $imResult = $imageProcessor->getImageDimensions($outputFile);
960
        $result = [
961
            'fileExists' => true,
962
            'outputFile' => $imResult[3],
963
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-shadow.' . $gifOrPng,
964
            'command' => $imageProcessor->IM_commands,
965
        ];
966
        return $this->getImageTestResponse($result);
967
    }
968
969
    /**
970
     * Initialize image processor
971
     *
972
     * @return GraphicalFunctions Initialized image processor
973
     */
974
    protected function initializeImageProcessor(): GraphicalFunctions
975
    {
976
        $imageProcessor = GeneralUtility::makeInstance(GraphicalFunctions::class);
977
        $imageProcessor->dontCheckForExistingTempFile = true;
978
        $imageProcessor->filenamePrefix = 'installTool-';
979
        $imageProcessor->dontCompress = true;
980
        $imageProcessor->alternativeOutputKey = 'typo3InstallTest';
981
        $imageProcessor->setImageFileExt(self::IMAGE_FILE_EXT);
982
        return $imageProcessor;
983
    }
984
985
    /**
986
     * Determine ImageMagick / GraphicsMagick version
987
     *
988
     * @return string Version
989
     */
990
    protected function determineImageMagickVersion(): string
991
    {
992
        $command = CommandUtility::imageMagickCommand('identify', '-version');
993
        CommandUtility::exec($command, $result);
994
        $string = $result[0];
995
        $version = '';
996
        if (!empty($string)) {
997
            [, $version] = explode('Magick', $string);
998
            [$version] = explode(' ', trim($version));
999
            $version = trim($version);
1000
        }
1001
        return $version;
1002
    }
1003
1004
    /**
1005
     * Convert to jpg from given input format
1006
     *
1007
     * @param string $inputFormat
1008
     * @return ResponseInterface
1009
     */
1010
    protected function convertImageFormatsToJpg(string $inputFormat): ResponseInterface
1011
    {
1012
        if (!$this->isImageMagickEnabledAndConfigured()) {
1013
            return new JsonResponse([
1014
                'status' => [$this->imageMagickDisabledMessage()],
1015
            ]);
1016
        }
1017
        if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $inputFormat)) {
1018
            return new JsonResponse([
1019
                'status' => [
1020
                    new FlashMessage(
1021
                        'Handling format ' . $inputFormat . ' must be enabled in TYPO3_CONF_VARS[\'GFX\'][\'imagefile_ext\']',
1022
                        'Skipped test',
1023
                        FlashMessage::WARNING
1024
                    )
1025
                ]
1026
            ]);
1027
        }
1028
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
1029
        $imageProcessor = $this->initializeImageProcessor();
1030
        $inputFile = $imageBasePath . 'TestInput/Test.' . $inputFormat;
1031
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('read') . '-' . $inputFormat;
1032
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '', '', [], true);
1033
        if ($imResult !== null) {
1034
            $result = [
1035
                'fileExists' => file_exists($imResult[3]),
1036
                'outputFile' => $imResult[3],
1037
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Read-' . $inputFormat . '.jpg',
1038
                'command' => $imageProcessor->IM_commands,
1039
            ];
1040
        } else {
1041
            $result = [
1042
                'status' => [$this->imageGenerationFailedMessage()],
1043
                'command' => $imageProcessor->IM_commands,
1044
            ];
1045
        }
1046
        return $this->getImageTestResponse($result);
1047
    }
1048
1049
    /**
1050
     * Get details about all configured database connections
1051
     *
1052
     * @return array
1053
     */
1054
    protected function getDatabaseConnectionInformation(): array
1055
    {
1056
        $connectionInfos = [];
1057
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1058
        foreach ($connectionPool->getConnectionNames() as $connectionName) {
1059
            $connection = $connectionPool->getConnectionByName($connectionName);
1060
            $connectionParameters = $connection->getParams();
1061
            $connectionInfo = [
1062
                'connectionName' => $connectionName,
1063
                'version' => $connection->getServerVersion(),
1064
                'databaseName' => $connection->getDatabase(),
1065
                'username' => $connectionParameters['user'],
1066
                'host' => $connectionParameters['host'],
1067
                'port' => $connectionParameters['port'],
1068
                'socket' => $connectionParameters['unix_socket'] ?? '',
1069
                'numberOfTables' => count($connection->getSchemaManager()->listTableNames()),
1070
                'numberOfMappedTables' => 0,
1071
            ];
1072
            if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
1073
                && is_array($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
1074
            ) {
1075
                // Count number of array keys having $connectionName as value
1076
                $connectionInfo['numberOfMappedTables'] = count(array_intersect(
1077
                    $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'],
1078
                    [$connectionName]
1079
                ));
1080
            }
1081
            $connectionInfos[] = $connectionInfo;
1082
        }
1083
        return $connectionInfos;
1084
    }
1085
1086
    /**
1087
     * Get details about the application context
1088
     *
1089
     * @return array
1090
     */
1091
    protected function getApplicationContextInformation(): array
1092
    {
1093
        $applicationContext = Environment::getContext();
1094
        $status = $applicationContext->isProduction() ? InformationStatus::STATUS_OK : InformationStatus::STATUS_WARNING;
1095
1096
        return [
1097
            'context' => (string)$applicationContext,
1098
            'status' => $status,
1099
        ];
1100
    }
1101
1102
    /**
1103
     * Get sender address from configuration
1104
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
1105
     * If this setting is empty fall back to '[email protected]'
1106
     *
1107
     * @return string Returns an email address
1108
     */
1109
    protected function getSenderEmailAddress(): string
1110
    {
1111
        return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'])
1112
            ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
1113
            : '[email protected]';
1114
    }
1115
1116
    /**
1117
     * Gets sender name from configuration
1118
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
1119
     * If this setting is empty, it falls back to a default string.
1120
     *
1121
     * @return string
1122
     */
1123
    protected function getSenderEmailName(): string
1124
    {
1125
        return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'])
1126
            ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
1127
            : 'TYPO3 CMS install tool';
1128
    }
1129
1130
    /**
1131
     * Gets email subject from configuration
1132
     * ['TYPO3_CONF_VARS']['SYS']['sitename']
1133
     * If this setting is empty, it falls back to a default string.
1134
     *
1135
     * @return string
1136
     */
1137
    protected function getEmailSubject(): string
1138
    {
1139
        $name = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'])
1140
            ? ' from site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"'
1141
            : '';
1142
        return 'Test TYPO3 CMS mail delivery' . $name;
1143
    }
1144
1145
    /**
1146
     * Create a JsonResponse from single image tests
1147
     *
1148
     * @param array $testResult
1149
     * @return ResponseInterface
1150
     */
1151
    protected function getImageTestResponse(array $testResult): ResponseInterface
1152
    {
1153
        $responseData = [
1154
            'success' => true,
1155
        ];
1156
        foreach ($testResult as $resultKey => $value) {
1157
            if ($resultKey === 'referenceFile' && !empty($testResult['referenceFile'])) {
1158
                $fileExt = end(explode('.', $testResult['referenceFile']));
1159
                $responseData['referenceFile'] = 'data:image/' . $fileExt . ';base64,' . base64_encode((string)file_get_contents($testResult['referenceFile']));
1160
            } elseif ($resultKey === 'outputFile' && !empty($testResult['outputFile'])) {
1161
                $fileExt = end(explode('.', $testResult['outputFile']));
1162
                $responseData['outputFile'] = 'data:image/' . $fileExt . ';base64,' . base64_encode((string)file_get_contents($testResult['outputFile']));
1163
            } else {
1164
                $responseData[$resultKey] = $value;
1165
            }
1166
        }
1167
        return new JsonResponse($responseData);
1168
    }
1169
1170
    /**
1171
     * Create a 'image generation failed' message
1172
     *
1173
     * @return FlashMessage
1174
     */
1175
    protected function imageGenerationFailedMessage(): FlashMessage
1176
    {
1177
        return new FlashMessage(
1178
            'ImageMagick / GraphicsMagick handling is enabled, but the execute'
1179
            . ' command returned an error. Please check your settings, especially'
1180
            . ' [\'GFX\'][\'processor_path\'] and [\'GFX\'][\'processor_path_lzw\'] and ensure Ghostscript is installed on your server.',
1181
            'Image generation failed',
1182
            FlashMessage::ERROR
1183
        );
1184
    }
1185
1186
    /**
1187
     * Find out if ImageMagick or GraphicsMagick is enabled and set up
1188
     *
1189
     * @return bool TRUE if enabled and path is set
1190
     */
1191
    protected function isImageMagickEnabledAndConfigured(): bool
1192
    {
1193
        $enabled = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'];
1194
        $path = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'];
1195
        return $enabled && $path;
1196
    }
1197
1198
    /**
1199
     * Create a 'imageMagick disabled' message
1200
     *
1201
     * @return FlashMessage
1202
     */
1203
    protected function imageMagickDisabledMessage(): FlashMessage
1204
    {
1205
        return new FlashMessage(
1206
            'ImageMagick / GraphicsMagick handling is disabled or not configured correctly.',
1207
            'Tests not executed',
1208
            FlashMessage::ERROR
1209
        );
1210
    }
1211
1212
    /**
1213
     * Return the temp image dir.
1214
     * If not exist it will be created
1215
     *
1216
     * @return string
1217
     */
1218
    protected function getImagesPath(): string
1219
    {
1220
        $imagePath = Environment::getPublicPath() . '/typo3temp/assets/images/';
1221
        if (!is_dir($imagePath)) {
1222
            GeneralUtility::mkdir_deep($imagePath);
1223
        }
1224
        return $imagePath;
1225
    }
1226
}
1227