Commit e6903b8b authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Make PHP code of TYPO3 Core PHP 7.4 compliant

This resolves the most common issues related to
PHP 7.4 PHP changes:
- implode() argument order
- using "{}" instead of "[]" in PHP array keys
- PHP notices for invalid array key access

Resolves: #89737
Releases: master, 9.5, 8.7
Change-Id: Iff0b8a46279d328f66ae6bab927aef2bca881774
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62367


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 41757830
......@@ -88,11 +88,11 @@ class ConfigurationService implements SingletonInterface
$beUser = $this->getBackendUser();
$this->triggerOnSubmitActors($modules, $request, $configurationToSave);
$existingConfiguration = $beUser->uc['AdminPanel'] ?? [];
$existingConfiguration = is_array($existingConfiguration) ? $existingConfiguration : [];
// Settings
$beUser->uc['AdminPanel'] = array_merge(
!is_array($beUser->uc['AdminPanel']) ? [] : $beUser->uc['AdminPanel'],
$configurationToSave
);
$beUser->uc['AdminPanel'] = array_merge($existingConfiguration, $configurationToSave);
unset($beUser->uc['AdminPanel']['action']);
// Saving
$beUser->writeUC();
......
......@@ -36,8 +36,8 @@ class FormSelectTreeAjaxController
*/
public function fetchDataAction(ServerRequestInterface $request): ResponseInterface
{
$tableName = $request->getQueryParams()['tableName'];
$fieldName = $request->getQueryParams()['fieldName'];
$tableName = $request->getQueryParams()['tableName'] ?? '';
$fieldName = $request->getQueryParams()['fieldName'] ?? '';
// Prepare processedTca: Remove all column definitions except the one that contains
// our tree definition. This way only this field is calculated, everything else is ignored.
......
......@@ -91,7 +91,7 @@ class TcaGroup implements FormDataProviderInterface
$title = BackendUtility::getRecordTitle($tableName, $record, false, false);
$items[] = [
'table' => $tableName,
'uid' => $record['uid'],
'uid' => $record['uid'] ?? null,
'title' => $title,
'row' => $record,
];
......
......@@ -32,7 +32,7 @@ class TcaInlineExpandCollapseState implements FormDataProviderInterface
public function addData(array $result)
{
if (empty($result['inlineExpandCollapseStateArray'])) {
$fullInlineState = json_decode($this->getBackendUser()->uc['inlineView'], true);
$fullInlineState = json_decode($this->getBackendUser()->uc['inlineView'] ?? null, true);
if (!is_array($fullInlineState)) {
$fullInlineState = [];
}
......
......@@ -78,7 +78,7 @@ class EmailLoginNotification
}
}
// Trigger an email to the current BE user, if this has been enabled in the user configuration
if ($currentUser->uc['emailMeAtLogin'] && GeneralUtility::validEmail($user['email'])) {
if (($currentUser->uc['emailMeAtLogin'] ?? null) && GeneralUtility::validEmail($user['email'])) {
$this->sendEmail($user['email'], $subject, $emailBody);
}
}
......
......@@ -574,6 +574,9 @@ class CharsetConverter implements SingletonInterface
if ($fh) {
while (!feof($fh)) {
$line = fgets($fh, 4096);
if ($line === false) {
continue;
}
if ($line[0] !== '#' && trim($line) !== '') {
list($char, $translit) = GeneralUtility::trimExplode(';', $line);
if (!$translit) {
......@@ -617,11 +620,11 @@ class CharsetConverter implements SingletonInterface
// Skip decompositions containing non-ASCII chars
$code_decomp[] = chr($ord);
}
$this->toASCII['utf-8'][$this->UnumberToChar(hexdec($from))] = implode('', $code_decomp);
$this->toASCII['utf-8'][$this->UnumberToChar(hexdec(substr($from, 2)))] = implode('', $code_decomp);
}
// Add numeric decompositions
foreach ($number as $from => $to) {
$utf8_char = $this->UnumberToChar(hexdec($from));
$utf8_char = $this->UnumberToChar(hexdec(substr($from, 2)));
if (!isset($this->toASCII['utf-8'][$utf8_char])) {
$this->toASCII['utf-8'][$utf8_char] = $to;
}
......
......@@ -655,10 +655,10 @@ class DataHandler implements LoggerAwareInterface
{
// Initializing BE_USER
$this->BE_USER = is_object($altUserObject) ? $altUserObject : $GLOBALS['BE_USER'];
$this->userid = $this->BE_USER->user['uid'];
$this->username = $this->BE_USER->user['username'];
$this->admin = $this->BE_USER->user['admin'];
if ($this->BE_USER->uc['recursiveDelete']) {
$this->userid = $this->BE_USER->user['uid'] ?? 0;
$this->username = $this->BE_USER->user['username'] ?? '';
$this->admin = $this->BE_USER->user['admin'] ?? false;
if ($this->BE_USER->uc['recursiveDelete'] ?? false) {
$this->deleteTree = 1;
}
......@@ -987,7 +987,7 @@ class DataHandler implements LoggerAwareInterface
} else {
// Here we fetch the PID of the record that we point to...
$tempdata = $this->recordInfo($table, $id, 'pid' . (BackendUtility::isTableWorkspaceEnabled($table) ? ',t3ver_oid,t3ver_wsid,t3ver_stage' : ''));
$theRealPid = $tempdata['pid'];
$theRealPid = $tempdata['pid'] ?? null;
// Use the new id of the versionized record we're trying to write to:
// (This record is a child record of a parent and has already been versionized.)
if (!empty($this->autoVersionIdMap[$table][$id])) {
......@@ -2194,7 +2194,7 @@ class DataHandler implements LoggerAwareInterface
// Action commands (sorting order and removals of elements) for flexform sections,
// see FormEngine for the use of this GP parameter
$actionCMDs = GeneralUtility::_GP('_ACTION_FLEX_FORMdata');
if (is_array($actionCMDs[$table][$id][$field]['data'])) {
if (is_array($actionCMDs[$table][$id][$field]['data'] ?? null)) {
$arrValue = GeneralUtility::xml2array($xmlValue);
$this->_ACTION_FLEX_FORMdata($arrValue['data'], $actionCMDs[$table][$id][$field]['data']);
$xmlValue = $this->checkValue_flexArray2Xml($arrValue, true);
......
......@@ -129,7 +129,7 @@ class SlugHelper
// Remove trailing and beginning slashes, except if the trailing slash was added, then we'll re-add it
$appendTrailingSlash = $extractedSlug !== '' && substr($slug, -1) === '/';
$slug = $extractedSlug . ($appendTrailingSlash ? '/' : '');
if ($this->prependSlashInSlug && ($slug{0} ?? '') !== '/') {
if ($this->prependSlashInSlug && ($slug[0] ?? '') !== '/') {
$slug = '/' . $slug;
}
return $slug;
......@@ -207,7 +207,7 @@ class SlugHelper
if ($slug === '' || $slug === '/') {
$slug = 'default-' . GeneralUtility::shortMD5(json_encode($recordData));
}
if ($this->prependSlashInSlug && ($slug{0} ?? '') !== '/') {
if ($this->prependSlashInSlug && ($slug[0] ?? '') !== '/') {
$slug = '/' . $slug;
}
if (!empty($prefix)) {
......
......@@ -141,7 +141,8 @@ class QueryHelper
// Catch the edge case that the table name is unquoted and the
// table alias is actually quoted. This will not work in the case
// that the quoted table alias contains whitespace.
if ($tableAlias[0] === '`' || $tableAlias[0] === '"') {
$firstCharacterOfTableAlias = $tableAlias[0] ?? null;
if ($firstCharacterOfTableAlias === '`' || $firstCharacterOfTableAlias === '"') {
$tableAlias = substr($tableAlias, 1, -1);
}
......
......@@ -220,7 +220,11 @@ class ServiceProviderCompilationPass implements CompilerPassInterface
*/
private function getReturnType(\ReflectionFunctionAbstract $reflection, string $serviceName): string
{
return (string)($reflection->getReturnType() ?: $serviceName);
if ($reflection->getReturnType() instanceof \ReflectionNamedType) {
return $reflection->getReturnType()->getName();
}
return $serviceName;
}
/**
......
......@@ -421,7 +421,7 @@ class HtmlParser
$tok = substr($tok, $eocPos + 10);
$skipTag = true;
}
$firstChar = $tok[0];
$firstChar = $tok[0] ?? null;
// It is a tag... (first char is a-z0-9 or /) (fixed 19/01 2004). This also avoids triggering on <?xml..> and <!DOCTYPE..>
if (!$skipTag && preg_match('/[[:alnum:]\\/]/', $firstChar) === 1) {
$tagEnd = strpos($tok, '>');
......
......@@ -173,7 +173,7 @@ class LegacyLinkNotationConverter
}
if (empty($data)) {
$result['pageuid'] = 'current';
} elseif ($data{0} === '#') {
} elseif ($data[0] === '#') {
$result['pageuid'] = 'current';
$result['fragment'] = substr($data, 1);
} elseif (strpos($data, ',') !== false) {
......
......@@ -106,7 +106,7 @@ class LanguageStore implements SingletonInterface
*/
public function getDataByLanguage($fileReference, $languageKey)
{
return $this->data[$fileReference][$languageKey];
return $this->data[$fileReference][$languageKey] ?? [];
}
/**
......
......@@ -2517,7 +2517,7 @@ class ResourceStorage implements ResourceStorageInterface
public function getFolder($identifier, $returnInaccessibleFolderObject = false)
{
$data = $this->driver->getFolderInfoByIdentifier($identifier);
$folder = $this->getResourceFactoryInstance()->createFolderObject($this, $data['identifier'], $data['name']);
$folder = $this->getResourceFactoryInstance()->createFolderObject($this, $data['identifier'] ?? null, $data['name'] ?? null);
try {
$this->assureFolderReadPermission($folder);
......
......@@ -146,8 +146,8 @@ class PageTypeDecorator extends AbstractEnhancer implements DecoratingEnhancerIn
$value = $this->resolveValue($type);
$considerIndex = $value !== ''
&& in_array($value{0}, static::ROUTE_PATH_DELIMITERS);
if ($value !== '' && !in_array($value{0}, static::ROUTE_PATH_DELIMITERS)) {
&& in_array($value[0], static::ROUTE_PATH_DELIMITERS);
if ($value !== '' && !in_array($value[0], static::ROUTE_PATH_DELIMITERS)) {
$value = '/' . $value;
}
......@@ -242,7 +242,7 @@ class PageTypeDecorator extends AbstractEnhancer implements DecoratingEnhancerIn
protected function needsSlashPrefix(string $value): bool
{
return !in_array(
$value{0} ?? '',
$value[0] ?? '',
static::ROUTE_PATH_DELIMITERS,
true
);
......
......@@ -46,11 +46,11 @@ class VariableProcessor
}
$hash = md5($value);
// Symfony Route Compiler requires first literal to be non-integer
if ($hash{0} === (string)(int)$hash{0}) {
$hash{0} = str_replace(
if ($hash[0] === (string)(int)$hash[0]) {
$hash[0] = str_replace(
range('0', '9'),
range('o', 'x'),
$hash{0}
$hash[0]
);
}
$this->hashes[$hash] = $value;
......
......@@ -82,7 +82,7 @@ class FlexFormService implements \TYPO3\CMS\Core\SingletonInterface
if (in_array($nodeKey, ['el', '_arrayContainer'])) {
return $this->walkFlexFormNode($nodeValue, $valuePointer);
}
if ($nodeKey[0] === '_') {
if (($nodeKey[0] ?? '') === '_') {
continue;
}
if (strpos($nodeKey, '.')) {
......
......@@ -291,7 +291,7 @@ class Site implements SiteInterface
public function getErrorHandler(int $statusCode): PageErrorHandlerInterface
{
$errorHandlerConfiguration = $this->errorHandlers[$statusCode] ?? null;
switch ($errorHandlerConfiguration['errorHandler']) {
switch ($errorHandlerConfiguration['errorHandler'] ?? null) {
case self::ERRORHANDLER_TYPE_FLUID:
return GeneralUtility::makeInstance(FluidPageErrorHandler::class, $statusCode, $errorHandlerConfiguration);
case self::ERRORHANDLER_TYPE_PAGE:
......@@ -346,7 +346,7 @@ class Site implements SiteInterface
{
// no protocol ("//") and the first part is no "/" (path), means that this is a domain like
// "www.domain.com/blabla", and we want to ensure that this one then gets a "no-scheme agnostic" part
if (!empty($base) && strpos($base, '//') === false && $base{0} !== '/') {
if (!empty($base) && strpos($base, '//') === false && $base[0] !== '/') {
// either a scheme is added, or no scheme but with domain, or a path which is not absolute
// make the base prefixed with a slash, so it is recognized as path, not as domain
// treat as path
......
......@@ -334,7 +334,7 @@ class TypoScriptParser
}
// Disable multiline
$this->multiLineEnabled = false;
$theValue = implode($this->multiLineValue, LF);
$theValue = implode(LF, $this->multiLineValue);
if (strpos($this->multiLineObject, '.') !== false) {
// Set the value deeper.
$this->setVal($this->multiLineObject, $setup, [$theValue]);
......
......@@ -20,6 +20,7 @@ use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type;
use Prophecy\Argument;
use TYPO3\CMS\Core\Database\Connection;
......@@ -89,7 +90,9 @@ class ConnectionMigratorTest extends UnitTestCase
*/
public function columnNamesStickToTheMaximumCharactersWhenPrefixedForRemoval()
{
$originalSchemaDiff = GeneralUtility::makeInstance(SchemaDiff::class, null, null, [$this->getTable()]);
$table = $this->getTable();
$tableDiff = new TableDiff($table->getName());
$originalSchemaDiff = new SchemaDiff(null, [$tableDiff]);
$originalSchemaDiff->changedTables[0]->removedColumns[] = $this->getColumn();
$renamedSchemaDiff = $this->subject->_call('migrateUnprefixedRemovedFieldsToRenames', $originalSchemaDiff);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment