From b5ca22f3165b1940d66b125ce60c5365275dcd22 Mon Sep 17 00:00:00 2001
From: Jochen Roth <jochen.roth@b13.com>
Date: Mon, 9 Aug 2021 15:28:36 +0200
Subject: [PATCH] [BUGFIX] Add fallback for undefined array keys in cli

Cli commands were fixed by adding a fallback where
undefined array key warning occured. Added tests
as well to make sure it will work ever after.

Resolves: #94763
Releases: master
Change-Id: I76e91d61649b5e2c54b83f737e46d679df2526a5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70306
Tested-by: core-ci <typo3@b13.com>
Tested-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 composer.json                                 |  1 +
 composer.lock                                 | 49 +++++++++++-
 .../Tests/Acceptance/Application.suite.yml    |  1 +
 .../Application/Cli/CommandCest.php           | 74 +++++++++++++++++++
 .../Application/DbCheck/DbCheckModuleCest.php |  4 +-
 .../Classes/Command/LanguagePackCommand.php   |  2 +-
 .../Classes/Command/ListSysLogCommand.php     |  2 +-
 .../Command/MissingRelationsCommand.php       |  2 +-
 .../Classes/Command/OrphanRecordsCommand.php  |  2 +-
 .../Classes/Service/IntegrityService.php      |  2 +-
 .../WorkspaceVersionRecordsCommand.php        |  2 +-
 11 files changed, 132 insertions(+), 9 deletions(-)
 create mode 100644 typo3/sysext/core/Tests/Acceptance/Application/Cli/CommandCest.php

diff --git a/composer.json b/composer.json
index 1cf3959f5317..20f6b6f6a5f2 100644
--- a/composer.json
+++ b/composer.json
@@ -92,6 +92,7 @@
 		"codeception/codeception": "^4.1.22",
 		"codeception/lib-asserts": "^1.13.2",
 		"codeception/module-asserts": "^1.3.1",
+		"codeception/module-cli": "^1.1",
 		"codeception/module-filesystem": "^1.0.3",
 		"codeception/module-webdriver": "^1.2.1",
 		"composer/package-versions-deprecated": "^1.11.99.2",
diff --git a/composer.lock b/composer.lock
index e3dfdf304e40..b7e5ab19f553 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "5f735b56f523e7891b4c7a42c483dcdb",
+    "content-hash": "18ef972ae8ceffb3b4f8e1a1aef18269",
     "packages": [
         {
             "name": "bacon/bacon-qr-code",
@@ -5445,6 +5445,53 @@
             },
             "time": "2020-10-21T16:48:15+00:00"
         },
