Completed
Push — master ( 956142...4390d4 )
by
unknown
13:50
created

EnvironmentController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

346
        imagecolorallocate(/** @scrutinizer ignore-type */ $image, 255, 255, 55);
Loading history...
347
        $textColor = imagecolorallocate($image, 233, 14, 91);
348
        @imagettftext(
349
            $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 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

349
            /** @scrutinizer ignore-type */ $image,
Loading history...
350
            20 / 96.0 * 72, // As in  compensateFontSizeBasedOnFreetypeDpi
351
            0,
352
            10,
353
            20,
354
            $textColor,
355
            ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
356
            'Testing true type'
357
        );
358
        $outputFile = Environment::getPublicPath() . '/typo3temp/assets/images/installTool-' . StringUtility::getUniqueId('createTrueTypeFontTestImage') . '.gif';
359
        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 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

359
        imagegif(/** @scrutinizer ignore-type */ $image, $outputFile);
Loading history...
360
        $fileExists = file_exists($outputFile);
361
        if ($fileExists) {
362
            GeneralUtility::fixPermissions($outputFile);
363
        }
364
        return $this->getImageTestResponse([
365
            'fileExists' => $fileExists,
366
            'outputFile' => $outputFile,
367
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Font.gif',
368
        ]);
369
    }
370
371
    /**
372
     * Convert to jpg from jpg
373
     *
374
     * @return ResponseInterface
375
     */
376
    public function imageProcessingReadJpgAction(): ResponseInterface
377
    {
378
        return $this->convertImageFormatsToJpg('jpg');
379
    }
380
381
    /**
382
     * Convert to jpg from gif
383
     *
384
     * @return ResponseInterface
385
     */
386
    public function imageProcessingReadGifAction(): ResponseInterface
387
    {
388
        return $this->convertImageFormatsToJpg('gif');
389
    }
390
391
    /**
392
     * Convert to jpg from png
393
     *
394
     * @return ResponseInterface
395
     */
396
    public function imageProcessingReadPngAction(): ResponseInterface
397
    {
398
        return $this->convertImageFormatsToJpg('png');
399
    }
400
401
    /**
402
     * Convert to jpg from tif
403
     *
404
     * @return ResponseInterface
405
     */
406
    public function imageProcessingReadTifAction(): ResponseInterface
407
    {
408
        return $this->convertImageFormatsToJpg('tif');
409
    }
410
411
    /**
412
     * Convert to jpg from pdf
413
     *
414
     * @return ResponseInterface
415
     */
416
    public function imageProcessingReadPdfAction(): ResponseInterface
417
    {
418
        return $this->convertImageFormatsToJpg('pdf');
419
    }
420
421
    /**
422
     * Convert to jpg from ai
423
     *
424
     * @return ResponseInterface
425
     */
426
    public function imageProcessingReadAiAction(): ResponseInterface
427
    {
428
        return $this->convertImageFormatsToJpg('ai');
429
    }
430
431
    /**
432
     * Writing gif test
433
     *
434
     * @return ResponseInterface
435
     */
436
    public function imageProcessingWriteGifAction(): ResponseInterface
437
    {
438
        if (!$this->isImageMagickEnabledAndConfigured()) {
439
            return new JsonResponse([
440
                'status' => [$this->imageMagickDisabledMessage()],
441
            ]);
442
        }
443
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
444
        $inputFile = $imageBasePath . 'TestInput/Test.gif';
445
        $imageProcessor = $this->initializeImageProcessor();
446
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-gif');
447
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
448
        $messages = new FlashMessageQueue('install');
449
        if ($imResult !== null && is_file($imResult[3])) {
450
            if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress']) {
451
                clearstatcache();
452
                $previousSize = GeneralUtility::formatSize(filesize($imResult[3]));
453
                $methodUsed = GraphicalFunctions::gifCompress($imResult[3], '');
454
                clearstatcache();
455
                $compressedSize = GeneralUtility::formatSize(filesize($imResult[3]));
456
                $messages->enqueue(new FlashMessage(
457
                    'Method used by compress: ' . $methodUsed . LF
458
                    . ' Previous filesize: ' . $previousSize . '. Current filesize:' . $compressedSize,
459
                    'Compressed gif',
460
                    FlashMessage::INFO
461
                ));
462
            } else {
463
                $messages->enqueue(new FlashMessage(
464
                    '',
465
                    'Gif compression not enabled by [GFX][gif_compress]',
466
                    FlashMessage::INFO
467
                ));
468
            }
469
            $result = [
470
                'status' => $messages,
471
                'fileExists' => true,
472
                'outputFile' => $imResult[3],
473
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Write-gif.gif',
474
                'command' => $imageProcessor->IM_commands,
475
            ];
476
        } else {
477
            $result = [
478
                'status' => [$this->imageGenerationFailedMessage()],
479
                'command' => $imageProcessor->IM_commands,
480
            ];
481
        }
482
        return $this->getImageTestResponse($result);
483
    }
484
485
    /**
486
     * Writing png test
487
     *
488
     * @return ResponseInterface
489
     */
490
    public function imageProcessingWritePngAction(): ResponseInterface
491
    {
492
        if (!$this->isImageMagickEnabledAndConfigured()) {
493
            return new JsonResponse([
494
                'status' => [$this->imageMagickDisabledMessage()],
495
            ]);
496
        }
497
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
498
        $inputFile = $imageBasePath . 'TestInput/Test.png';
499
        $imageProcessor = $this->initializeImageProcessor();
500
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('write-png');
501
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
502
        if ($imResult !== null && is_file($imResult[3])) {
503
            $result = [
504
                'fileExists' => true,
505
                'outputFile' => $imResult[3],
506
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Write-png.png',
507
                'command' => $imageProcessor->IM_commands,
508
            ];
509
        } else {
510
            $result = [
511
                'status' => [$this->imageGenerationFailedMessage()],
512
                'command' => $imageProcessor->IM_commands,
513
            ];
514
        }
515
        return $this->getImageTestResponse($result);
516
    }
517
518
    /**
519
     * Scaling transparent files - gif to gif
520
     *
521
     * @return ResponseInterface
522
     */
523
    public function imageProcessingGifToGifAction(): ResponseInterface
524
    {
525
        if (!$this->isImageMagickEnabledAndConfigured()) {
526
            return new JsonResponse([
527
                'status' => [$this->imageMagickDisabledMessage()],
528
            ]);
529
        }
530
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
531
        $imageProcessor = $this->initializeImageProcessor();
532
        $inputFile = $imageBasePath . 'TestInput/Transparent.gif';
533
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-gif');
534
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'gif', '300', '', '', '', [], true);
535
        if ($imResult !== null && file_exists($imResult[3])) {
536
            $result = [
537
                'fileExists' => true,
538
                'outputFile' => $imResult[3],
539
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-gif.gif',
540
                'command' => $imageProcessor->IM_commands,
541
            ];
542
        } else {
543
            $result = [
544
                'status' => [$this->imageGenerationFailedMessage()],
545
                'command' => $imageProcessor->IM_commands,
546
            ];
547
        }
548
        return $this->getImageTestResponse($result);
549
    }
550
551
    /**
552
     * Scaling transparent files - png to png
553
     *
554
     * @return ResponseInterface
555
     */
556
    public function imageProcessingPngToPngAction(): ResponseInterface
557
    {
558
        if (!$this->isImageMagickEnabledAndConfigured()) {
559
            return new JsonResponse([
560
                'status' => [$this->imageMagickDisabledMessage()],
561
            ]);
562
        }
563
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
564
        $imageProcessor = $this->initializeImageProcessor();
565
        $inputFile = $imageBasePath . 'TestInput/Transparent.png';
566
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-png');
567
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'png', '300', '', '', '', [], true);
568
        if ($imResult !== null && file_exists($imResult[3])) {
569
            $result = [
570
                'fileExists' => true,
571
                'outputFile' => $imResult[3],
572
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-png.png',
573
                'command' => $imageProcessor->IM_commands,
574
            ];
575
        } else {
576
            $result = [
577
                'status' => [$this->imageGenerationFailedMessage()],
578
                'command' => $imageProcessor->IM_commands,
579
            ];
580
        }
581
        return $this->getImageTestResponse($result);
582
    }
583
584
    /**
585
     * Scaling transparent files - gif to jpg
586
     *
587
     * @return ResponseInterface
588
     */
589
    public function imageProcessingGifToJpgAction(): ResponseInterface
590
    {
591
        if (!$this->isImageMagickEnabledAndConfigured()) {
592
            return new JsonResponse([
593
                'status' => [$this->imageMagickDisabledMessage()],
594
            ]);
595
        }
596
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
597
        $imageProcessor = $this->initializeImageProcessor();
598
        $inputFile = $imageBasePath . 'TestInput/Transparent.gif';
599
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('scale-jpg');
600
        $jpegQuality = MathUtility::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'], 10, 100, 85);
601
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '-quality ' . $jpegQuality . ' -opaque white -background white -flatten', '', [], true);
602
        if ($imResult !== null && file_exists($imResult[3])) {
603
            $result = [
604
                'fileExists' => true,
605
                'outputFile' => $imResult[3],
606
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Scale-jpg.jpg',
607
                'command' => $imageProcessor->IM_commands,
608
            ];
609
        } else {
610
            $result = [
611
                'status' => [$this->imageGenerationFailedMessage()],
612
                'command' => $imageProcessor->IM_commands,
613
            ];
614
        }
615
        return $this->getImageTestResponse($result);
616
    }
617
618
    /**
619
     * Combine images with gif mask
620
     *
621
     * @return ResponseInterface
622
     */
623
    public function imageProcessingCombineGifMaskAction(): ResponseInterface
624
    {
625
        if (!$this->isImageMagickEnabledAndConfigured()) {
626
            return new JsonResponse([
627
                'status' => [$this->imageMagickDisabledMessage()],
628
            ]);
629
        }
630
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
631
        $imageProcessor = $this->initializeImageProcessor();
632
        $inputFile = $imageBasePath . 'TestInput/BackgroundOrange.gif';
633
        $overlayFile = $imageBasePath . 'TestInput/Test.jpg';
634
        $maskFile = $imageBasePath . 'TestInput/MaskBlackWhite.gif';
635
        $resultFile = $this->getImagesPath() . $imageProcessor->filenamePrefix
636
            . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine1') . '.jpg';
637
        $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
638
        $imResult = $imageProcessor->getImageDimensions($resultFile);
639
        if ($imResult) {
640
            $result = [
641
                'fileExists' => true,
642
                'outputFile' => $imResult[3],
643
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Combine-1.jpg',
644
                'command' => $imageProcessor->IM_commands,
645
            ];
646
        } else {
647
            $result = [
648
                'status' => [$this->imageGenerationFailedMessage()],
649
                'command' => $imageProcessor->IM_commands,
650
            ];
651
        }
652
        return $this->getImageTestResponse($result);
653
    }
654
655
    /**
656
     * Combine images with jpg mask
657
     *
658
     * @return ResponseInterface
659
     */
660
    public function imageProcessingCombineJpgMaskAction(): ResponseInterface
661
    {
662
        if (!$this->isImageMagickEnabledAndConfigured()) {
663
            return new JsonResponse([
664
                'status' => [$this->imageMagickDisabledMessage()],
665
            ]);
666
        }
667
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
668
        $imageProcessor = $this->initializeImageProcessor();
669
        $inputFile = $imageBasePath . 'TestInput/BackgroundCombine.jpg';
670
        $overlayFile = $imageBasePath . 'TestInput/Test.jpg';
671
        $maskFile = $imageBasePath . 'TestInput/MaskCombine.jpg';
672
        $resultFile = $this->getImagesPath() . $imageProcessor->filenamePrefix
673
            . StringUtility::getUniqueId($imageProcessor->alternativeOutputKey . 'combine2') . '.jpg';
674
        $imageProcessor->combineExec($inputFile, $overlayFile, $maskFile, $resultFile);
675
        $imResult = $imageProcessor->getImageDimensions($resultFile);
676
        if ($imResult) {
677
            $result = [
678
                'fileExists' => true,
679
                'outputFile' => $imResult[3],
680
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Combine-2.jpg',
681
                'command' => $imageProcessor->IM_commands,
682
            ];
683
        } else {
684
            $result = [
685
                'status' => [$this->imageGenerationFailedMessage()],
686
                'command' => $imageProcessor->IM_commands,
687
            ];
688
        }
689
        return $this->getImageTestResponse($result);
690
    }
