Skip to content

Commit

Permalink
[TASK] Fix phpstan checkFunctionArgumentTypes errors in ext:core Utility
Browse files Browse the repository at this point in the history
This patch fixes incompatible type usage in function arguments
and is preparatory work for introducing native type hints and
strict mode in all core files.

Releases: master, 10.4
Resolves: #92279
Change-Id: I469892a56334a13ab19df17aeaa39a68226b7510
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/66040
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
  • Loading branch information
alexanderschnitzler authored and ervaude committed Oct 6, 2020
1 parent 84dea4f commit b0712a5
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 45 deletions.
4 changes: 2 additions & 2 deletions typo3/sysext/core/Classes/Utility/ArrayUtility.php
Expand Up @@ -679,7 +679,7 @@ public static function removeArrayEntryByValue(array $array, $cmpValue)
*
* @param array $array The initial array to be filtered/reduced
* @param mixed $keepItems The items which are allowed/kept in the array - accepts array or csv string
* @param string $getValueFunc (optional) Callback function used to get the value to keep
* @param callable|null $getValueFunc (optional) Callback function used to get the value to keep
* @return array The filtered/reduced array with the kept items
*/
public static function keepItemsInArray(array $array, $keepItems, $getValueFunc = null)
Expand Down Expand Up @@ -837,7 +837,7 @@ public static function stripTagsFromValuesRecursive(array $array): array
if (is_array($value)) {
$result[$key] = self::stripTagsFromValuesRecursive($value);
} elseif (is_string($value) || (is_object($value) && method_exists($value, '__toString'))) {
$result[$key] = strip_tags($value);
$result[$key] = strip_tags((string)$value);
}
}
return $result;
Expand Down
2 changes: 1 addition & 1 deletion typo3/sysext/core/Classes/Utility/CommandUtility.php
Expand Up @@ -453,7 +453,7 @@ public static function escapeShellArguments(array $input)
$isUTF8Filesystem = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']);
$currentLocale = false;
if ($isUTF8Filesystem) {
$currentLocale = setlocale(LC_CTYPE, 0);
$currentLocale = setlocale(LC_CTYPE, '0');
setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
}