+        {
+            "name": "codeception/module-cli",
+            "version": "1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Codeception/module-cli.git",
+                "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Codeception/module-cli/zipball/1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f",
+                "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f",
+                "shasum": ""
+            },
+            "require": {
+                "codeception/codeception": "*@dev",
+                "php": ">=5.6.0 <9.0"
+            },
+            "conflict": {
+                "codeception/codeception": "<4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michael Bodnarchuk"
+                }
+            ],
+            "description": "Codeception module for testing basic shell commands and shell output",
+            "homepage": "http://codeception.com/",
+            "keywords": [
+                "codeception"
+            ],
+            "support": {
+                "issues": "https://github.com/Codeception/module-cli/issues",
+                "source": "https://github.com/Codeception/module-cli/tree/1.1.1"
+            },
+            "time": "2020-12-26T16:56:19+00:00"
+        },
         {
             "name": "codeception/module-filesystem",
             "version": "1.0.3",
diff --git a/typo3/sysext/core/Tests/Acceptance/Application.suite.yml b/typo3/sysext/core/Tests/Acceptance/Application.suite.yml
index fada46475782..a9a73cf344fa 100644
--- a/typo3/sysext/core/Tests/Acceptance/Application.suite.yml
+++ b/typo3/sysext/core/Tests/Acceptance/Application.suite.yml
@@ -13,6 +13,7 @@ modules:
             editor: ff83dfd81e20b34c27d3e97771a4525a
             admin: 886526ce72b86870739cc41991144ec1
     - Asserts
+    - Codeception\Module\Cli
 
 extensions:
     enabled:
diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Cli/CommandCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Cli/CommandCest.php
new file mode 100644
index 000000000000..7ddaac9926b1
--- /dev/null
+++ b/typo3/sysext/core/Tests/Acceptance/Application/Cli/CommandCest.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Cli;
+
+use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester;
+
+/**
+ * Tests the styleguide backend module can be loaded
+ */
+class CommandCest
+{
+    protected string $typo3Cli = '../../../../bin/typo3 ';
+
+    /**
+     * @param ApplicationTester $I
+     */
+    public function runCommand(ApplicationTester $I): void
+    {
+        foreach ($this->commandTestDataProvider() as $command => $expectedCode) {
+            $I->runShellCommand($this->typo3Cli . $command, false);
+            $I->seeResultCodeIs($expectedCode);
+        }
+    }
+
+    /**
+     * Test cli commands for their exit status
+     *
+     * 'site:show' and 'mailer:spool:send' fail
+     * due to missing configuration or unpredictable
+     * params.
+     */
+    protected function commandTestDataProvider(): array
+    {
+        return [
+            'cleanup:flexforms' => 0,
+            'cleanup:deletedrecords' => 0,
+            'cleanup:multiplereferencedfiles --dry-run --update-refindex' => 0,
+            'cleanup:lostfiles --dry-run --update-refindex' => 0,
+            'cleanup:missingfiles --dry-run --update-refindex' => 0,
+            'cleanup:missingrelations --dry-run --update-refindex' => 0,
+            'cleanup:orphanrecords' => 0,
+            'cleanup:previewlinks' => 0,
+            'cleanup:versions' => 0,
+            'extension:list' => 0,
+            'extension:deactivate workspaces' => 0,
+            'extension:activate workspaces' => 0,
+            'language:update' => 0,
+            'mailer:spool:send' => 1,
+            'redirects:checkintegrity' => 0,
+            'redirects:cleanup' => 0,
+            'referenceindex:update --check' => 0,
+            'scheduler:run' => 0,
+            'site:list' => 0,
+            'site:show' => 1,
+            'syslog:list' => 0,
+            'upgrade:list' => 0,
+        ];
+    }
+}
diff --git a/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php b/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php
index c70e1975ebb9..3c7aa211603b 100644
--- a/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php
+++ b/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php
@@ -105,10 +105,10 @@ class DbCheckModuleCest
         $this->goToPageAndSeeHeadline($I, 'Manage Reference Index', 'Manage Reference Index');
 
         $I->click('Check reference index');
-        $I->waitForElement('.alert-danger');
+        $I->waitForElement('.alert');
 
         $I->click('Update reference index');
-        $I->waitForElement('.alert-danger');
+        $I->waitForElement('.alert');
 
         $I->click('Check reference index');
         $I->waitForElement('.alert-success');
diff --git a/typo3/sysext/install/Classes/Command/LanguagePackCommand.php b/typo3/sysext/install/Classes/Command/LanguagePackCommand.php
index 70ea56423cdc..2ee1d110af23 100644
--- a/typo3/sysext/install/Classes/Command/LanguagePackCommand.php
+++ b/typo3/sysext/install/Classes/Command/LanguagePackCommand.php
@@ -126,7 +126,7 @@ class LanguagePackCommand extends Command
         }
         $languagePackService->setLastUpdatedIsoCode($isos);
         $progressBar->finish();
-
+        $output->writeln('');
         // Flush language cache
         GeneralUtility::makeInstance(CacheManager::class)->getCache('l10n')->flush();
 
diff --git a/typo3/sysext/lowlevel/Classes/Command/ListSysLogCommand.php b/typo3/sysext/lowlevel/Classes/Command/ListSysLogCommand.php
index b5a9e8c5c814..e8d62e242c96 100644
--- a/typo3/sysext/lowlevel/Classes/Command/ListSysLogCommand.php
+++ b/typo3/sysext/lowlevel/Classes/Command/ListSysLogCommand.php
@@ -89,7 +89,7 @@ class ListSysLogCommand extends Command
                 $row['uid'],
                 BackendUtility::datetime($row['tstamp']),
                 $userInformation,