691
692
    /**
693
     * GD with simple box
694
     *
695
     * @return ResponseInterface
696
     */
697
    public function imageProcessingGdlibSimpleAction(): ResponseInterface
698
    {
699
        $imageProcessor = $this->initializeImageProcessor();
700
        $gifOrPng = $imageProcessor->gifExtension;
701
        $image = imagecreatetruecolor(300, 225);
702
        $backgroundColor = imagecolorallocate($image, 0, 0, 0);
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 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

702
        $backgroundColor = imagecolorallocate(/** @scrutinizer ignore-type */ $image, 0, 0, 0);
Loading history...
703
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagefilledrectangle() 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

703
        imagefilledrectangle(/** @scrutinizer ignore-type */ $image, 0, 0, 300, 225, $backgroundColor);
Loading history...
704
        $workArea = [0, 0, 300, 225];
705
        $conf = [
706
            'dimensions' => '10,50,280,50',
707
            'color' => 'olive',
708
        ];
709
        $imageProcessor->makeBox($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; 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

709
        $imageProcessor->makeBox(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
710
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdSimple') . '.' . $gifOrPng;
711
        $imageProcessor->ImageWrite($image, $outputFile);
712
        $imResult = $imageProcessor->getImageDimensions($outputFile);
713
        $result = [
714
            'fileExists' => true,
715
            'outputFile' => $imResult[3],
716
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-simple.' . $gifOrPng,
717
            'command' => $imageProcessor->IM_commands,
718
        ];
719
        return $this->getImageTestResponse($result);
720
    }
721
722
    /**
723
     * GD from image with box
724
     *
725
     * @return ResponseInterface
726
     */
727
    public function imageProcessingGdlibFromFileAction(): ResponseInterface
728
    {
729
        $imageProcessor = $this->initializeImageProcessor();
730
        $gifOrPng = $imageProcessor->gifExtension;
731
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
732
        $inputFile = $imageBasePath . 'TestInput/Test.' . $gifOrPng;
733
        $image = $imageProcessor->imageCreateFromFile($inputFile);
734
        $workArea = [0, 0, 400, 300];
735
        $conf = [
736
            'dimensions' => '10,50,380,50',
737
            'color' => 'olive',
738
        ];
739
        $imageProcessor->makeBox($image, $conf, $workArea);
740
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdBox') . '.' . $gifOrPng;
741
        $imageProcessor->ImageWrite($image, $outputFile);
742
        $imResult = $imageProcessor->getImageDimensions($outputFile);
743
        $result = [
744
            'fileExists' => true,
745
            'outputFile' => $imResult[3],
746
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-box.' . $gifOrPng,
747
            'command' => $imageProcessor->IM_commands,
748
        ];
749
        return $this->getImageTestResponse($result);
750
    }
751
752
    /**
753
     * GD with text
754
     *
755
     * @return ResponseInterface
756
     */
757
    public function imageProcessingGdlibRenderTextAction(): ResponseInterface
758
    {
759
        $imageProcessor = $this->initializeImageProcessor();
760
        $gifOrPng = $imageProcessor->gifExtension;
761
        $image = imagecreatetruecolor(300, 225);
762
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
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 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

762
        $backgroundColor = imagecolorallocate(/** @scrutinizer ignore-type */ $image, 128, 128, 150);
Loading history...
763
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagefilledrectangle() 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

763
        imagefilledrectangle(/** @scrutinizer ignore-type */ $image, 0, 0, 300, 225, $backgroundColor);
Loading history...
764
        $workArea = [0, 0, 300, 225];
765
        $conf = [
766
            'iterations' => 1,
767
            'angle' => 0,
768
            'antiAlias' => 1,
769
            'text' => 'HELLO WORLD',
770
            'fontColor' => '#003366',
771
            'fontSize' => 30,
772
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
773
            'offset' => '30,80',
774
        ];
775
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
776
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; 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

776
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
777
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
778
        $imageProcessor->ImageWrite($image, $outputFile);
779
        $imResult = $imageProcessor->getImageDimensions($outputFile);
780
        $result = [
781
            'fileExists' => true,
782
            'outputFile' => $imResult[3],
783
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-text.' . $gifOrPng,
784
            'command' => $imageProcessor->IM_commands,
785
        ];
786
        return $this->getImageTestResponse($result);
787
    }
788
789
    /**
790
     * GD with text, niceText
791
     *
792
     * @return ResponseInterface
793
     */
794
    public function imageProcessingGdlibNiceTextAction(): ResponseInterface
795
    {
796
        if (!$this->isImageMagickEnabledAndConfigured()) {
797
            return new JsonResponse([
798
                'status' => [$this->imageMagickDisabledMessage()],
799
            ]);
800
        }
801
        $imageProcessor = $this->initializeImageProcessor();
802
        $gifOrPng = $imageProcessor->gifExtension;
803
        $image = imagecreatetruecolor(300, 225);
804
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
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 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

804
        $backgroundColor = imagecolorallocate(/** @scrutinizer ignore-type */ $image, 128, 128, 150);
Loading history...
805
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagefilledrectangle() 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

805
        imagefilledrectangle(/** @scrutinizer ignore-type */ $image, 0, 0, 300, 225, $backgroundColor);
Loading history...
806
        $workArea = [0, 0, 300, 225];
807
        $conf = [
808
            'iterations' => 1,
809
            'angle' => 0,
810
            'antiAlias' => 1,
811
            'text' => 'HELLO WORLD',
812
            'fontColor' => '#003366',
813
            'fontSize' => 30,
814
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
815
            'offset' => '30,80',
816
        ];
817
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
818
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; 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

818
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
819
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
820
        $imageProcessor->ImageWrite($image, $outputFile);
821
        $conf['offset'] = '30,120';
822
        $conf['niceText'] = 1;
823
        $imageProcessor->makeText($image, $conf, $workArea);
824
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
825
        $imageProcessor->ImageWrite($image, $outputFile);
826
        $imResult = $imageProcessor->getImageDimensions($outputFile);
827
        $result = [
828
            'fileExists' => true,
829
            'outputFile' => $imResult[3],
830
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-niceText.' . $gifOrPng,
831
            'command' => $imageProcessor->IM_commands,
832
        ];
833
        return $this->getImageTestResponse($result);
834
    }
835
836
    /**
837
     * GD with text, niceText, shadow
838
     *
839
     * @return ResponseInterface
840
     */
841
    public function imageProcessingGdlibNiceTextShadowAction(): ResponseInterface
842
    {
843
        if (!$this->isImageMagickEnabledAndConfigured()) {
844
            return new JsonResponse([
845
                'status' => [$this->imageMagickDisabledMessage()],
846
            ]);
847
        }
848
        $imageProcessor = $this->initializeImageProcessor();
849
        $gifOrPng = $imageProcessor->gifExtension;
850
        $image = imagecreatetruecolor(300, 225);
851
        $backgroundColor = imagecolorallocate($image, 128, 128, 150);
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 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

851
        $backgroundColor = imagecolorallocate(/** @scrutinizer ignore-type */ $image, 128, 128, 150);
Loading history...
852
        imagefilledrectangle($image, 0, 0, 300, 225, $backgroundColor);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; however, parameter $image of imagefilledrectangle() 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

852
        imagefilledrectangle(/** @scrutinizer ignore-type */ $image, 0, 0, 300, 225, $backgroundColor);
Loading history...
853
        $workArea = [0, 0, 300, 225];
854
        $conf = [
855
            'iterations' => 1,
856
            'angle' => 0,
857
            'antiAlias' => 1,
858
            'text' => 'HELLO WORLD',
859
            'fontColor' => '#003366',
860
            'fontSize' => 30,
861
            'fontFile' => ExtensionManagementUtility::extPath('install') . 'Resources/Private/Font/vera.ttf',
862
            'offset' => '30,80',
863
        ];
864
        $conf['BBOX'] = $imageProcessor->calcBBox($conf);
865
        $imageProcessor->makeText($image, $conf, $workArea);
0 ignored issues
show
Bug introduced by
It seems like $image can also be of type false; 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

865
        $imageProcessor->makeText(/** @scrutinizer ignore-type */ $image, $conf, $workArea);
Loading history...
866
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdText') . '.' . $gifOrPng;
867
        $imageProcessor->ImageWrite($image, $outputFile);
868
        $conf['offset'] = '30,120';
869
        $conf['niceText'] = 1;
870
        $imageProcessor->makeText($image, $conf, $workArea);
871
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('gdNiceText') . '.' . $gifOrPng;
872
        $imageProcessor->ImageWrite($image, $outputFile);
873
        $conf['offset'] = '30,160';
874
        $conf['niceText'] = 1;
875
        $conf['shadow.'] = [
876
            'offset' => '2,2',
877
            'blur' => '20',
878
            'opacity' => '50',
879
            'color' => 'black'
880
        ];
881
        // Warning: Re-uses $image from above!
882
        $imageProcessor->makeShadow($image, $conf['shadow.'], $workArea, $conf);
883
        $imageProcessor->makeText($image, $conf, $workArea);
884
        $outputFile = $this->getImagesPath() . $imageProcessor->filenamePrefix . StringUtility::getUniqueId('GDwithText-niceText-shadow') . '.' . $gifOrPng;
885
        $imageProcessor->ImageWrite($image, $outputFile);
886
        $imResult = $imageProcessor->getImageDimensions($outputFile);
887
        $result = [
888
            'fileExists' => true,
889
            'outputFile' => $imResult[3],
890
            'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Gdlib-shadow.' . $gifOrPng,
891
            'command' => $imageProcessor->IM_commands,
892
        ];
893
        return $this->getImageTestResponse($result);
894
    }
895
896
    /**
897
     * Initialize image processor
898
     *
899
     * @return GraphicalFunctions Initialized image processor
900
     */
901
    protected function initializeImageProcessor(): GraphicalFunctions
902
    {
903
        $imageProcessor = GeneralUtility::makeInstance(GraphicalFunctions::class);
904
        $imageProcessor->dontCheckForExistingTempFile = true;
905
        $imageProcessor->filenamePrefix = 'installTool-';
906
        $imageProcessor->dontCompress = true;
907
        $imageProcessor->alternativeOutputKey = 'typo3InstallTest';
908
        return $imageProcessor;
909
    }
910
911
    /**
912
     * Determine ImageMagick / GraphicsMagick version
913
     *
914
     * @return string Version
915
     */
916
    protected function determineImageMagickVersion(): string
917
    {
918
        $command = CommandUtility::imageMagickCommand('identify', '-version');
919
        CommandUtility::exec($command, $result);
920
        $string = $result[0];
921
        $version = '';
922
        if (!empty($string)) {
923
            [, $version] = explode('Magick', $string);
924
            [$version] = explode(' ', trim($version));
925
            $version = trim($version);
926
        }
927
        return $version;
928
    }
929
930
    /**
931
     * Convert to jpg from given input format
932
     *
933
     * @param string $inputFormat
934
     * @return ResponseInterface
935
     */
936
    protected function convertImageFormatsToJpg(string $inputFormat): ResponseInterface
937
    {
938
        if (!$this->isImageMagickEnabledAndConfigured()) {
939
            return new JsonResponse([
940
                'status' => [$this->imageMagickDisabledMessage()],
941
            ]);
942
        }
943
        if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $inputFormat)) {
944
            return new JsonResponse([
945
                'status' => [
946
                    new FlashMessage(
947
                        'Handling format ' . $inputFormat . ' must be enabled in TYPO3_CONF_VARS[\'GFX\'][\'imagefile_ext\']',
948
                        'Skipped test',
949
                        FlashMessage::WARNING
950
                    )
951
                ]
952
            ]);
953
        }
954
        $imageBasePath = ExtensionManagementUtility::extPath('install') . 'Resources/Public/Images/';
955
        $imageProcessor = $this->initializeImageProcessor();
956
        $inputFile = $imageBasePath . 'TestInput/Test.' . $inputFormat;
957
        $imageProcessor->imageMagickConvert_forceFileNameBody = StringUtility::getUniqueId('read') . '-' . $inputFormat;
958
        $imResult = $imageProcessor->imageMagickConvert($inputFile, 'jpg', '300', '', '', '', [], true);
959
        if ($imResult !== null) {
960
            $result = [
961
                'fileExists' => file_exists($imResult[3]),
962
                'outputFile' => $imResult[3],
963
                'referenceFile' => Environment::getFrameworkBasePath() . '/install/Resources/Public/Images/TestReference/Read-' . $inputFormat . '.jpg',
964
                'command' => $imageProcessor->IM_commands,
965
            ];
966
        } else {
967
            $result = [
968
                'status' => [$this->imageGenerationFailedMessage()],
969
                'command' => $imageProcessor->IM_commands,
970
            ];
971
        }
972
        return $this->getImageTestResponse($result);
973
    }