Expand Down
1 change: 1 addition & 0 deletions typo3/sysext/core/Classes/Utility/CsvUtility.php
Expand Up @@ -40,6 +40,7 @@ public static function csvToArray($input, $fieldDelimiter = ',', $fieldEnclosure
fwrite($handle, $input);
rewind($handle);
while (($cells = fgetcsv($handle, 0, $fieldDelimiter, $fieldEnclosure)) !== false) {
$cells = is_array($cells) ? $cells : [];
$maximumCellCount = max(count($cells), $maximumCellCount);
$multiArray[] = preg_replace('|<br */?>|i', LF, $cells);
}
Expand Down
Expand Up @@ -1605,7 +1605,7 @@ protected static function createExtLocalconfCacheEntry(FrontendInterface $codeCa
$phpCodeToCache[] = ' */';
$phpCodeToCache[] = '';
// Add ext_localconf.php content of extension
$phpCodeToCache[] = trim(file_get_contents($extLocalconfPath));
$phpCodeToCache[] = trim((string)file_get_contents($extLocalconfPath));
$phpCodeToCache[] = '';
$phpCodeToCache[] = '';
}
Expand Down Expand Up @@ -1829,7 +1829,7 @@ protected static function createExtTablesCacheEntry()
$phpCodeToCache[] = ' */';
$phpCodeToCache[] = '';
// Add ext_tables.php content of extension
$phpCodeToCache[] = trim(file_get_contents($extTablesPath));
$phpCodeToCache[] = trim((string)file_get_contents($extTablesPath));
$phpCodeToCache[] = '';
}
}
Expand Down
4 changes: 2 additions & 2 deletions typo3/sysext/core/Classes/Utility/File/BasicFileUtility.php
Expand Up @@ -159,11 +159,11 @@ public function cleanFileName($fileName)
// Handle UTF-8 characters
if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
// allow ".", "-", 0-9, a-z, A-Z and everything beyond U+C0 (latin capital letter a with grave)
$cleanFileName = preg_replace('/[' . self::UNSAFE_FILENAME_CHARACTER_EXPRESSION . ']/u', '_', trim($fileName));
$cleanFileName = preg_replace('/[' . self::UNSAFE_FILENAME_CHARACTER_EXPRESSION . ']/u', '_', trim($fileName)) ?? '';
} else {
$fileName = GeneralUtility::makeInstance(CharsetConverter::class)->utf8_char_mapping($fileName);
// Replace unwanted characters by underscores
$cleanFileName = preg_replace('/[' . self::UNSAFE_FILENAME_CHARACTER_EXPRESSION . '\\xC0-\\xFF]/', '_', trim($fileName));
$cleanFileName = preg_replace('/[' . self::UNSAFE_FILENAME_CHARACTER_EXPRESSION . '\\xC0-\\xFF]/', '_', trim($fileName)) ?? '';
}
// Strip trailing dots and return
return rtrim($cleanFileName, '.');
Expand Down
75 changes: 44 additions & 31 deletions typo3/sysext/core/Classes/Utility/GeneralUtility.php
Expand Up @@ -262,9 +262,10 @@ public static function cmpIPv4($baseIP, $list)
$mask = false;
}
if ((int)$mask) {
$mask = (int)$mask;
// "192.168.3.0/24"
$lnet = ip2long($test);
$lip = ip2long($baseIP);
$lnet = (int)ip2long($test);
$lip = (int)ip2long($baseIP);
$binnet = str_pad(decbin($lnet), 32, '0', STR_PAD_LEFT);
$firstpart = substr($binnet, 0, $mask);
$binip = str_pad(decbin($lip), 32, '0', STR_PAD_LEFT);
Expand Down Expand Up @@ -318,13 +319,15 @@ public static function cmpIPv6($baseIP, $list)
} elseif ($maskInt == 128) {
$success = $test === $baseIP;
} else {
$testBin = inet_pton($test);
$baseIPBin = inet_pton($baseIP);
$testBin = (string)inet_pton($test);
$baseIPBin = (string)inet_pton($baseIP);

$success = true;
// Modulo is 0 if this is a 8-bit-boundary
$maskIntModulo = $maskInt % 8;
$numFullCharactersUntilBoundary = (int)($maskInt / 8);
if (strpos($testBin, substr($baseIPBin, 0, $numFullCharactersUntilBoundary)) !== 0) {
$substring = (string)substr($baseIPBin, 0, $numFullCharactersUntilBoundary);
if (strpos($testBin, $substring) !== 0) {
$success = false;
} elseif ($maskIntModulo > 0) {
// If not an 8-bit-boundary, check bits of last character
Expand Down Expand Up @@ -501,7 +504,7 @@ public static function cmpFQDN($baseHost, $list)
// Resolve hostname
// Note: this is reverse-lookup and can be randomly set as soon as somebody is able to set
// the reverse-DNS for his IP (security when for example used with REMOTE_ADDR)
$baseHostName = gethostbyaddr($baseHost);
$baseHostName = (string)gethostbyaddr($baseHost);
if ($baseHostName === $baseHost) {
// Unable to resolve hostname
return false;
Expand Down Expand Up @@ -913,7 +916,7 @@ public static function underscoredToLowerCamelCase($string)
*/
public static function camelCaseToLowerCaseUnderscored($string)
{
$value = preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $string);
$value = preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $string) ?? '';
return mb_strtolower($value, 'utf-8');
}

Expand Down Expand Up @@ -987,7 +990,7 @@ public static function isValidUrl($url)
*/
public static function intExplode($delimiter, $string, $removeEmptyValues = false, $limit = 0)
{
$result = explode($delimiter, $string);
$result = explode($delimiter, $string) ?: [];
foreach ($result as $key => &$value) {
if ($removeEmptyValues && ($value === '' || trim($value) === '')) {
unset($result[$key]);
Expand Down Expand Up @@ -1035,7 +1038,7 @@ public static function revExplode($delimiter, $string, $count = 0)
if ($count <= 1) {
return [$string];
}
$explodedValues = explode($delimiter, strrev($string), $count);
$explodedValues = explode($delimiter, strrev($string), $count) ?: [];
$explodedValues = array_map('strrev', $explodedValues);
return array_reverse($explodedValues);
}
Expand All @@ -1054,7 +1057,7 @@ public static function revExplode($delimiter, $string, $count = 0)
*/
public static function trimExplode($delim, $string, $removeEmptyValues = false, $limit = 0)
{
$result = explode($delim, $string);
$result = explode($delim, $string) ?: [];
if ($removeEmptyValues) {
$temp = [];
foreach ($result as $value) {
Expand Down Expand Up @@ -1184,7 +1187,7 @@ public static function removeDotsFromTS(array $ts)
*
* @param string $tag HTML-tag string (or attributes only)
* @param bool $decodeEntities Whether to decode HTML entities
* @return string[] Array with the attribute values.
* @return array<string, string> Array with the attribute values.
*/
public static function get_tag_attributes($tag, bool $decodeEntities = false)
{
Expand All @@ -1202,7 +1205,7 @@ public static function get_tag_attributes($tag, bool $decodeEntities = false)
$name = '';
}
} else {
if ($key = strtolower(preg_replace('/[^[:alnum:]_\\:\\-]/', '', $val))) {
if ($key = strtolower(preg_replace('/[^[:alnum:]_\\:\\-]/', '', $val) ?? '')) {
$attributes[$key] = '';
$name = $key;
}
Expand All @@ -1224,7 +1227,7 @@ public static function get_tag_attributes($tag, bool $decodeEntities = false)
*/
public static function split_tag_attributes($tag)
{
$tag_tmp = trim(preg_replace('/^<[^[:space:]]*/', '', trim($tag)));
$tag_tmp = trim(preg_replace('/^<[^[:space:]]*/', '', trim($tag)) ?? '');
// Removes any > in the end of the string
$tag_tmp = trim(rtrim($tag_tmp, '>'));
$value = [];
Expand Down Expand Up @@ -1853,13 +1856,13 @@ public static function fixPermissions($path, $recursive = false)
}
if (static::isAllowedAbsPath($path)) {
if (@is_file($path)) {
$targetPermissions = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] ?? '0644';
$targetPermissions = (string)($GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] ?? '0644');
} elseif (@is_dir($path)) {
$targetPermissions = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'] ?? '0755';
$targetPermissions = (string)($GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'] ?? '0755');
}
if (!empty($targetPermissions)) {
// make sure it's always 4 digits
$targetPermissions = str_pad($targetPermissions, 4, 0, STR_PAD_LEFT);
$targetPermissions = str_pad($targetPermissions, 4, '0', STR_PAD_LEFT);
$targetPermissions = octdec($targetPermissions);
// "@" is there because file is not necessarily OWNED by the user
$result = @chmod($path, $targetPermissions);
Expand Down Expand Up @@ -2035,9 +2038,9 @@ protected static function createDirectoryPath($fullDirectoryPath)
if (!@is_dir($currentPath)) {
do {
$firstCreatedPath = $currentPath;
$separatorPosition = strrpos($currentPath, DIRECTORY_SEPARATOR);
$separatorPosition = (int)strrpos($currentPath, DIRECTORY_SEPARATOR);
$currentPath = substr($currentPath, 0, $separatorPosition);
} while (!is_dir($currentPath) && $separatorPosition !== false);
} while (!is_dir($currentPath) && $separatorPosition > 0);
$result = @mkdir($fullDirectoryPath, $permissionMask, true);
// Check existence of directory again to avoid race condition. Directory could have get created by another process between previous is_dir() and mkdir()
if (!$result && !@is_dir($fullDirectoryPath)) {
Expand All @@ -2058,7 +2061,7 @@ public static function rmdir($path, $removeNonEmpty = false)
{
$OK = false;
// Remove trailing slash
$path = preg_replace('|/$|', '', $path);
$path = preg_replace('|/$|', '', $path) ?? '';
$isWindows = DIRECTORY_SEPARATOR === '\\';
if (file_exists($path)) {
$OK = true;
Expand Down Expand Up @@ -2250,7 +2253,7 @@ public static function getAllFilesAndFoldersInPath(array $fileArr, $path, $extLi
if ($regDirs) {
$fileArr[md5($path)] = $path;
}
$fileArr = array_merge($fileArr, self::getFilesInDir($path, $extList, 1, 1, $excludePattern));
$fileArr = array_merge($fileArr, (array)self::getFilesInDir($path, $extList, true, '', $excludePattern));
$dirs = self::get_dirs($path);
if ($recursivityLevels > 0 && is_array($dirs)) {
foreach ($dirs as $subdirs) {
Expand Down Expand Up @@ -2362,10 +2365,12 @@ public static function locationHeaderUrl($path)
*/
public static function getMaxUploadFileSize()
{
$uploadMaxFilesize = (string)ini_get('upload_max_filesize');
$postMaxSize = (string)ini_get('post_max_size');
// Check for PHP restrictions of the maximum size of one of the $_FILES
$phpUploadLimit = self::getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
$phpUploadLimit = self::getBytesFromSizeMeasurement($uploadMaxFilesize);
// Check for PHP restrictions of the maximum $_POST size
$phpPostLimit = self::getBytesFromSizeMeasurement(ini_get('post_max_size'));
$phpPostLimit = self::getBytesFromSizeMeasurement($postMaxSize);
// If the total amount of post data is smaller (!) than the upload_max_filesize directive,
// then this is the real limit in PHP
$phpUploadLimit = $phpPostLimit > 0 && $phpPostLimit < $phpUploadLimit ? $phpPostLimit : $phpUploadLimit;
Expand All @@ -2388,7 +2393,7 @@ public static function getBytesFromSizeMeasurement($measurement)
} elseif (stripos($measurement, 'K')) {
$bytes *= 1024;
}
return $bytes;
return (int)$bytes;
}

/**
Expand Down Expand Up @@ -2684,7 +2689,7 @@ public static function getIndpEnv($getEnvName)
$ip = '';
}
}
if (self::validIP($ip)) {
if (self::validIP((string)$ip)) {
$retVal = $ip;
}
}
Expand Down Expand Up @@ -3225,13 +3230,14 @@ public static function tempnam($filePrefix, $fileSuffix = '')
self::mkdir_deep($temporaryPath);
}
if ($fileSuffix === '') {
$tempFileName = $temporaryPath . PathUtility::basename(tempnam($temporaryPath, $filePrefix));
$path = (string)tempnam($temporaryPath, $filePrefix);
$tempFileName = $temporaryPath . PathUtility::basename($path);
} else {
do {
$tempFileName = $temporaryPath . $filePrefix . random_int(1, PHP_INT_MAX) . $fileSuffix;
} while (file_exists($tempFileName));
touch($tempFileName);
clearstatcache(null, $tempFileName);
clearstatcache(false, $tempFileName);
}
return $tempFileName;
}
Expand Down Expand Up @@ -3320,9 +3326,11 @@ public static function callUserFunction($funcName, &$params, &$ref = null)
if (class_exists($parts[0])) {
// Create object
$classObj = self::makeInstance($parts[0]);
if (method_exists($classObj, $parts[1])) {
$methodName = (string)$parts[1];
$callable = [$classObj, $methodName];
if (is_callable($callable)) {
// Call method:
$content = call_user_func_array([&$classObj, $parts[1]], [&$params, &$ref]);
$content = call_user_func_array($callable, [&$params, &$ref]);
} else {
$errorMsg = 'No method name \'' . $parts[1] . '\' in class ' . $parts[0];
throw new \InvalidArgumentException($errorMsg, 1294585865);
Expand All @@ -3331,7 +3339,7 @@ public static function callUserFunction($funcName, &$params, &$ref = null)
$errorMsg = 'No class named ' . $parts[0];
throw new \InvalidArgumentException($errorMsg, 1294585866);
}
} elseif (function_exists($funcName)) {
} elseif (function_exists($funcName) && is_callable($funcName)) {
// It's a function
$content = call_user_func_array($funcName, [&$params, &$ref]);
} else {
Expand Down Expand Up @@ -3726,8 +3734,13 @@ public static function makeInstanceService($serviceType, $serviceSubType = '', $
*/
public static function quoteJSvalue($value)
{
$json = (string)json_encode(
(string)$value,
JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG
);

return strtr(
json_encode((string)$value, JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG),
$json,
[
'"' => '\'',
'\\\\' => '\\u005C',
Expand All @@ -3747,7 +3760,7 @@ public static function quoteJSvalue($value)
*/
public static function jsonEncodeForHtmlAttribute($value, bool $useHtmlEntities = true): string
{
$json = json_encode($value, JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG);
$json = (string)json_encode($value, JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG);
return $useHtmlEntities ? htmlspecialchars($json) : $json;
}

Expand Down
10 changes: 5 additions & 5 deletions typo3/sysext/core/Classes/Utility/PathUtility.php
Expand Up @@ -114,7 +114,7 @@ public static function getCommonPrefix(array $paths)
if (count($paths) === 1) {
$commonPath = array_shift($paths);
} elseif (count($paths) > 1) {
$parts = explode('/', array_shift($paths));
$parts = explode('/', (string)array_shift($paths));
$comparePath = '';
$break = false;
foreach ($parts as $part) {
Expand Down Expand Up @@ -164,7 +164,7 @@ public static function sanitizeTrailingSeparator($path, $separator = '/')
*/
public static function basename($path)
{
$currentLocale = setlocale(LC_CTYPE, 0);
$currentLocale = (string)setlocale(LC_CTYPE, '0');
setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
$basename = basename($path);
setlocale(LC_CTYPE, $currentLocale);
Expand All @@ -185,7 +185,7 @@ public static function basename($path)
*/
public static function dirname($path)
{
$currentLocale = setlocale(LC_CTYPE, 0);
$currentLocale = (string)setlocale(LC_CTYPE, '0');
setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
$dirname = dirname($path);
setlocale(LC_CTYPE, $currentLocale);
Expand All @@ -203,11 +203,11 @@ public static function dirname($path)
* @param string $path
* @param int $options
*
* @return string|array
* @return string|string[]
*/
public static function pathinfo($path, $options = null)
{
$currentLocale = setlocale(LC_CTYPE, 0);
$currentLocale = (string)setlocale(LC_CTYPE, '0');
setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
$pathinfo = $options == null ? pathinfo($path) : pathinfo($path, $options);
setlocale(LC_CTYPE, $currentLocale);
Expand Down
4 changes: 2 additions & 2 deletions typo3/sysext/core/Classes/Utility/VersionNumberUtility.php
Expand Up @@ -35,7 +35,7 @@ public static function convertVersionNumberToInteger($versionNumber)
$version = $versionParts[0];
for ($i = 1; $i < 3; $i++) {
if (!empty($versionParts[$i])) {
$version .= str_pad((int)$versionParts[$i], 3, '0', STR_PAD_LEFT);
$version .= str_pad((string)(int)$versionParts[$i], 3, '0', STR_PAD_LEFT);
} else {
$version .= '000';
}
Expand Down Expand Up @@ -142,7 +142,7 @@ public static function convertVersionsStringToVersionNumbers($versionsString)
$cleanedVersion = GeneralUtility::trimExplode('.', $versions[$i]);
$cleanedVersionCount = count($cleanedVersion);
for ($j = 0; $j < $cleanedVersionCount; $j++) {
$cleanedVersion[$j] = MathUtility::forceIntegerInRange($cleanedVersion[$j], 0, 999);
$cleanedVersion[$j] = MathUtility::forceIntegerInRange((int)$cleanedVersion[$j], 0, 999);
}
$cleanedVersionString = implode('.', $cleanedVersion);
if (static::convertVersionNumberToInteger($cleanedVersionString) === 0) {
Expand Down

0 comments on commit b0712a5

Please sign in to comment.