-                sprintf($row['details'], $logData[0], $logData[1], $logData[2], $logData[3], $logData[4], $logData[5])
+                sprintf($row['details'], ($logData[0] ?? ''), ($logData[1] ?? ''), ($logData[2] ?? ''), ($logData[3] ?? ''), ($logData[4] ?? ''), ($logData[5] ?? ''))
             ];
 
             if ($showDetails) {
diff --git a/typo3/sysext/lowlevel/Classes/Command/MissingRelationsCommand.php b/typo3/sysext/lowlevel/Classes/Command/MissingRelationsCommand.php
index db1ec7aed598..a91680560cbf 100644
--- a/typo3/sysext/lowlevel/Classes/Command/MissingRelationsCommand.php
+++ b/typo3/sysext/lowlevel/Classes/Command/MissingRelationsCommand.php
@@ -278,7 +278,7 @@ If you want to get more detailed information, use the --verbose option.')
             // Compile info string for location of reference:
             $infoString = $this->formatReferenceIndexEntryToString($rec);
             // Handle missing file:
-            if ($existingRecords[$idx]['uid']) {
+            if ($existingRecords[$idx]['uid'] ?? false) {
                 // Record exists, but is a reference to an offline version
                 if ((int)($existingRecords[$idx]['t3ver_oid'] ?? 0) > 0) {
                     if ($isSoftReference) {
diff --git a/typo3/sysext/lowlevel/Classes/Command/OrphanRecordsCommand.php b/typo3/sysext/lowlevel/Classes/Command/OrphanRecordsCommand.php
index 32e964ab1971..1aed3ab91c79 100644
--- a/typo3/sysext/lowlevel/Classes/Command/OrphanRecordsCommand.php
+++ b/typo3/sysext/lowlevel/Classes/Command/OrphanRecordsCommand.php
@@ -99,7 +99,7 @@ Manual repair suggestions:
         $orphans = [];
         foreach (array_keys($GLOBALS['TCA']) as $tableName) {
             $idList = [0];
-            if (is_array($allRecords[$tableName]) && !empty($allRecords[$tableName])) {
+            if (is_array($allRecords[$tableName] ?? false) && !empty($allRecords[$tableName])) {
                 $idList = $allRecords[$tableName];
             }
             // Select all records that are NOT connected
diff --git a/typo3/sysext/redirects/Classes/Service/IntegrityService.php b/typo3/sysext/redirects/Classes/Service/IntegrityService.php
index af7fdb301582..2627430cb154 100644
--- a/typo3/sysext/redirects/Classes/Service/IntegrityService.php
+++ b/typo3/sysext/redirects/Classes/Service/IntegrityService.php
@@ -126,7 +126,7 @@ class IntegrityService
         $row = $queryBuilder->execute()->fetchAssociative();
 
         $subPages = $this->getSlugsOfSubPages($site->getRootPageId());
-        $pages = array_merge([$site->getBase()->getPath() . '/', $row['slug']], $subPages);
+        $pages = array_merge([$site->getBase()->getPath() . '/', ($row['slug'] ?? '')], $subPages);
         return array_unique($pages);
     }
 
diff --git a/typo3/sysext/workspaces/Classes/Command/WorkspaceVersionRecordsCommand.php b/typo3/sysext/workspaces/Classes/Command/WorkspaceVersionRecordsCommand.php
index 7a47e7d65bf8..36ee89f7e5c9 100644
--- a/typo3/sysext/workspaces/Classes/Command/WorkspaceVersionRecordsCommand.php
+++ b/typo3/sysext/workspaces/Classes/Command/WorkspaceVersionRecordsCommand.php
@@ -298,7 +298,7 @@ class WorkspaceVersionRecordsCommand extends Command
                         ->execute();
                     while ($rowSub = $result->fetchAssociative()) {
                         // Add any versions of those records
-                        $versions = BackendUtility::selectVersionsOfRecord($tableName, $rowSub['uid'], 'uid,t3ver_wsid' . ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] : ''), null, true);
+                        $versions = BackendUtility::selectVersionsOfRecord($tableName, $rowSub['uid'], 'uid,t3ver_wsid' . (($GLOBALS['TCA'][$tableName]['ctrl']['delete'] ?? false) ? ',' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] : ''), null, true);
                         if (is_array($versions)) {
                             foreach ($versions as $verRec) {
                                 if (!$verRec['_CURRENT_VERSION']) {
-- 
GitLab