974
975
    /**
976
     * Get details about all configured database connections
977
     *
978
     * @return array
979
     */
980
    protected function getDatabaseConnectionInformation(): array
981
    {
982
        $connectionInfos = [];
983
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
984
        foreach ($connectionPool->getConnectionNames() as $connectionName) {
985
            $connection = $connectionPool->getConnectionByName($connectionName);
986
            $connectionParameters = $connection->getParams();
987
            $connectionInfo = [
988
                'connectionName' => $connectionName,
989
                'version' => $connection->getServerVersion(),
990
                'databaseName' => $connection->getDatabase(),
991
                'username' => $connectionParameters['user'],
992
                'host' => $connectionParameters['host'],
993
                'port' => $connectionParameters['port'],
994
                'socket' => $connectionParameters['unix_socket'] ?? '',
995
                'numberOfTables' => count($connection->getSchemaManager()->listTableNames()),
996
                'numberOfMappedTables' => 0,
997
            ];
998
            if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
999
                && is_array($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
1000
            ) {
1001
                // Count number of array keys having $connectionName as value
1002
                $connectionInfo['numberOfMappedTables'] = count(array_intersect(
1003
                    $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'],
1004
                    [$connectionName]
1005
                ));
1006
            }
1007
            $connectionInfos[] = $connectionInfo;
1008
        }
1009
        return $connectionInfos;
1010
    }
