Skip to content

Commit

Permalink
[BUGFIX] Fix array undefined warnings in "DB Check" Module
Browse files Browse the repository at this point in the history
Add fallback for undefined array keys to make "DB Check"
compatible with PHP8.

Also basic tests have been added to check each page in
the module.

Resolves: #94498
Releases: master
Change-Id: I98a598d0e809077cd89e7620efe31a498b3fbfa1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69759
Tested-by: core-ci <typo3@b13.com>
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: crell <larry@garfieldtech.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
  • Loading branch information
ochorocho authored and maddy2101 committed Jul 8, 2021
1 parent cdc6b71 commit 9ea6ad0
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 58 deletions.
2 changes: 1 addition & 1 deletion typo3/sysext/core/Classes/Database/ReferenceIndex.php
Expand Up @@ -408,7 +408,7 @@ protected function createEntryDataForSoftReferencesUsingRecord(string $tableName
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']);
Expand Down
@@ -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 . ']'
)
);
}
);
}
}
Expand Up @@ -360,11 +360,11 @@ protected function func_search()
}
$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);
Expand Down Expand Up @@ -441,21 +441,21 @@ protected function func_records()
$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() !== '') {
$lostRecordCount = count(explode(',', $admin->getLostPagesList()));
} 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>';
Expand Down

0 comments on commit 9ea6ad0

Please sign in to comment.