diff --git a/typo3/sysext/core/Classes/Database/ReferenceIndex.php b/typo3/sysext/core/Classes/Database/ReferenceIndex.php index 5caa60870526492fadb5fbcfc2ac3f5ee7603ea8..4a9b26b4c434569fe3aa45499ce04277afe1d60f 100644 --- a/typo3/sysext/core/Classes/Database/ReferenceIndex.php +++ b/typo3/sysext/core/Classes/Database/ReferenceIndex.php @@ -408,7 +408,7 @@ class ReferenceIndex implements LoggerAwareInterface foreach ($keys as $spKey => $elements) { if (is_array($elements)) { foreach ($elements as $subKey => $el) { - if (is_array($el['subst'])) { + if (is_array($el['subst'] ?? false)) { switch ((string)$el['subst']['type']) { case 'db': [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']); diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/DbCheck/DbCheckModuleCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/DbCheck/DbCheckModuleCest.php new file mode 100644 index 0000000000000000000000000000000000000000..617fa77510f560bf52d9d63d05e62be82824a078 --- /dev/null +++ b/typo3/sysext/core/Tests/Acceptance/Backend/DbCheck/DbCheckModuleCest.php @@ -0,0 +1,189 @@ +<?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\Backend\DbCheck; + +use Facebook\WebDriver\Remote\RemoteWebDriver; +use Facebook\WebDriver\Remote\RemoteWebElement; +use TYPO3\CMS\Core\Tests\Acceptance\Support\BackendTester; +use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog; + +/** + * Tests concerning Reports Module + */ +class DbCheckModuleCest +{ + protected static string $defaultDashboardTitle = 'My Dashboard'; + + /** + * @param BackendTester $I + */ + public function _before(BackendTester $I) + { + $I->useExistingSession('admin'); + $I->click('#system_dbint'); + $I->switchToContentFrame(); + } + + /** + * @param BackendTester $I + */ + public function seeOverview(BackendTester $I) + { + $I->see('Database integrity check', 'h1'); + $I->see('Records Statistics', 'a'); + $I->see('Relations', 'a'); + $I->see('Search', 'a'); + $I->see('Check and update global reference index', 'a'); + } + + /** + * @param BackendTester $I + */ + public function seeRecordStatistics(BackendTester $I) + { + $this->goToPageAndSeeHeadline($I, 'Record Statistics', 'Records Statistics'); + + foreach ($this->recordStatisticsDataProvider() as $statistic) { + $count = $this->getCountByRowName($I, $statistic['name'])->getText(); + // Use >= here to make sure we don't get in trouble with other tests creating db entries + $I->assertGreaterThanOrEqual($statistic['count'], $count); + } + } + + /** + * @param BackendTester $I + */ + public function seeDatabaseRelations(BackendTester $I) + { + $this->goToPageAndSeeHeadline($I, 'Database Relations', 'Relations'); + $I->see('Select fields', 'h2'); + $I->see('Group fields', 'h2'); + } + + /** + * @param BackendTester $I + */ + public function seeFullSearch(BackendTester $I, ModalDialog $modalDialog) + { + $this->goToPageAndSeeHeadline($I, 'Full search', 'Search whole Database'); + $I->see('Search options', 'h2'); + $I->see('Result', 'h2'); + + // Fill in search phrase and check results + $I->fillField('input[name="SET[sword]"]', 'styleguide demo group 1'); + $I->click('Search All Records'); + $I->see('styleguide demo group 1', 'td'); + $I->dontSee('styleguide demo group 2', 'td'); + + // Open info modal and see text in card + $I->click('a[data-dispatch-args-list]'); + $modalDialog->canSeeDialog(); + $I->switchToIFrame('.modal-iframe'); + $I->see('styleguide demo group 1', '.card-title'); + } + + /** + * @param BackendTester $I + */ + public function seeManageReferenceIndex(BackendTester $I) + { + $this->goToPageAndSeeHeadline($I, 'Manage Reference Index', 'Manage Reference Index'); + + $I->click('Check reference index'); + $I->waitForElement('.alert-danger'); + + $I->click('Update reference index'); + $I->waitForElement('.alert-danger'); + + $I->click('Check reference index'); + $I->waitForElement('.alert-success'); + $I->see('Index Integrity was perfect!', '.alert-success'); + + $I->click('Update reference index'); + $I->see('Index Integrity was perfect!', '.alert-success'); + } + + /** + * @return array[] + */ + protected function recordStatisticsDataProvider(): array + { + return [ + [ + 'name' => 'Total number of default language pages', + 'count' => 84, + ], + [ + 'name' => 'Total number of translated pages', + 'count' => 132, + ], + [ + 'name' => 'Marked-deleted pages', + 'count' => 0, + ], + [ + 'name' => 'Hidden pages', + 'count' => 1, + ], + [ + 'name' => 'Standard', + 'count' => 1, + ], + [ + 'name' => 'Backend User Section', + 'count' => 0, + ], + [ + 'name' => 'Link to External URL', + 'count' => 0, + ], + ]; + } + + /** + * @param string $select + * @param string $headline + * @param BackendTester $I + */ + protected function goToPageAndSeeHeadline(BackendTester $I, string $select, string $headline): void + { + $I->selectOption('select[name=DatabaseJumpMenu]', $select); + $I->see($headline, 'h1'); + } + + /** + * Find count of table row by name + * + * @param BackendTester $I + * @param string $fieldLabel + * @return RemoteWebElement + */ + protected function getCountByRowName(BackendTester $I, string $rowName, int $sibling = 1): RemoteWebElement + { + $I->comment('Get context for table row "' . $rowName . '"'); + return $I->executeInSelenium( + function (RemoteWebDriver $webDriver) use ($rowName, $sibling) { + return $webDriver->findElement( + \Facebook\WebDriver\WebDriverBy::xpath( + '//td[contains(text(),"' . $rowName . '")]/following-sibling::td[' . $sibling . ']' + ) + ); + } + ); + } +} diff --git a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php index 898d8705bd25b367138275143f4b872396857585..ec7de8e48804cbf501b09c18ec424285d4338526 100644 --- a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php +++ b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php @@ -360,11 +360,11 @@ class DatabaseIntegrityController } $submenu .= '</div>'; if ($this->MOD_SETTINGS['search'] === 'query') { - $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[search_query_smallparts]', $this->MOD_SETTINGS['search_query_smallparts'], '', '', 'id="checkSearch_query_smallparts"') . '<label class="form-check-label" for="checkSearch_query_smallparts">' . $lang->getLL('showSQL') . '</label></div>'; - $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[search_result_labels]', $this->MOD_SETTINGS['search_result_labels'], '', '', 'id="checkSearch_result_labels"') . '<label class="form-check-label" for="checkSearch_result_labels">' . $lang->getLL('useFormattedStrings') . '</label></div>'; - $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[labels_noprefix]', $this->MOD_SETTINGS['labels_noprefix'], '', '', 'id="checkLabels_noprefix"') . '<label class="form-check-label" for="checkLabels_noprefix">' . $lang->getLL('dontUseOrigValues') . '</label></div>'; - $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[options_sortlabel]', $this->MOD_SETTINGS['options_sortlabel'], '', '', 'id="checkOptions_sortlabel"') . '<label class="form-check-label" for="checkOptions_sortlabel">' . $lang->getLL('sortOptions') . '</label></div>'; - $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[show_deleted]', $this->MOD_SETTINGS['show_deleted'], '', '', 'id="checkShow_deleted"') . '<label class="form-check-label" for="checkShow_deleted">' . $lang->getLL('showDeleted') . '</label></div>'; + $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[search_query_smallparts]', $this->MOD_SETTINGS['search_query_smallparts'] ?? '', '', '', 'id="checkSearch_query_smallparts"') . '<label class="form-check-label" for="checkSearch_query_smallparts">' . $lang->getLL('showSQL') . '</label></div>'; + $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[search_result_labels]', $this->MOD_SETTINGS['search_result_labels'] ?? '', '', '', 'id="checkSearch_result_labels"') . '<label class="form-check-label" for="checkSearch_result_labels">' . $lang->getLL('useFormattedStrings') . '</label></div>'; + $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[labels_noprefix]', $this->MOD_SETTINGS['labels_noprefix'] ?? '', '', '', 'id="checkLabels_noprefix"') . '<label class="form-check-label" for="checkLabels_noprefix">' . $lang->getLL('dontUseOrigValues') . '</label></div>'; + $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[options_sortlabel]', $this->MOD_SETTINGS['options_sortlabel'] ?? '', '', '', 'id="checkOptions_sortlabel"') . '<label class="form-check-label" for="checkOptions_sortlabel">' . $lang->getLL('sortOptions') . '</label></div>'; + $submenu .= '<div class="form-check">' . BackendUtility::getFuncCheck(0, 'SET[show_deleted]', $this->MOD_SETTINGS['show_deleted'] ?? 0, '', '', 'id="checkShow_deleted"') . '<label class="form-check-label" for="checkShow_deleted">' . $lang->getLL('showDeleted') . '</label></div>'; } $this->view->assign('submenu', $submenu); $this->view->assign('searchMode', $searchMode); @@ -441,7 +441,7 @@ class DatabaseIntegrityController $countArr = $admin->countRecords($id_list); if (is_array($GLOBALS['TCA'])) { foreach ($GLOBALS['TCA'] as $t => $value) { - if ($GLOBALS['TCA'][$t]['ctrl']['hideTable']) { + if ($GLOBALS['TCA'][$t]['ctrl']['hideTable'] ?? false) { continue; } if ($t === 'pages' && $admin->getLostPagesList() !== '') { @@ -449,13 +449,13 @@ class DatabaseIntegrityController } else { $lostRecordCount = isset($admin->getLRecords()[$t]) ? count($admin->getLRecords()[$t]) : 0; } - if ($countArr['all'][$t]) { + if ($countArr['all'][$t] ?? false) { $theNumberOfRe = (int)$countArr['non_deleted'][$t] . '/' . $lostRecordCount; } else { $theNumberOfRe = ''; } $lr = ''; - if (is_array($admin->getLRecords()[$t])) { + if (is_array($admin->getLRecords()[$t] ?? false)) { foreach ($admin->getLRecords()[$t] as $data) { if (!GeneralUtility::inList($admin->getLostPagesList(), $data['pid'])) { $lr .= '<div class="record"><a href="' . htmlspecialchars((string)$this->uriBuilder->buildUriFromRoute('system_dbint') . '&SET[function]=records&fixLostRecords_table=' . $t . '&fixLostRecords_uid=' . $data['uid']) . '" title="' . htmlspecialchars($lang->getLL('fixLostRecord')) . '">' . $this->iconFactory->getIcon('status-dialog-error', Icon::SIZE_SMALL)->render() . '</a>uid:' . $data['uid'] . ', pid:' . $data['pid'] . ', ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(strip_tags($data['title']), 20)) . '</div>'; diff --git a/typo3/sysext/lowlevel/Classes/Database/QueryGenerator.php b/typo3/sysext/lowlevel/Classes/Database/QueryGenerator.php index 6ea7325f29f30831f2df6ae61344a6bec8fbac29..f9461fb4af66376b72256f748c7ea55ad7b8b2a3 100644 --- a/typo3/sysext/lowlevel/Classes/Database/QueryGenerator.php +++ b/typo3/sysext/lowlevel/Classes/Database/QueryGenerator.php @@ -318,7 +318,7 @@ class QueryGenerator $markup = []; $markup[] = '<div class="form-group">'; $markup[] = '<input placeholder="Search Word" class="form-control" type="search" name="SET[sword]" value="' - . htmlspecialchars($this->settings['sword']) . '">'; + . htmlspecialchars($this->settings['sword'] ?? '') . '">'; $markup[] = '</div>'; $markup[] = '<div class="form-group">'; $markup[] = '<input class="btn btn-default" type="submit" name="submit" value="Search All Records">'; @@ -337,13 +337,13 @@ class QueryGenerator $this->hookArray = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3lib_fullsearch'] ?? []; $msg = $this->procesStoreControl(); $userTsConfig = $this->getBackendUserAuthentication()->getTSConfig(); - if (!$userTsConfig['mod.']['dbint.']['disableStoreControl']) { + if (!($userTsConfig['mod.']['dbint.']['disableStoreControl'] ?? false)) { $output .= '<h2>Load/Save Query</h2>'; $output .= '<div>' . $this->makeStoreControl() . '</div>'; $output .= $msg; } // Query Maker: - $this->init('queryConfig', $this->settings['queryTable'], '', $this->settings); + $this->init('queryConfig', $this->settings['queryTable'] ?? '', '', $this->settings); if ($this->formName) { $this->setFormName($this->formName); } @@ -379,7 +379,7 @@ class QueryGenerator $fullQueryString = $selectQueryString; $dataRows = $connection->executeQuery($selectQueryString)->fetchAll(); } - if (!$userTsConfig['mod.']['dbint.']['disableShowSQLQuery']) { + if (!($userTsConfig['mod.']['dbint.']['disableShowSQLQuery'] ?? false)) { $output .= '<h2>SQL query</h2><div><pre>' . htmlspecialchars($fullQueryString) . '</pre></div>'; } $cPR = $this->getQueryResultCode($mQ, $dataRows, $this->table); @@ -405,7 +405,7 @@ class QueryGenerator */ public function search() { - $swords = $this->settings['sword']; + $swords = $this->settings['sword'] ?? ''; $out = ''; if ($swords) { foreach ($GLOBALS['TCA'] as $table => $value) { @@ -547,7 +547,7 @@ class QueryGenerator $storeArray = [ '0' => '[New]' ]; - $savedStoreArray = unserialize($this->settings['storeArray'], ['allowed_classes' => false]); + $savedStoreArray = unserialize($this->settings['storeArray'] ?? '', ['allowed_classes' => false]); if (is_array($savedStoreArray)) { $storeArray = array_merge($storeArray, $savedStoreArray); } @@ -667,14 +667,14 @@ class QueryGenerator $languageService = $this->getLanguageService(); $flashMessage = null; $storeArray = $this->initStoreArray(); - $storeQueryConfigs = unserialize($this->settings['storeQueryConfigs'], ['allowed_classes' => false]); + $storeQueryConfigs = unserialize($this->settings['storeQueryConfigs'] ?? '', ['allowed_classes' => false]); $storeControl = GeneralUtility::_GP('storeControl'); - $storeIndex = (int)$storeControl['STORE']; + $storeIndex = (int)($storeControl['STORE'] ?? 0); $saveStoreArray = 0; $writeArray = []; $msg = ''; if (is_array($storeControl)) { - if ($storeControl['LOAD']) { + if ($storeControl['LOAD'] ?? false) { if ($storeIndex > 0) { $writeArray = $this->loadStoreQueryConfigs($storeQueryConfigs, $storeIndex, $writeArray); $saveStoreArray = 1; @@ -698,7 +698,7 @@ class QueryGenerator ); } } - } elseif ($storeControl['SAVE']) { + } elseif ($storeControl['SAVE'] ?? false) { if ($storeIndex < 0) { $qOK = $this->saveQueryInAction(abs($storeIndex)); if ($qOK) { @@ -731,7 +731,7 @@ class QueryGenerator ); } } - } elseif ($storeControl['REMOVE']) { + } elseif ($storeControl['REMOVE'] ?? false) { if ($storeIndex > 0) { $flashMessage = GeneralUtility::makeInstance( FlashMessage::class, @@ -788,7 +788,7 @@ class QueryGenerator foreach ($dataRows as $dataRow) { $rowArr[] = $this->resultRowDisplay($dataRow, $GLOBALS['TCA'][$table], $table); } - if (is_array($this->hookArray['beforeResultTable'])) { + if (is_array($this->hookArray['beforeResultTable'] ?? false)) { foreach ($this->hookArray['beforeResultTable'] as $_funcRef) { $out .= GeneralUtility::callUserFunction($_funcRef, $this->settings); } @@ -882,12 +882,12 @@ class QueryGenerator $languageService = $this->getLanguageService(); $out = '<tr>'; foreach ($row as $fieldName => $fieldValue) { - if (GeneralUtility::inList($this->settings['queryFields'], $fieldName) - || !$this->settings['queryFields'] + if (GeneralUtility::inList($this->settings['queryFields'] ?? '', $fieldName) + || !($this->settings['queryFields'] ?? false) && $fieldName !== 'pid' && $fieldName !== 'deleted' ) { - if ($this->settings['search_result_labels']) { + if ($this->settings['search_result_labels'] ?? false) { $fVnew = $this->getProcessedValueExtra($table, $fieldName, $fieldValue, $conf, '<br />'); } else { $fVnew = htmlspecialchars($fieldValue); @@ -898,7 +898,7 @@ class QueryGenerator $out .= '<td>'; $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - if (!$row['deleted']) { + if (!($row['deleted'] ?? false)) { $out .= '<div class="btn-group" role="group">'; $url = (string)$uriBuilder->buildUriFromRoute('record_edit', [ 'edit' => [ @@ -955,7 +955,7 @@ class QueryGenerator $out .= '</div>'; } $_params = [$table => $row]; - if (is_array($this->hookArray['additionalButtons'])) { + if (is_array($this->hookArray['additionalButtons'] ?? false)) { foreach ($this->hookArray['additionalButtons'] as $_funcRef) { $out .= GeneralUtility::callUserFunction($_funcRef, $_params); } @@ -1357,12 +1357,12 @@ class QueryGenerator $tableHeader[] = '<thead><tr>'; // Iterate over given columns foreach ($row as $fieldName => $fieldValue) { - if (GeneralUtility::inList($this->settings['queryFields'], $fieldName) - || !$this->settings['queryFields'] + if (GeneralUtility::inList($this->settings['queryFields'] ?? '', $fieldName) + || !($this->settings['queryFields'] ?? false) && $fieldName !== 'pid' && $fieldName !== 'deleted' ) { - if ($this->settings['search_result_labels']) { + if ($this->settings['search_result_labels'] ?? false) { $title = $languageService->sL($conf['columns'][$fieldName]['label'] ?: $fieldName); } else { @@ -1411,7 +1411,7 @@ class QueryGenerator if ($GLOBALS['TCA'][$this->table]['ctrl']['cruser_id']) { $fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['cruser_id']; } - if ($GLOBALS['TCA'][$this->table]['ctrl']['sortby']) { + if ($GLOBALS['TCA'][$this->table]['ctrl']['sortby'] ?? false) { $fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['sortby']; } } @@ -1429,25 +1429,25 @@ class QueryGenerator protected function init($name, $table, $fieldList = '', array $settings = []) { // Analysing the fields in the table. - if (is_array($GLOBALS['TCA'][$table])) { + if (is_array($GLOBALS['TCA'][$table] ?? false)) { $this->name = $name; $this->table = $table; $this->fieldList = $fieldList ?: $this->makeFieldList(); $this->settings = $settings; $fieldArr = GeneralUtility::trimExplode(',', $this->fieldList, true); foreach ($fieldArr as $fieldName) { - $fC = $GLOBALS['TCA'][$this->table]['columns'][$fieldName]; - $this->fields[$fieldName] = $fC['config']; - $this->fields[$fieldName]['exclude'] = $fC['exclude']; - if ($this->fields[$fieldName]['type'] === 'user' && !isset($this->fields[$fieldName]['type']['userFunc']) - || $this->fields[$fieldName]['type'] === 'none' + $fC = $GLOBALS['TCA'][$this->table]['columns'][$fieldName] ?? []; + $this->fields[$fieldName] = $fC['config'] ?? []; + $this->fields[$fieldName]['exclude'] = $fC['exclude'] ?? ''; + if (($this->fields[$fieldName]['type'] ?? '') === 'user' && !isset($this->fields[$fieldName]['type']['userFunc']) + || ($this->fields[$fieldName]['type'] ?? '') === 'none' ) { // Do not list type=none "virtual" fields or query them from db, // and if type is user without defined userFunc unset($this->fields[$fieldName]); continue; } - if (is_array($fC) && $fC['label']) { + if (is_array($fC) && ($fC['label'] ?? false)) { $this->fields[$fieldName]['label'] = rtrim(trim($this->getLanguageService()->sL($fC['label'])), ':'); switch ($this->fields[$fieldName]['type']) { case 'input': @@ -1473,10 +1473,10 @@ class QueryGenerator break; case 'select': $this->fields[$fieldName]['type'] = 'multiple'; - if ($this->fields[$fieldName]['foreign_table']) { + if ($this->fields[$fieldName]['foreign_table'] ?? false) { $this->fields[$fieldName]['type'] = 'relation'; } - if ($this->fields[$fieldName]['special']) { + if ($this->fields[$fieldName]['special'] ?? false) { $this->fields[$fieldName]['type'] = 'text'; } break; @@ -1583,7 +1583,7 @@ class QueryGenerator $this->queryConfig = $qC; $POST = GeneralUtility::_POST(); // If delete... - if ($POST['qG_del']) { + if ($POST['qG_del'] ?? false) { // Initialize array to work on, save special parameters $ssArr = $this->getSubscript($POST['qG_del']); $workArr = &$this->queryConfig; @@ -1601,7 +1601,7 @@ class QueryGenerator } } // If insert... - if ($POST['qG_ins']) { + if ($POST['qG_ins'] ?? false) { // Initialize array to work on, save special parameters $ssArr = $this->getSubscript($POST['qG_ins']); $workArr = &$this->queryConfig; @@ -1620,7 +1620,7 @@ class QueryGenerator $workArr[$ssArr[$i] + 1]['type'] = 'FIELD_'; } // If move up... - if ($POST['qG_up']) { + if ($POST['qG_up'] ?? false) { // Initialize array to work on $ssArr = $this->getSubscript($POST['qG_up']); $workArr = &$this->queryConfig; @@ -1635,7 +1635,7 @@ class QueryGenerator $workArr[$ssArr[$i] - 1] = $qG_tmp; } // If new level... - if ($POST['qG_nl']) { + if ($POST['qG_nl'] ?? false) { // Initialize array to work on $ssArr = $this->getSubscript($POST['qG_nl']); $workArr = &$this->queryConfig; @@ -1657,7 +1657,7 @@ class QueryGenerator } } // If collapse level... - if ($POST['qG_remnl']) { + if ($POST['qG_remnl'] ?? false) { // Initialize array to work on $ssArr = $this->getSubscript($POST['qG_remnl']); $workArr = &$this->queryConfig; @@ -2535,7 +2535,7 @@ class QueryGenerator $userTsConfig = $this->getBackendUserAuthentication()->getTSConfig(); // Make output - if (in_array('table', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableSelectATable']) { + if (in_array('table', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableSelectATable'] ?? false)) { $out[] = '<div class="form-group">'; $out[] = ' <label for="SET[queryTable]">Select a table:</label>'; $out[] = $this->mkTableSelect('SET[queryTable]', $this->table); @@ -2543,16 +2543,16 @@ class QueryGenerator } if ($this->table) { // Init fields: - $this->setAndCleanUpExternalLists('queryFields', $modSettings['queryFields'], 'uid,' . $this->getLabelCol()); - $this->setAndCleanUpExternalLists('queryGroup', $modSettings['queryGroup']); - $this->setAndCleanUpExternalLists('queryOrder', $modSettings['queryOrder'] . ',' . $modSettings['queryOrder2']); + $this->setAndCleanUpExternalLists('queryFields', $modSettings['queryFields'] ?? '', 'uid,' . $this->getLabelCol()); + $this->setAndCleanUpExternalLists('queryGroup', $modSettings['queryGroup'] ?? ''); + $this->setAndCleanUpExternalLists('queryOrder', ($modSettings['queryOrder'] ?? '') . ',' . ($modSettings['queryOrder2'] ?? '')); // Limit: - $this->extFieldLists['queryLimit'] = $modSettings['queryLimit']; + $this->extFieldLists['queryLimit'] = $modSettings['queryLimit'] ?? ''; if (!$this->extFieldLists['queryLimit']) { $this->extFieldLists['queryLimit'] = 100; } $parts = GeneralUtility::intExplode(',', $this->extFieldLists['queryLimit']); - if ($parts[1]) { + if ($parts[1] ?? false) { $this->limitBegin = $parts[0]; $this->limitLength = $parts[1]; } else { @@ -2570,35 +2570,35 @@ class QueryGenerator $this->extFieldLists['queryOrder_SQL'] = implode(',', $reList); } // Query Generator: - $this->procesData($modSettings['queryConfig'] ? unserialize($modSettings['queryConfig'], ['allowed_classes' => false]) : []); + $this->procesData(($modSettings['queryConfig'] ?? false) ? unserialize($modSettings['queryConfig'] ?? '', ['allowed_classes' => false]) : []); $this->queryConfig = $this->cleanUpQueryConfig($this->queryConfig); $this->enableQueryParts = (bool)$modSettings['search_query_smallparts']; $codeArr = $this->getFormElements(); $queryCode = $this->printCodeArray($codeArr); - if (in_array('fields', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableSelectFields']) { + if (in_array('fields', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableSelectFields'] ?? false)) { $out[] = '<div class="form-group form-group-with-button-addon">'; $out[] = ' <label for="SET[queryFields]">Select fields:</label>'; $out[] = $this->mkFieldToInputSelect('SET[queryFields]', $this->extFieldLists['queryFields']); $out[] = '</div>'; } - if (in_array('query', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableMakeQuery']) { + if (in_array('query', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableMakeQuery'] ?? false)) { $out[] = '<div class="form-group">'; $out[] = ' <label>Make Query:</label>'; $out[] = $queryCode; $out[] = '</div>'; } - if (in_array('group', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableGroupBy']) { + if (in_array('group', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableGroupBy'] ?? false)) { $out[] = '<div class="form-group form-inline">'; $out[] = ' <label for="SET[queryGroup]">Group By:</label>'; $out[] = $this->mkTypeSelect('SET[queryGroup]', $this->extFieldLists['queryGroup'], ''); $out[] = '</div>'; } - if (in_array('order', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableOrderBy']) { + if (in_array('order', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableOrderBy'] ?? false)) { $orderByArr = explode(',', $this->extFieldLists['queryOrder']); $orderBy = []; $orderBy[] = $this->mkTypeSelect('SET[queryOrder]', $orderByArr[0], ''); $orderBy[] = '<div class="form-check">'; - $orderBy[] = BackendUtility::getFuncCheck(0, 'SET[queryOrderDesc]', $modSettings['queryOrderDesc'], '', '', 'id="checkQueryOrderDesc"'); + $orderBy[] = BackendUtility::getFuncCheck(0, 'SET[queryOrderDesc]', $modSettings['queryOrderDesc'] ?? '', '', '', 'id="checkQueryOrderDesc"'); $orderBy[] = ' <label class="form-check-label" for="checkQueryOrderDesc">Descending</label>'; $orderBy[] = '</div>'; @@ -2614,7 +2614,7 @@ class QueryGenerator $out[] = implode(LF, $orderBy); $out[] = '</div>'; } - if (in_array('limit', $enableArr) && !$userTsConfig['mod.']['dbint.']['disableLimit']) { + if (in_array('limit', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableLimit'] ?? false)) { $limit = []; $limit[] = '<div class="input-group">'; $limit[] = ' <span class="input-group-btn">'; diff --git a/typo3/sysext/lowlevel/Classes/Integrity/DatabaseIntegrityCheck.php b/typo3/sysext/lowlevel/Classes/Integrity/DatabaseIntegrityCheck.php index 3efc373bf5efc73c784754ef6fba29957e600074..dc722272bb37fd2f3fe262cdbc3c8b82d4448722 100644 --- a/typo3/sysext/lowlevel/Classes/Integrity/DatabaseIntegrityCheck.php +++ b/typo3/sysext/lowlevel/Classes/Integrity/DatabaseIntegrityCheck.php @@ -147,9 +147,19 @@ class DatabaseIntegrityCheck if ($row['deleted']) { $this->recStats['deleted']['pages'][$newID] = $newID; } + + if (!isset($this->recStats['hidden'])) { + $this->recStats['hidden'] = 0; + } + if ($row['hidden']) { $this->recStats['hidden']++; } + + if (!is_array($this->recStats['doktype'][$row['doktype']] ?? false)) { + $this->recStats['doktype'][$row['doktype']] = 0; + } + $this->recStats['doktype'][$row['doktype']]++; // If all records should be shown, do so: if ($this->genTreeIncludeRecords) { @@ -436,7 +446,7 @@ class DatabaseIntegrityCheck while ($row = $queryResult->fetch()) { foreach ($fields as $field) { - if (trim($row[$field])) { + if (trim($row[$field] ?? '')) { $fieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config']; if ($fieldConf['type'] === 'group' && $fieldConf['internal_type'] === 'db') { $dbAnalysis = GeneralUtility::makeInstance(RelationHandler::class);