1011
1012
    /**
1013
     * Get details about the application context
1014
     *
1015
     * @return array
1016
     */
1017
    protected function getApplicationContextInformation(): array
1018
    {
1019
        $applicationContext = Environment::getContext();
1020
        $status = $applicationContext->isProduction() ? InformationStatus::STATUS_OK : InformationStatus::STATUS_WARNING;
1021
1022
        return [
1023
            'context' => (string)$applicationContext,
1024
            'status' => $status,
1025
        ];
1026
    }
1027
1028
    /**
1029
     * Get sender address from configuration
1030
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
1031
     * If this setting is empty fall back to '[email protected]'
1032
     *
1033
     * @return string Returns an email address
1034
     */
1035
    protected function getSenderEmailAddress(): string
1036
    {
1037
        return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'])
1038
            ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "?"; newline found
Loading history...
1039
            : '[email protected]';
0 ignored issues
show
Coding Style introduced by
Expected 1 space before ":"; newline found
Loading history...
1040
    }
1041
1042
    /**
1043
     * Gets sender name from configuration
1044
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
1045
     * If this setting is empty, it falls back to a default string.
1046
     *
1047
     * @return string
1048
     */
1049
    protected function getSenderEmailName(): string
1050
    {
1051
        return !empty($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'])
1052
            ? $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "?"; newline found
Loading history...
1053
            : 'TYPO3 CMS install tool';
0 ignored issues
show
Coding Style introduced by
Expected 1 space before ":"; newline found
Loading history...
1054
    }
1055
1056
    /**
1057
     * Gets email subject from configuration
1058
     * ['TYPO3_CONF_VARS']['SYS']['sitename']
1059
     * If this setting is empty, it falls back to a default string.
1060
     *
1061
     * @return string
1062
     */
1063
    protected function getEmailSubject(): string
1064
    {
1065
        $name = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'])
1066
            ? ' from site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"'
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "?"; newline found
Loading history...
1067
            : '';
0 ignored issues
show
Coding Style introduced by
Expected 1 space before ":"; newline found
Loading history...
1068
        return 'Test TYPO3 CMS mail delivery' . $name;
1069
    }
1070
1071
    /**
1072
     * Create a JsonResponse from single image tests
1073
     *
1074
     * @param array $testResult
1075
     * @return ResponseInterface
1076
     */
1077
    protected function getImageTestResponse(array $testResult): ResponseInterface
1078
    {
1079
        $responseData = [
1080
            'success' => true,
1081
        ];
1082
        foreach ($testResult as $resultKey => $value) {
1083
            if ($resultKey === 'referenceFile') {
1084
                $fileExt = end(explode('.', $testResult['referenceFile']));
1085
                $responseData['referenceFile'] = 'data:image/' . $fileExt . ';base64,' . base64_encode(file_get_contents($testResult['referenceFile']));
1086
            } elseif ($resultKey === 'outputFile') {
1087
                $fileExt = end(explode('.', $testResult['outputFile']));
1088
                $responseData['outputFile'] = 'data:image/' . $fileExt . ';base64,' . base64_encode(file_get_contents($testResult['outputFile']));
1089
            } else {
1090
                $responseData[$resultKey] = $value;
1091
            }
1092
        }
1093
        return new JsonResponse($responseData);
1094
    }
1095
1096
    /**
1097
     * Create a 'image generation failed' message
1098
     *
1099
     * @return FlashMessage
1100
     */
1101
    protected function imageGenerationFailedMessage(): FlashMessage
1102
    {
1103
        return new FlashMessage(
1104
            'ImageMagick / GraphicsMagick handling is enabled, but the execute'
1105
            . ' command returned an error. Please check your settings, especially'
1106
            . ' [\'GFX\'][\'processor_path\'] and [\'GFX\'][\'processor_path_lzw\'] and ensure Ghostscript is installed on your server.',
1107
            'Image generation failed',
1108
            FlashMessage::ERROR
1109
        );
1110
    }
1111
1112
    /**
1113
     * Find out if ImageMagick or GraphicsMagick is enabled and set up
1114
     *
1115
     * @return bool TRUE if enabled and path is set
1116
     */
1117
    protected function isImageMagickEnabledAndConfigured(): bool
1118
    {
1119
        $enabled = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'];
1120
        $path = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'];
1121
        return $enabled && $path;
1122
    }
1123
1124
    /**
1125
     * Create a 'imageMagick disabled' message
1126
     *
1127
     * @return FlashMessage
1128
     */
1129
    protected function imageMagickDisabledMessage(): FlashMessage
1130
    {
1131
        return new FlashMessage(
1132
            'ImageMagick / GraphicsMagick handling is disabled or not configured correctly.',
1133
            'Tests not executed',
1134
            FlashMessage::ERROR
1135
        );
1136
    }
1137
1138
    /**
1139
     * Return the temp image dir.
1140
     * If not exist it will be created
1141
     *
1142
     * @return string
1143
     */
1144
    protected function getImagesPath(): string
1145
    {
1146
        $imagePath = Environment::getPublicPath() . '/typo3temp/assets/images/';
1147
        if (!is_dir($imagePath)) {
1148
            GeneralUtility::mkdir_deep($imagePath);
1149
        }
1150
        return $imagePath;
1151
    }
1152
}
1153