[BUGFIX] Remove side effects from ErrorController tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / GeneralUtility.php
index 0609a82..fc14c97 100644 (file)
@@ -15,14 +15,16 @@ namespace TYPO3\CMS\Core\Utility;
  */
 
 use GuzzleHttp\Exception\RequestException;
-use TYPO3\CMS\Core\Charset\CharsetConverter;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
 use TYPO3\CMS\Core\Core\ApplicationContext;
 use TYPO3\CMS\Core\Core\ClassLoadingInformation;
-use TYPO3\CMS\Core\Crypto\Random;
-use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Http\RequestFactory;
+use TYPO3\CMS\Core\Log\LogLevel;
+use TYPO3\CMS\Core\Log\LogManager;
 use TYPO3\CMS\Core\Service\OpcodeCacheService;
 use TYPO3\CMS\Core\SingletonInterface;
+use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 
 /**
  * The legendary "t3lib_div" class - Miscellaneous functions for general purpose.
@@ -38,7 +40,8 @@ use TYPO3\CMS\Core\SingletonInterface;
  */
 class GeneralUtility
 {
-    // Severity constants used by \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog()
+    // Severity constants used by \TYPO3\CMS\Core\Utility\GeneralUtility::devLog()
+    // @deprecated since TYPO3 CMS 9, will be removed in TYPO3 CMS 10.
     const SYSLOG_SEVERITY_INFO = 0;
     const SYSLOG_SEVERITY_NOTICE = 1;
     const SYSLOG_SEVERITY_WARNING = 2;
@@ -62,21 +65,21 @@ class GeneralUtility
      *
      * @var array<\TYPO3\CMS\Core\SingletonInterface>
      */
-    protected static $singletonInstances = array();
+    protected static $singletonInstances = [];
 
     /**
      * Instances returned by makeInstance, using the class names as array keys
      *
      * @var array<array><object>
      */
-    protected static $nonSingletonInstances = array();
+    protected static $nonSingletonInstances = [];
 
     /**
      * Cache for makeInstance with given class name and final class names to reduce number of self::getClassName() calls
      *
      * @var array Given class name => final class name
      */
-    protected static $finalClassNameCache = array();
+    protected static $finalClassNameCache = [];
 
     /**
      * The application context
@@ -90,7 +93,7 @@ class GeneralUtility
      *
      * @var array<string>
      */
-    protected static $idnaStringCache = array();
+    protected static $idnaStringCache = [];
 
     /**
      * IDNA converter
@@ -104,13 +107,13 @@ class GeneralUtility
      * NOTICE: This is a duplicate of the SAME array in SystemEnvironmentBuilder
      * @var array
      */
-    protected static $supportedCgiServerApis = array(
+    protected static $supportedCgiServerApis = [
         'fpm-fcgi',
         'cgi',
         'isapi',
         'cgi-fcgi',
         'srv', // HHVM with fastcgi
-    );
+    ];
 
     /**
      * @var array
@@ -166,8 +169,8 @@ class GeneralUtility
      */
     public static function _GPmerged($parameter)
     {
-        $postParameter = isset($_POST[$parameter]) && is_array($_POST[$parameter]) ? $_POST[$parameter] : array();
-        $getParameter = isset($_GET[$parameter]) && is_array($_GET[$parameter]) ? $_GET[$parameter] : array();
+        $postParameter = isset($_POST[$parameter]) && is_array($_POST[$parameter]) ? $_POST[$parameter] : [];
+        $getParameter = isset($_GET[$parameter]) && is_array($_GET[$parameter]) ? $_GET[$parameter] : [];
         $mergedParameters = $getParameter;
         ArrayUtility::mergeRecursiveWithOverrule($mergedParameters, $postParameter);
         return $mergedParameters;
@@ -202,7 +205,7 @@ class GeneralUtility
      */
     public static function _POST($var = null)
     {
-        $value = $var === null ? $_POST : (empty($var) ? null : $_POST[$var]);
+        $value = $var === null ? $_POST : (empty($var) || !isset($_POST[$var]) ? null : $_POST[$var]);
         // This is there for backwards-compatibility, in order to avoid NULL
         if (isset($value) && !is_array($value)) {
             $value = (string)$value;
@@ -215,14 +218,13 @@ class GeneralUtility
      *
      * @param mixed $inputGet
      * @param string $key
-     * @return void
      */
     public static function _GETset($inputGet, $key = '')
     {
         if ($key != '') {
             if (strpos($key, '|') !== false) {
                 $pieces = explode('|', $key);
-                $newGet = array();
+                $newGet = [];
                 $pointer = &$newGet;
                 foreach ($pieces as $piece) {
                     $pointer = &$pointer[$piece];
@@ -242,27 +244,6 @@ class GeneralUtility
         }
     }
 
-    /**
-     * Wrapper for the RemoveXSS function.
-     * Removes potential XSS code from an input string.
-     *
-     * Using an external class by Travis Puderbaugh <kallahar@quickwired.com>
-     *
-     * @param string $string Input string
-     * @return string Input string with potential XSS code removed
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function removeXSS($string)
-    {
-        return \RemoveXSS::process($string);
-    }
-
-    /*************************
-     *
-     * IMAGE FUNCTIONS
-     *
-     *************************/
-
     /*************************
      *
      * STRING FUNCTIONS
@@ -278,9 +259,15 @@ class GeneralUtility
      */
     public static function fixed_lgd_cs($string, $chars, $appendString = '...')
     {
-        /** @var CharsetConverter $charsetConverter */
-        $charsetConverter = self::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
-        return $charsetConverter->crop('utf-8', $string, $chars, $appendString);
+        if ((int)$chars === 0 || mb_strlen($string, 'utf-8') <= abs($chars)) {
+            return $string;
+        }
+        if ($chars > 0) {
+            $string = mb_substr($string, 0, $chars, 'utf-8') . $appendString;
+        } else {
+            $string = $appendString . mb_substr($string, $chars, mb_strlen($string, 'utf-8'), 'utf-8');
+        }
+        return $string;
     }
 
     /**
@@ -296,14 +283,14 @@ class GeneralUtility
         $list = trim($list);
         if ($list === '') {
             return false;
-        } elseif ($list === '*') {
+        }
+        if ($list === '*') {
             return true;
         }
         if (strpos($baseIP, ':') !== false && self::validIPv6($baseIP)) {
             return self::cmpIPv6($baseIP, $list);
-        } else {
-            return self::cmpIPv4($baseIP, $list);
         }
+        return self::cmpIPv4($baseIP, $list);
     }
 
     /**
@@ -445,7 +432,7 @@ class GeneralUtility
         // According to RFC lowercase-representation is recommended
         $address = strtolower($address);
         // Normalized representation has 39 characters (0000:0000:0000:0000:0000:0000:0000:0000)
-        if (strlen($address) == 39) {
+        if (strlen($address) === 39) {
             // Already in full expanded form
             return $address;
         }
@@ -457,7 +444,7 @@ class GeneralUtility
             $left = count($chunksLeft);
             $right = count($chunksRight);
             // Special case: leading zero-only blocks count to 1, should be 0
-            if ($left == 1 && strlen($chunksLeft[0]) == 0) {
+            if ($left === 1 && strlen($chunksLeft[0]) === 0) {
                 $left = 0;
             }
             $hiddenBlocks = 8 - ($left + $right);
@@ -467,7 +454,7 @@ class GeneralUtility
                 $hiddenPart .= '0000:';
                 $h++;
             }
-            if ($left == 0) {
+            if ($left === 0) {
                 $stageOneAddress = $hiddenPart . $chunks[1];
             } else {
                 $stageOneAddress = $chunks[0] . ':' . $hiddenPart . $chunks[1];
@@ -599,9 +586,8 @@ class GeneralUtility
                         if ($wildcardMatched) {
                             // Match found by recursive compare
                             return true;
-                        } else {
-                            $yes = false;
                         }
+                        $yes = false;
                     }
                 } elseif ($baseHostNameParts[$index] !== $val) {
                     // In case of no match
@@ -671,7 +657,7 @@ class GeneralUtility
     public static function expandList($list)
     {
         $items = explode(',', $list);
-        $list = array();
+        $list = [];
         foreach ($items as $item) {
             $range = explode('-', $item);
             if (isset($range[1])) {
@@ -691,21 +677,6 @@ class GeneralUtility
     }
 
     /**
-     * Returns TRUE if the current TYPO3 version (or compatibility version) is compatible to the input version
-     * Notice that this function compares branches, not versions (4.0.1 would be > 4.0.0 although they use the same compat_version)
-     *
-     * @param string $verNumberStr Minimum branch number required (format x.y / e.g. "4.0" NOT "4.0.0"!)
-     * @return bool Returns TRUE if this setup is compatible with the provided version number
-     * @todo Still needs a function to convert versions to branches
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function compat_version($verNumberStr)
-    {
-        static::logDeprecatedFunction();
-        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger($verNumberStr);
-    }
-
-    /**
      * Makes a positive integer hash out of the first 7 chars from the md5 hash of the input
      *
      * @param string $str String to md5-hash
@@ -732,14 +703,13 @@ class GeneralUtility
      * Returns a proper HMAC on a given input string and secret TYPO3 encryption key.
      *
      * @param string $input Input string to create HMAC from
-     * @param string $additionalSecret additionalSecret to prevent hmac beeing used in a different context
+     * @param string $additionalSecret additionalSecret to prevent hmac being used in a different context
      * @return string resulting (hexadecimal) HMAC currently with a length of 40 (HMAC-SHA-1)
      */
     public static function hmac($input, $additionalSecret = '')
     {
         $hashAlgorithm = 'sha1';
         $hashBlocksize = 64;
-        $hmac = '';
         $secret = $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . $additionalSecret;
         if (extension_loaded('hash') && function_exists('hash_hmac') && function_exists('hash_algos') && in_array($hashAlgorithm, hash_algos())) {
             $hmac = hash_hmac($hashAlgorithm, $input, $secret);
@@ -787,7 +757,7 @@ class GeneralUtility
      */
     public static function split_fileref($fileNameWithPath)
     {
-        $reg = array();
+        $reg = [];
         if (preg_match('/(.*\\/)(.*)$/', $fileNameWithPath, $reg)) {
             $info['path'] = $reg[1];
             $info['file'] = $reg[2];
@@ -852,10 +822,10 @@ class GeneralUtility
      */
     public static function formatSize($sizeInBytes, $labels = '', $base = 0)
     {
-        $defaultFormats = array(
-            'iec' => array('base' => 1024, 'labels' => array(' ', ' Ki', ' Mi', ' Gi', ' Ti', ' Pi', ' Ei', ' Zi', ' Yi')),
-            'si' => array('base' => 1000, 'labels' => array(' ', ' k', ' M', ' G', ' T', ' P', ' E', ' Z', ' Y')),
-        );
+        $defaultFormats = [
+            'iec' => ['base' => 1024, 'labels' => [' ', ' Ki', ' Mi', ' Gi', ' Ti', ' Pi', ' Ei', ' Zi', ' Yi']],
+            'si' => ['base' => 1000, 'labels' => [' ', ' k', ' M', ' G', ' T', ' P', ' E', ' Z', ' Y']],
+        ];
         // Set labels and base:
         if (empty($labels)) {
             $labels = 'iec';
@@ -892,20 +862,6 @@ class GeneralUtility
     }
 
     /**
-     * Returns microtime input to milliseconds
-     *
-     * @param string $microtime Microtime
-     * @return int Microtime input string converted to an integer (milliseconds)
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function convertMicrotime($microtime)
-    {
-        static::logDeprecatedFunction();
-        $parts = explode(' ', $microtime);
-        return round(($parts[0] + $parts[1]) * 1000);
-    }
-
-    /**
      * This splits a string by the chars in $operators (typical /+-*) and returns an array with them in
      *
      * @param string $string Input string, eg "123 + 456 / 789 - 4
@@ -915,12 +871,12 @@ class GeneralUtility
      */
     public static function splitCalc($string, $operators)
     {
-        $res = array();
+        $res = [];
         $sign = '+';
         while ($string) {
             $valueLen = strcspn($string, $operators);
             $value = substr($string, 0, $valueLen);
-            $res[] = array($sign, trim($value));
+            $res[] = [$sign, trim($value)];
             $sign = substr($string, $valueLen, 1);
             $string = substr($string, $valueLen + 1);
         }
@@ -929,67 +885,6 @@ class GeneralUtility
     }
 
     /**
-     * Re-converts HTML entities if they have been converted by htmlspecialchars()
-     * Note: Use htmlspecialchars($str, ENT_COMPAT, 'UTF-8', FALSE) to avoid double encoding.
-     *       This makes the call to this method obsolete.
-     *
-     * @param string $str String which contains eg. "&amp;amp;" which should stay "&amp;". Or "&amp;#1234;" to "&#1234;". Or "&amp;#x1b;" to "&#x1b;
-     * @return string Converted result.
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function deHSCentities($str)
-    {
-        static::logDeprecatedFunction();
-        return preg_replace('/&amp;([#[:alnum:]]*;)/', '&\\1', $str);
-    }
-
-    /**
-     * This function is used to escape any ' -characters when transferring text to JavaScript!
-     *
-     * @param string $string String to escape
-     * @param bool $extended If set, also backslashes are escaped.
-     * @param string $char The character to escape, default is ' (single-quote)
-     * @return string Processed input string
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function slashJS($string, $extended = false, $char = '\'')
-    {
-        static::logDeprecatedFunction();
-        if ($extended) {
-            $string = str_replace('\\', '\\\\', $string);
-        }
-        return str_replace($char, '\\' . $char, $string);
-    }
-
-    /**
-     * Version of rawurlencode() where all spaces (%20) are re-converted to space-characters.
-     * Useful when passing text to JavaScript where you simply url-encode it to get around problems with syntax-errors, linebreaks etc.
-     *
-     * @param string $str String to raw-url-encode with spaces preserved
-     * @return string Rawurlencoded result of input string, but with all %20 (space chars) converted to real spaces.
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9, implement directly via PHP instead
-     */
-    public static function rawUrlEncodeJS($str)
-    {
-        static::logDeprecatedFunction();
-        return str_replace('%20', ' ', rawurlencode($str));
-    }
-
-    /**
-     * rawurlencode which preserves "/" chars
-     * Useful when file paths should keep the "/" chars, but have all other special chars encoded.
-     *
-     * @param string $str Input string
-     * @return string Output string
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9, use the PHP methods directly instead
-     */
-    public static function rawUrlEncodeFP($str)
-    {
-        static::logDeprecatedFunction();
-        return str_replace('%2F', '/', rawurlencode($str));
-    }
-
-    /**
      * Checking syntax of input email address
      *
      * http://tools.ietf.org/html/rfc3696
@@ -1021,57 +916,16 @@ class GeneralUtility
         $domain = substr($email, $atPosition + 1);
         $user = substr($email, 0, $atPosition);
         if (!preg_match('/^[a-z0-9.\\-]*$/i', $domain)) {
-            $domain = self::idnaEncode($domain);
+            try {
+                $domain = self::idnaEncode($domain);
+            } catch (\InvalidArgumentException $exception) {
+                return false;
+            }
         }
         return filter_var($user . '@' . $domain, FILTER_VALIDATE_EMAIL) !== false;
     }
 
     /**
-     * Converts string to uppercase
-     * The function converts all Latin characters (a-z, but no accents, etc) to
-     * uppercase. It is safe for all supported character sets (incl. utf-8).
-     * Unlike strtoupper() it does not honour the locale.
-     *
-     * @param string $str Input string
-     * @return string Uppercase String
-     * @deprecated since TYPO3 CMS v8, this method will be removed in TYPO3 CMS v9, Use \TYPO3\CMS\Core\Charset\CharsetConverter->conv_case() instead
-     */
-    public static function strtoupper($str)
-    {
-        self::logDeprecatedFunction();
-        return strtr((string)$str, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
-    }
-
-    /**
-     * Converts string to lowercase
-     * The function converts all Latin characters (A-Z, but no accents, etc) to
-     * lowercase. It is safe for all supported character sets (incl. utf-8).
-     * Unlike strtolower() it does not honour the locale.
-     *
-     * @param string $str Input string
-     * @return string Lowercase String
-     * @deprecated since TYPO3 CMS v8, this method will be removed in TYPO3 CMS v9, Use \TYPO3\CMS\Core\Charset\CharsetConverter->conv_case() instead
-     */
-    public static function strtolower($str)
-    {
-        self::logDeprecatedFunction();
-        return strtr((string)$str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
-    }
-
-    /**
-     * Returns a string of highly randomized bytes (over the full 8-bit range).
-     *
-     * @param int $bytesToReturn Number of bytes to return
-     * @return string Random Bytes
-     * @deprecated since TYPO3 CMS 8, this method will be removed in TYPO3 CMS 9. Use \TYPO3\CMS\Core\Crypto\Random->generateRandomBytes() instead
-     */
-    public static function generateRandomBytes($bytesToReturn)
-    {
-        self::logDeprecatedFunction();
-        return self::makeInstance(Random::class)->generateRandomBytes($bytesToReturn);
-    }
-
-    /**
      * Returns an ASCII string (punicode) representation of $value
      *
      * @param string $value
@@ -1081,26 +935,12 @@ class GeneralUtility
     {
         if (isset(self::$idnaStringCache[$value])) {
             return self::$idnaStringCache[$value];
-        } else {
-            if (!self::$idnaConverter) {
-                self::$idnaConverter = new \Mso\IdnaConvert\IdnaConvert(array('idn_version' => 2008));
-            }
-            self::$idnaStringCache[$value] = self::$idnaConverter->encode($value);
-            return self::$idnaStringCache[$value];
         }
-    }
-
-    /**
-     * Returns a hex representation of a random byte string.
-     *
-     * @param int $count Number of hex characters to return
-     * @return string Random Bytes
-     * @deprecated since TYPO3 CMS 8, this method will be removed in TYPO3 CMS 9. Use \TYPO3\CMS\Core\Crypto\Random::generateRandomHexString() instead
-     */
-    public static function getRandomHexString($count)
-    {
-        self::logDeprecatedFunction();
-        return self::makeInstance(Random::class)->generateRandomHexString($count);
+        if (!self::$idnaConverter) {
+            self::$idnaConverter = new \Mso\IdnaConvert\IdnaConvert(['idn_version' => 2008]);
+        }
+        self::$idnaStringCache[$value] = self::$idnaConverter->encode($value);
+        return self::$idnaStringCache[$value];
     }
 
     /**
@@ -1136,23 +976,8 @@ class GeneralUtility
      */
     public static function camelCaseToLowerCaseUnderscored($string)
     {
-        $charsetConverter = self::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
         $value = preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $string);
-        return $charsetConverter->conv_case('utf-8', $value, 'toLower');
-    }
-
-    /**
-     * Converts the first char of a string to lowercase if it is a latin character (A-Z).
-     * Example: Converts "Hello World" to "hello World"
-     *
-     * @param string $string The string to be used to lowercase the first character
-     * @return string The string with the first character as lowercase
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function lcfirst($string)
-    {
-        static::logDeprecatedFunction();
-        return lcfirst($string);
+        return mb_strtolower($value, 'utf-8');
     }
 
     /**
@@ -1198,7 +1023,11 @@ class GeneralUtility
             return false;
         }
         if (isset($parsedUrl['host']) && !preg_match('/^[a-z0-9.\\-]*$/i', $parsedUrl['host'])) {
-            $parsedUrl['host'] = self::idnaEncode($parsedUrl['host']);
+            try {
+                $parsedUrl['host'] = self::idnaEncode($parsedUrl['host']);
+            } catch (\InvalidArgumentException $exception) {
+                return false;
+            }
         }
         return filter_var(HttpUtility::buildUrl($parsedUrl), FILTER_VALIDATE_URL) !== false;
     }
@@ -1210,7 +1039,7 @@ class GeneralUtility
      *************************/
 
     /**
-     * Explodes a $string delimited by $delim and casts each item in the array to (int).
+     * Explodes a $string delimited by $delimiter and casts each item in the array to (int).
      * Corresponds to \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(), but with conversion to integers for all values.
      *
      * @param string $delimiter Delimiter string to explode with
@@ -1262,17 +1091,16 @@ class GeneralUtility
         if ($count === 2) {
             $position = strrpos($string, strrev($delimiter));
             if ($position !== false) {
-                return array(substr($string, 0, $position), substr($string, $position + strlen($delimiter)));
-            } else {
-                return array($string);
+                return [substr($string, 0, $position), substr($string, $position + strlen($delimiter))];
             }
-        } elseif ($count <= 1) {
-            return array($string);
-        } else {
-            $explodedValues = explode($delimiter, strrev($string), $count);
-            $explodedValues = array_map('strrev', $explodedValues);
-            return array_reverse($explodedValues);
+            return [$string];
         }
+        if ($count <= 1) {
+            return [$string];
+        }
+        $explodedValues = explode($delimiter, strrev($string), $count);
+        $explodedValues = array_map('strrev', $explodedValues);
+        return array_reverse($explodedValues);
     }
 
     /**
@@ -1291,7 +1119,7 @@ class GeneralUtility
     {
         $result = explode($delim, $string);
         if ($removeEmptyValues) {
-            $temp = array();
+            $temp = [];
             foreach ($result as $value) {
                 if (trim($value) !== '') {
                     $temp[] = $value;
@@ -1345,7 +1173,7 @@ class GeneralUtility
      */
     public static function explodeUrl2Array($string, $multidim = false)
     {
-        $output = array();
+        $output = [];
         if ($multidim) {
             parse_str($string, $output);
         } else {
@@ -1372,7 +1200,7 @@ class GeneralUtility
     public static function compileSelectedGetVarsFromArray($varList, array $getArray, $GPvarAlt = true)
     {
         $keys = self::trimExplode(',', $varList, true);
-        $outArr = array();
+        $outArr = [];
         foreach ($keys as $v) {
             if (isset($getArray[$v])) {
                 $outArr[$v] = $getArray[$v];
@@ -1384,24 +1212,6 @@ class GeneralUtility
     }
 
     /**
-     * Takes a row and returns a CSV string of the values with $delim (default is ,) and $quote (default is ") as separator chars.
-     *
-     * @param array $row Input array of values
-     * @param string $delim Delimited, default is comma
-     * @param string $quote Quote-character to wrap around the values.
-     * @return string A single line of CSV
-     */
-    public static function csvValues(array $row, $delim = ',', $quote = '"')
-    {
-        $out = array();
-        foreach ($row as $value) {
-            $out[] = str_replace($quote, $quote . $quote, $value);
-        }
-        $str = $quote . implode(($quote . $delim . $quote), $out) . $quote;
-        return $str;
-    }
-
-    /**
      * Removes dots "." from end of a key identifier of TypoScript styled array.
      * array('key.' => array('property.' => 'value')) --> array('key' => array('property' => 'value'))
      *
@@ -1410,7 +1220,7 @@ class GeneralUtility
      */
     public static function removeDotsFromTS(array $ts)
     {
-        $out = array();
+        $out = [];
         foreach ($ts as $key => $value) {
             if (is_array($value)) {
                 $key = rtrim($key, '.');
@@ -1441,10 +1251,10 @@ class GeneralUtility
         // Attribute name is stored here
         $name = '';
         $valuemode = false;
-        $attributes = array();
+        $attributes = [];
         foreach ($components as $key => $val) {
             // Only if $name is set (if there is an attribute, that waits for a value), that valuemode is enabled. This ensures that the attribute is assigned it's value
-            if ($val != '=') {
+            if ($val !== '=') {
                 if ($valuemode) {
                     if ($name) {
                         $attributes[$name] = $val;
@@ -1476,7 +1286,7 @@ class GeneralUtility
         $tag_tmp = trim(preg_replace('/^<[^[:space:]]*/', '', trim($tag)));
         // Removes any > in the end of the string
         $tag_tmp = trim(rtrim($tag_tmp, '>'));
-        $value = array();
+        $value = [];
         // Compared with empty string instead , 030102
         while ($tag_tmp !== '') {
             $firstChar = $tag_tmp[0];
@@ -1510,7 +1320,7 @@ class GeneralUtility
     public static function implodeAttributes(array $arr, $xhtmlSafe = false, $dontOmitBlankAttribs = false)
     {
         if ($xhtmlSafe) {
-            $newArr = array();
+            $newArr = [];
             foreach ($arr as $p => $v) {
                 if (!isset($newArr[strtolower($p)])) {
                     $newArr[strtolower($p)] = htmlspecialchars($v);
@@ -1518,7 +1328,7 @@ class GeneralUtility
             }
             $arr = $newArr;
         }
-        $list = array();
+        $list = [];
         foreach ($arr as $p => $v) {
             if ((string)$v !== '' || $dontOmitBlankAttribs) {
                 $list[] = $p . '="' . $v . '"';
@@ -1533,20 +1343,15 @@ class GeneralUtility
      * This is nice for indenting JS code with PHP code on the same level.
      *
      * @param string $string JavaScript code
-     * @param null $_ unused, will be removed in TYPO3 CMS 9
      * @return string The wrapped JS code, ready to put into a XHTML page
      */
-    public static function wrapJS($string, $_ = null)
+    public static function wrapJS($string)
     {
-        if ($_ !== null) {
-            self::deprecationLog('Parameter 2 of GeneralUtility::wrapJS is obsolete and can be omitted.');
-        }
-
         if (trim($string)) {
             // remove nl from the beginning
             $string = ltrim($string, LF);
             // re-ident to one tab using the first line as reference
-            $match = array();
+            $match = [];
             if (preg_match('/^(\\t+)/', $string, $match)) {
                 $string = str_replace($match[1], TAB, $string);
             }
@@ -1567,13 +1372,13 @@ class GeneralUtility
      * @param array $parserOptions Options that will be passed to PHP's xml_parser_set_option()
      * @return mixed The array with the parsed structure unless the XML parser returns with an error in which case the error message string is returned.
      */
-    public static function xml2tree($string, $depth = 999, $parserOptions = array())
+    public static function xml2tree($string, $depth = 999, $parserOptions = [])
     {
         // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
         $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
         $parser = xml_parser_create();
-        $vals = array();
-        $index = array();
+        $vals = [];
+        $index = [];
         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
         xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
         foreach ($parserOptions as $option => $value) {
@@ -1585,19 +1390,19 @@ class GeneralUtility
             return 'Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser));
         }
         xml_parser_free($parser);
-        $stack = array(array());
+        $stack = [[]];
         $stacktop = 0;
         $startPoint = 0;
-        $tagi = array();
+        $tagi = [];
         foreach ($vals as $key => $val) {
             $type = $val['type'];
             // open tag:
-            if ($type == 'open' || $type == 'complete') {
+            if ($type === 'open' || $type === 'complete') {
                 $stack[$stacktop++] = $tagi;
                 if ($depth == $stacktop) {
                     $startPoint = $key;
                 }
-                $tagi = array('tag' => $val['tag']);
+                $tagi = ['tag' => $val['tag']];
                 if (isset($val['attributes'])) {
                     $tagi['attrs'] = $val['attributes'];
                 }
@@ -1606,7 +1411,7 @@ class GeneralUtility
                 }
             }
             // finish tag:
-            if ($type == 'complete' || $type == 'close') {
+            if ($type === 'complete' || $type === 'close') {
                 $oldtagi = $tagi;
                 $tagi = $stack[--$stacktop];
                 $oldtag = $oldtagi['tag'];
@@ -1623,7 +1428,7 @@ class GeneralUtility
                 unset($oldtagi);
             }
             // cdata
-            if ($type == 'cdata') {
+            if ($type === 'cdata') {
                 $tagi['values'][] = $val['value'];
             }
         }
@@ -1631,26 +1436,6 @@ class GeneralUtility
     }
 
     /**
-     * Turns PHP array into XML. See array2xml()
-     *
-     * @param array $array The input PHP array with any kind of data; text, binary, integers. Not objects though.
-     * @param string $docTag Alternative document tag. Default is "phparray".
-     * @param array $options Options for the compilation. See array2xml() for description.
-     * @param string $charset Forced charset to prologue
-     * @return string An XML string made from the input content in the array.
-     * @see xml2array(),array2xml()
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9.
-     */
-    public static function array2xml_cs(array $array, $docTag = 'phparray', array $options = array(), $charset = '')
-    {
-        static::logDeprecatedFunction();
-        // Set default charset unless explicitly specified
-        $charset = $charset ?: 'utf-8';
-        // Return XML:
-        return '<?xml version="1.0" encoding="' . htmlspecialchars($charset) . '" standalone="yes" ?>' . LF . self::array2xml($array, '', 0, $docTag, 0, $options);
-    }
-
-    /**
      * Converts a PHP array into an XML string.
      * The XML output is optimized for readability since associative keys are used as tag names.
      * This also means that only alphanumeric characters are allowed in the tag names AND only keys NOT starting with numbers (so watch your usage of keys!). However there are options you can set to avoid this problem.
@@ -1670,7 +1455,7 @@ class GeneralUtility
      * @return string An XML string made from the input content in the array.
      * @see xml2array()
      */
-    public static function array2xml(array $array, $NSprefix = '', $level = 0, $docTag = 'phparray', $spaceInd = 0, array $options = array(), array $stackData = array())
+    public static function array2xml(array $array, $NSprefix = '', $level = 0, $docTag = 'phparray', $spaceInd = 0, array $options = [], array $stackData = [])
     {
         // The list of byte values which will trigger binary-safe storage. If any value has one of these char values in it, it will be encoded in base64
         $binaryChars = chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . chr(11) . chr(12) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19) . chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29) . chr(30) . chr(31);
@@ -1731,11 +1516,11 @@ class GeneralUtility
                 if (empty($v)) {
                     $content = '';
                 } else {
-                    $content = $nl . self::array2xml($v, $NSprefix, ($level + 1), '', $spaceInd, $subOptions, array(
+                    $content = $nl . self::array2xml($v, $NSprefix, ($level + 1), '', $spaceInd, $subOptions, [
                             'parentTagName' => $tagName,
                             'grandParentTagName' => $stackData['parentTagName'],
                             'path' => ($clearStackPath ? '' : $stackData['path'] . '/' . $tagName)
-                        )) . ($spaceInd >= 0 ? str_pad('', ($level + 1) * $indentN, $indentChar) : '');
+                        ]) . ($spaceInd >= 0 ? str_pad('', ($level + 1) * $indentN, $indentChar) : '');
                 }
                 // Do not set "type = array". Makes prettier XML but means that empty arrays are not restored with xml2array
                 if ((int)$options['disableTypeAttrib'] != 2) {
@@ -1754,7 +1539,7 @@ class GeneralUtility
                     // Otherwise, just htmlspecialchar the stuff:
                     $content = htmlspecialchars($v);
                     $dType = gettype($v);
-                    if ($dType == 'string') {
+                    if ($dType === 'string') {
                         if ($options['useCDATA'] && $content != $v) {
                             $content = '<![CDATA[' . $v . ']]>';
                         }
@@ -1789,13 +1574,13 @@ class GeneralUtility
      */
     public static function xml2array($string, $NSprefix = '', $reportDocTag = false)
     {
-        static $firstLevelCache = array();
+        static $firstLevelCache = [];
         $identifier = md5($string . $NSprefix . ($reportDocTag ? '1' : '0'));
         // Look up in first level cache
         if (!empty($firstLevelCache[$identifier])) {
             $array = $firstLevelCache[$identifier];
         } else {
-            $array = self::xml2arrayProcess($string, $NSprefix, $reportDocTag);
+            $array = self::xml2arrayProcess(trim($string), $NSprefix, $reportDocTag);
             // Store content in first level cache
             $firstLevelCache[$identifier] = $array;
         }
@@ -1818,12 +1603,12 @@ class GeneralUtility
         $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
         // Create parser:
         $parser = xml_parser_create();
-        $vals = array();
-        $index = array();
+        $vals = [];
+        $index = [];
         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
         xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
         // Default output charset is UTF-8, only ASCII, ISO-8859-1 and UTF-8 are supported!!!
-        $match = array();
+        $match = [];
         preg_match('/^[[:space:]]*<\\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/', substr($string, 0, 200), $match);
         $theCharset = $match[1] ?: 'utf-8';
         // us-ascii / utf-8 / iso-8859-1
@@ -1837,9 +1622,9 @@ class GeneralUtility
         }
         xml_parser_free($parser);
         // Init vars:
-        $stack = array(array());
+        $stack = [[]];
         $stacktop = 0;
-        $current = array();
+        $current = [];
         $tagName = '';
         $documentTag = '';
         // Traverse the parsed XML structure:
@@ -1856,7 +1641,7 @@ class GeneralUtility
             // Closing tag.
             $tagName = $tagName[0] === 'n' && MathUtility::canBeInterpretedAsInteger($testNtag) ? (int)$testNtag : $tagName;
             // Test for alternative index value:
-            if ((string)$val['attributes']['index'] !== '') {
+            if ((string)($val['attributes']['index'] ?? '') !== '') {
                 $tagName = $val['attributes']['index'];
             }
             // Setting tag-values, manage stack:
@@ -1864,9 +1649,9 @@ class GeneralUtility
                 case 'open':
                     // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
                     // Setting blank place holder
-                    $current[$tagName] = array();
+                    $current[$tagName] = [];
                     $stack[$stacktop++] = $current;
-                    $current = array();
+                    $current = [];
                     break;
                 case 'close':
                     // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
@@ -1879,18 +1664,18 @@ class GeneralUtility
                     break;
                 case 'complete':
                     // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
-                    if ($val['attributes']['base64']) {
+                    if (!empty($val['attributes']['base64'])) {
                         $current[$tagName] = base64_decode($val['value']);
                     } else {
                         // Had to cast it as a string - otherwise it would be evaluate FALSE if tested with isset()!!
-                        $current[$tagName] = (string)$val['value'];
+                        $current[$tagName] = (string)($val['value'] ?? '');
                         // Cast type:
-                        switch ((string)$val['attributes']['type']) {
+                        switch ((string)($val['attributes']['type'] ?? '')) {
                             case 'integer':
                                 $current[$tagName] = (int)$current[$tagName];
                                 break;
                             case 'double':
-                                $current[$tagName] = (double) $current[$tagName];
+                                $current[$tagName] = (double)$current[$tagName];
                                 break;
                             case 'boolean':
                                 $current[$tagName] = (bool)$current[$tagName];
@@ -1900,7 +1685,7 @@ class GeneralUtility
                                 break;
                             case 'array':
                                 // MUST be an empty array since it is processed as a value; Empty arrays would end up here because they would have no tags inside...
-                                $current[$tagName] = array();
+                                $current[$tagName] = [];
                                 break;
                         }
                     }
@@ -1926,14 +1711,14 @@ class GeneralUtility
         foreach ($vals as $val) {
             $type = $val['type'];
             // Open tag:
-            if ($type == 'open' || $type == 'complete') {
+            if ($type === 'open' || $type === 'complete') {
                 $XMLcontent .= '<' . $val['tag'];
                 if (isset($val['attributes'])) {
                     foreach ($val['attributes'] as $k => $v) {
                         $XMLcontent .= ' ' . $k . '="' . htmlspecialchars($v) . '"';
                     }
                 }
-                if ($type == 'complete') {
+                if ($type === 'complete') {
                     if (isset($val['value'])) {
                         $XMLcontent .= '>' . htmlspecialchars($val['value']) . '</' . $val['tag'] . '>';
                     } else {
@@ -1942,16 +1727,16 @@ class GeneralUtility
                 } else {
                     $XMLcontent .= '>';
                 }
-                if ($type == 'open' && isset($val['value'])) {
+                if ($type === 'open' && isset($val['value'])) {
                     $XMLcontent .= htmlspecialchars($val['value']);
                 }
             }
             // Finish tag:
-            if ($type == 'close') {
+            if ($type === 'close') {
                 $XMLcontent .= '</' . $val['tag'] . '>';
             }
             // Cdata
-            if ($type == 'cdata') {
+            if ($type === 'cdata') {
                 $XMLcontent .= htmlspecialchars($val['value']);
             }
         }
@@ -1959,22 +1744,6 @@ class GeneralUtility
     }
 
     /**
-     * Extracts the attributes (typically encoding and version) of an XML prologue (header).
-     *
-     * @param string $xmlData XML data
-     * @return array Attributes of the xml prologue (header)
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9.
-     */
-    public static function xmlGetHeaderAttribs($xmlData)
-    {
-        self::logDeprecatedFunction();
-        $match = array();
-        if (preg_match('/^\\s*<\\?xml([^>]*)\\?\\>/', $xmlData, $match)) {
-            return self::get_tag_attributes($match[1]);
-        }
-    }
-
-    /**
      * Minifies JavaScript
      *
      * @param string $script Script to minify
@@ -1983,21 +1752,19 @@ class GeneralUtility
      */
     public static function minifyJavaScript($script, &$error = '')
     {
-        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'])) {
-            $fakeThis = false;
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'] as $hookMethod) {
-                try {
-                    $parameters = array('script' => $script);
-                    $script = static::callUserFunction($hookMethod, $parameters, $fakeThis);
-                } catch (\Exception $e) {
-                    $errorMessage = 'Error minifying java script: ' . $e->getMessage();
-                    $error .= $errorMessage;
-                    static::devLog($errorMessage, \TYPO3\CMS\Core\Utility\GeneralUtility::class, 2, array(
-                        'JavaScript' => $script,
-                        'Stack trace' => $e->getTrace(),
-                        'hook' => $hookMethod
-                    ));
-                }
+        $fakeThis = false;
+        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'] ?? [] as $hookMethod) {
+            try {
+                $parameters = ['script' => $script];
+                $script = static::callUserFunction($hookMethod, $parameters, $fakeThis);
+            } catch (\Exception $e) {
+                $errorMessage = 'Error minifying java script: ' . $e->getMessage();
+                $error .= $errorMessage;
+                static::getLogger()->warning($errorMessage, [
+                    'JavaScript' => $script,
+                    'hook' => $hookMethod,
+                    'exception' => $e,
+                ]);
             }
         }
         return $script;
@@ -2041,7 +1808,7 @@ class GeneralUtility
                 $response = $requestFactory->request($url, 'GET', $configuration);
             } catch (RequestException $exception) {
                 if (isset($report)) {
-                    $report['error'] = $exception->getHandlerContext()['errno'];
+                    $report['error'] = $exception->getCode() ?: 1518707554;
                     $report['message'] = $exception->getMessage();
                     $report['exception'] = $exception;
                 }
@@ -2055,8 +1822,8 @@ class GeneralUtility
             if ($includeHeader) {
                 $parsedURL = parse_url($url);
                 $method = $includeHeader === 2 ? 'HEAD' : 'GET';
-                $content = $method . ' ' . (isset($parsedURL['path']) ? $parsedURL['path'] : '/')
-                    . ($parsedURL['query'] ? '?' . $parsedURL['query'] : '') . ' HTTP/1.0' . CRLF
+                $content = $method . ' ' . ($parsedURL['path'] ?? '/')
+                    . (!empty($parsedURL['query']) ? '?' . $parsedURL['query'] : '') . ' HTTP/1.0' . CRLF
                     . 'Host: ' . $parsedURL['host'] . CRLF
                     . 'Connection: close' . CRLF;
                 if (is_array($requestHeaders)) {
@@ -2076,7 +1843,7 @@ class GeneralUtility
                 $report['lib'] = 'http';
                 if ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) {
                     $report['http_code'] = $response->getStatusCode();
-                    $report['content_type'] = $response->getHeader('Content-type');
+                    $report['content_type'] = $response->getHeader('Content-Type');
                     $report['error'] = $response->getStatusCode();
                     $report['message'] = $response->getReasonPhrase();
                 } elseif (!empty($content)) {
@@ -2085,7 +1852,7 @@ class GeneralUtility
                 } elseif ($includeHeader) {
                     // Set only for $includeHeader to work exactly like PHP variant
                     $report['http_code'] = $response->getStatusCode();
-                    $report['content_type'] = $response->getHeader('Content-type');
+                    $report['content_type'] = $response->getHeader('Content-Type');
                 }
             }
         } else {
@@ -2148,13 +1915,9 @@ class GeneralUtility
         }
         if (static::isAllowedAbsPath($path)) {
             if (@is_file($path)) {
-                $targetPermissions = isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'])
-                    ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask']
-                    : '0644';
+                $targetPermissions = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] ?? '0644';
             } elseif (@is_dir($path)) {
-                $targetPermissions = isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'])
-                    ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']
-                    : '0755';
+                $targetPermissions = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask'] ?? '0755';
             }
             if (!empty($targetPermissions)) {
                 // make sure it's always 4 digits
@@ -2175,20 +1938,22 @@ class GeneralUtility
             // Call recursive if recursive flag if set and $path is directory
             if ($recursive && @is_dir($path)) {
                 $handle = opendir($path);
-                while (($file = readdir($handle)) !== false) {
-                    $recursionResult = null;
-                    if ($file !== '.' && $file !== '..') {
-                        if (@is_file(($path . '/' . $file))) {
-                            $recursionResult = static::fixPermissions($path . '/' . $file);
-                        } elseif (@is_dir(($path . '/' . $file))) {
-                            $recursionResult = static::fixPermissions($path . '/' . $file, true);
-                        }
-                        if (isset($recursionResult) && !$recursionResult) {
-                            $result = false;
+                if (is_resource($handle)) {
+                    while (($file = readdir($handle)) !== false) {
+                        $recursionResult = null;
+                        if ($file !== '.' && $file !== '..') {
+                            if (@is_file(($path . '/' . $file))) {
+                                $recursionResult = static::fixPermissions($path . '/' . $file);
+                            } elseif (@is_dir(($path . '/' . $file))) {
+                                $recursionResult = static::fixPermissions($path . '/' . $file, true);
+                            }
+                            if (isset($recursionResult) && !$recursionResult) {
+                                $result = false;
+                            }
                         }
                     }
+                    closedir($handle);
                 }
-                closedir($handle);
             }
         }
         return $result;
@@ -2204,10 +1969,6 @@ class GeneralUtility
      */
     public static function writeFileToTypo3tempDir($filepath, $content)
     {
-        if (!defined('PATH_site')) {
-            return 'PATH_site constant was NOT defined!';
-        }
-
         // Parse filepath into directory and basename:
         $fI = pathinfo($filepath);
         $fI['dirname'] .= '/';
@@ -2229,7 +1990,7 @@ class GeneralUtility
             if (preg_match('#^(?:[[:alnum:]_]+/)+$#', $subdir)) {
                 $dirName .= $subdir;
                 if (!@is_dir($dirName)) {
-                    static::mkdir_deep(PATH_site . 'typo3temp/', $subdir);
+                    static::mkdir_deep(PATH_site . 'typo3temp/' . $subdir);
                 }
             } else {
                 return 'Subdir, "' . $subdir . '", was NOT on the form "[[:alnum:]_]/+"';
@@ -2237,13 +1998,13 @@ class GeneralUtility
         }
         // Checking dir-name again (sub-dir might have been created):
         if (@is_dir($dirName)) {
-            if ($filepath == $dirName . $fI['basename']) {
+            if ($filepath === $dirName . $fI['basename']) {
                 static::writeFile($filepath, $content);
                 if (!@is_file($filepath)) {
                     return 'The file was not written to the disk. Please, check that you have write permissions to the typo3temp/ directory.';
                 }
             } else {
-                return 'Calculated filelocation didn\'t match input "' . $filepath . '".';
+                return 'Calculated file location didn\'t match input "' . $filepath . '".';
             }
         } else {
             return '"' . $dirName . '" is not a directory!';
@@ -2274,7 +2035,6 @@ class GeneralUtility
      *
      * @param string $directory Target directory to create. Must a have trailing slash
      * @param string $deepDirectory Directory to create. This second parameter
-     * @return void
      * @throws \InvalidArgumentException If $directory or $deepDirectory are not strings
      * @throws \RuntimeException If directory could not be created
      */
@@ -2287,8 +2047,12 @@ class GeneralUtility
             throw new \InvalidArgumentException('The specified directory is of type "' . gettype($deepDirectory) . '" but a string is expected.', 1303662956);
         }
         // Ensure there is only one slash
-        $fullPath = rtrim($directory, '/') . '/' . ltrim($deepDirectory, '/');
-        if ($fullPath !== '' && !is_dir($fullPath)) {
+        $fullPath = rtrim($directory, '/') . '/';
+        if ($deepDirectory !== '') {
+            trigger_error('Second argument $deepDirectory of GeneralUtility::mkdir_deep() will be removed in TYPO3 v10.0, use a combined string as first argument instead.', E_USER_DEPRECATED);
+            $fullPath .= ltrim($deepDirectory, '/');
+        }
+        if ($fullPath !== '/' && !is_dir($fullPath)) {
             $firstCreatedPath = static::createDirectoryPath($fullPath);
             if ($firstCreatedPath !== '') {
                 static::fixPermissions($firstCreatedPath, true);
@@ -2344,7 +2108,7 @@ class GeneralUtility
             if (!is_link($path) && is_dir($path)) {
                 if ($removeNonEmpty == true && ($handle = @opendir($path))) {
                     while ($OK && false !== ($file = readdir($handle))) {
-                        if ($file == '.' || $file == '..') {
+                        if ($file === '.' || $file === '..') {
                             continue;
                         }
                         $OK = static::rmdir($path . '/' . $file, $removeNonEmpty);
@@ -2390,7 +2154,7 @@ class GeneralUtility
             $temporaryDirectory = rtrim($directory, '/') . '.' . StringUtility::getUniqueId('remove') . '/';
             if (rename($directory, $temporaryDirectory)) {
                 if ($flushOpcodeCache) {
-                    GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($directory);
+                    self::makeInstance(OpcodeCacheService::class)->clearAllActive($directory);
                 }
                 if ($keepOriginalDirectory) {
                     static::mkdir($directory);
@@ -2412,12 +2176,13 @@ class GeneralUtility
      */
     public static function get_dirs($path)
     {
+        $dirs = null;
         if ($path) {
             if (is_dir($path)) {
                 $dir = scandir($path);
-                $dirs = array();
+                $dirs = [];
                 foreach ($dir as $entry) {
-                    if (is_dir($path . '/' . $entry) && $entry != '..' && $entry != '.') {
+                    if (is_dir($path . '/' . $entry) && $entry !== '..' && $entry !== '.') {
                         $dirs[] = $entry;
                     }
                 }
@@ -2445,7 +2210,7 @@ class GeneralUtility
         $excludePattern = (string)$excludePattern;
         $path = rtrim($path, '/');
         if (!@is_dir($path)) {
-            return array();
+            return [];
         }
 
         $rawFileList = scandir($path);
@@ -2454,23 +2219,26 @@ class GeneralUtility
         }
 
         $pathPrefix = $path . '/';
-        $extensionList = ',' . $extensionList . ',';
-        $files = array();
+        $allowedFileExtensionArray = self::trimExplode(',', $extensionList);
+        $extensionList = ',' . str_replace(' ', '', $extensionList) . ',';
+        $files = [];
         foreach ($rawFileList as $entry) {
             $completePathToEntry = $pathPrefix . $entry;
             if (!@is_file($completePathToEntry)) {
                 continue;
             }
 
-            if (
-                ($extensionList === ',,' || stripos($extensionList, ',' . pathinfo($entry, PATHINFO_EXTENSION) . ',') !== false)
-                && ($excludePattern === '' || !preg_match(('/^' . $excludePattern . '$/'), $entry))
-            ) {
-                if ($order !== 'mtime') {
-                    $files[] = $entry;
-                } else {
-                    // Store the value in the key so we can do a fast asort later.
-                    $files[$entry] = filemtime($completePathToEntry);
+            foreach ($allowedFileExtensionArray as $allowedFileExtension) {
+                if (
+                    ($extensionList === ',,' || stripos($extensionList, ',' . substr($entry, strlen($allowedFileExtension) * -1, strlen($allowedFileExtension)) . ',') !== false)
+                    && ($excludePattern === '' || !preg_match(('/^' . $excludePattern . '$/'), $entry))
+                ) {
+                    if ($order !== 'mtime') {
+                        $files[] = $entry;
+                    } else {
+                        // Store the value in the key so we can do a fast asort later.
+                        $files[$entry] = filemtime($completePathToEntry);
+                    }
                 }
             }
         }
@@ -2482,7 +2250,7 @@ class GeneralUtility
         }
 
         $valuePathPrefix = $prependPath ? $pathPrefix : '';
-        $foundFiles = array();
+        $foundFiles = [];
         foreach ($files as $key => $value) {
             // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension)
             $foundFiles[md5($pathPrefix . ${$valueName})] = $valuePathPrefix . ${$valueName};
@@ -2547,7 +2315,7 @@ class GeneralUtility
      */
     public static function fixWindowsFilePath($theFile)
     {
-        return str_replace(array('\\', '//'), '/', $theFile);
+        return str_replace(['\\', '//'], '/', $theFile);
     }
 
     /**
@@ -2563,7 +2331,7 @@ class GeneralUtility
             return $pathStr;
         }
         $parts = explode('/', $pathStr);
-        $output = array();
+        $output = [];
         $c = 0;
         foreach ($parts as $part) {
             if ($part === '..') {
@@ -2630,7 +2398,7 @@ class GeneralUtility
      */
     public static function getBytesFromSizeMeasurement($measurement)
     {
-        $bytes = doubleval($measurement);
+        $bytes = (float)$measurement;
         if (stripos($measurement, 'G')) {
             $bytes *= 1024 * 1024 * 1024;
         } elseif (stripos($measurement, 'M')) {
@@ -2642,18 +2410,6 @@ class GeneralUtility
     }
 
     /**
-     * Retrieves the maximum path length that is valid in the current environment.
-     *
-     * @return int The maximum available path length
-     * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
-     */
-    public static function getMaximumPathLength()
-    {
-        static::logDeprecatedFunction();
-        return PHP_MAXPATHLEN;
-    }
-
-    /**
      * Function for static version numbers on files, based on the filemtime
      *
      * This will make the filename automatically change when a file is
@@ -2675,7 +2431,7 @@ class GeneralUtility
         $path = self::resolveBackPath(self::dirname(PATH_thisScript) . '/' . $lookupFile[0]);
 
         $doNothing = false;
-        if (TYPO3_MODE == 'FE') {
+        if (TYPO3_MODE === 'FE') {
             $mode = strtolower($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['versionNumberInFilename']);
             if ($mode === 'embed') {
                 $mode = true;
@@ -2689,14 +2445,14 @@ class GeneralUtility
         } else {
             $mode = $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['versionNumberInFilename'];
         }
-        if (!file_exists($path) || $doNothing) {
+        if ($doNothing || !file_exists($path)) {
             // File not found, return filename unaltered
             $fullName = $file;
         } else {
             if (!$mode) {
                 // If use of .htaccess rule is not configured,
                 // we use the default query-string method
-                if ($lookupFile[1]) {
+                if (!empty($lookupFile[1])) {
                     $separator = '&';
                 } else {
                     $separator = '?';
@@ -2729,7 +2485,7 @@ class GeneralUtility
      * @param array $getParams Array of GET parameters to include
      * @return string
      */
-    public static function linkThisScript(array $getParams = array())
+    public static function linkThisScript(array $getParams = [])
     {
         $parts = self::getIndpEnv('SCRIPT_NAME');
         $params = self::_GET();
@@ -2752,10 +2508,10 @@ class GeneralUtility
      * @param array $getParams Array of key/value pairs for get parameters to add/overrule with. Can be multidimensional.
      * @return string Output URL with added getParams.
      */
-    public static function linkThisUrl($url, array $getParams = array())
+    public static function linkThisUrl($url, array $getParams = [])
     {
         $parts = parse_url($url);
-        $getP = array();
+        $getP = [];
         if ($parts['query']) {
             parse_str($parts['query'], $getP);
         }
@@ -2844,7 +2600,7 @@ class GeneralUtility
                 break;
             case 'REQUEST_URI':
                 // Typical application of REQUEST_URI is return urls, forms submitting to itself etc. Example: returnUrl='.rawurlencode(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI'))
-                if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar']) {
+                if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar'])) {
                     // This is for URL rewriters that store the original URI in a server variable (eg ISAPI_Rewriter for IIS: HTTP_X_REWRITE_URL)
                     list($v, $n) = explode('|', $GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar']);
                     $retVal = $GLOBALS[$v][$n];
@@ -2905,7 +2661,7 @@ class GeneralUtility
                 break;
             case 'HTTP_HOST':
                 // if it is not set we're most likely on the cli
-                $retVal = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null;
+                $retVal = $_SERVER['HTTP_HOST'] ?? null;
                 if (isset($_SERVER['REMOTE_ADDR']) && static::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'])) {
                     $host = self::trimExplode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
                     // Choose which host in list to use
@@ -2945,7 +2701,6 @@ class GeneralUtility
             case 'REMOTE_HOST':
 
             case 'QUERY_STRING':
-                $retVal = '';
                 if (isset($_SERVER[$getEnvName])) {
                     $retVal = $_SERVER[$getEnvName];
                 }
@@ -2958,7 +2713,7 @@ class GeneralUtility
                 $SFN = self::getIndpEnv('SCRIPT_FILENAME');
                 $SN_A = explode('/', strrev(self::getIndpEnv('SCRIPT_NAME')));
                 $SFN_A = explode('/', strrev($SFN));
-                $acc = array();
+                $acc = [];
                 foreach ($SN_A as $kk => $vv) {
                     if ((string)$SFN_A[$kk] === (string)$vv) {
                         $acc[] = $vv;
@@ -2968,9 +2723,8 @@ class GeneralUtility
                 }
                 $commonEnd = strrev(implode('/', $acc));
                 if ((string)$commonEnd !== '') {
-                    $DR = substr($SFN, 0, -(strlen($commonEnd) + 1));
+                    $retVal = substr($SFN, 0, -(strlen($commonEnd) + 1));
                 }
-                $retVal = $DR;
                 break;
             case 'TYPO3_HOST_ONLY':
                 $httpHost = self::getIndpEnv('HTTP_HOST');
@@ -3003,7 +2757,7 @@ class GeneralUtility
                 } elseif (defined('PATH_thisScript') && defined('PATH_site')) {
                     $lPath = PathUtility::stripPathSitePrefix(dirname(PATH_thisScript)) . '/';
                     $siteUrl = substr($url, 0, -strlen($lPath));
-                    if (substr($siteUrl, -1) != '/') {
+                    if (substr($siteUrl, -1) !== '/') {
                         $siteUrl .= '/';
                     }
                     $retVal = $siteUrl;
@@ -3017,7 +2771,7 @@ class GeneralUtility
                 break;
             case 'TYPO3_SSL':
                 $proxySSL = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxySSL']);
-                if ($proxySSL == '*') {
+                if ($proxySSL === '*') {
                     $proxySSL = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'];
                 }
                 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $proxySSL)) {
@@ -3027,9 +2781,9 @@ class GeneralUtility
                 }
                 break;
             case '_ARRAY':
-                $out = array();
+                $out = [];
                 // Here, list ALL possible keys to this function for debug display.
-                $envTestVars = array(
+                $envTestVars = [
                     'HTTP_HOST',
                     'TYPO3_HOST_ONLY',
                     'TYPO3_PORT',
@@ -3052,7 +2806,7 @@ class GeneralUtility
                     'REMOTE_HOST',
                     'HTTP_USER_AGENT',
                     'HTTP_ACCEPT_LANGUAGE'
-                );
+                ];
                 foreach ($envTestVars as $v) {
                     $out[$v] = self::getIndpEnv($v);
                 }
@@ -3136,7 +2890,7 @@ class GeneralUtility
      */
     protected static function isInternalRequestType()
     {
-        return (!defined('TYPO3_REQUESTTYPE') || (defined('TYPO3_REQUESTTYPE') && TYPO3_REQUESTTYPE & (TYPO3_REQUESTTYPE_INSTALL | TYPO3_REQUESTTYPE_CLI)));
+        return !defined('TYPO3_REQUESTTYPE') || (defined('TYPO3_REQUESTTYPE') && TYPO3_REQUESTTYPE & (TYPO3_REQUESTTYPE_INSTALL | TYPO3_REQUESTTYPE_CLI));
     }
 
     /**
@@ -3160,7 +2914,7 @@ class GeneralUtility
         if (!$useragent) {
             $useragent = self::getIndpEnv('HTTP_USER_AGENT');
         }
-        $bInfo = array();
+        $bInfo = [];
         // Which browser?
         if (strpos($useragent, 'Konqueror') !== false) {
             $bInfo['BROWSER'] = 'konqu';
@@ -3177,29 +2931,29 @@ class GeneralUtility
             // Browser version
             switch ($bInfo['BROWSER']) {
                 case 'net':
-                    $bInfo['VERSION'] = doubleval(substr($useragent, 8));
+                    $bInfo['VERSION'] = (float)substr($useragent, 8);
                     if (strpos($useragent, 'Netscape6/') !== false) {
-                        $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape6/'), 10));
+                        $bInfo['VERSION'] = (float)substr(strstr($useragent, 'Netscape6/'), 10);
                     }
                     // Will we ever know if this was a typo or intention...?! :-(
                     if (strpos($useragent, 'Netscape/6') !== false) {
-                        $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape/6'), 10));
+                        $bInfo['VERSION'] = (float)substr(strstr($useragent, 'Netscape/6'), 10);
                     }
                     if (strpos($useragent, 'Netscape/7') !== false) {
-                        $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape/7'), 9));
+                        $bInfo['VERSION'] = (float)substr(strstr($useragent, 'Netscape/7'), 9);
                     }
                     break;
                 case 'msie':
                     $tmp = strstr($useragent, 'MSIE');
-                    $bInfo['VERSION'] = doubleval(preg_replace('/^[^0-9]*/', '', substr($tmp, 4)));
+                    $bInfo['VERSION'] = (float)preg_replace('/^[^0-9]*/', '', substr($tmp, 4));
                     break;
                 case 'opera':
                     $tmp = strstr($useragent, 'Opera');
-                    $bInfo['VERSION'] = doubleval(preg_replace('/^[^0-9]*/', '', substr($tmp, 5)));
+                    $bInfo['VERSION'] = (float)preg_replace('/^[^0-9]*/', '', substr($tmp, 5));
                     break;
                 case 'konqu':
                     $tmp = strstr($useragent, 'Konqueror/');
-                    $bInfo['VERSION'] = doubleval(substr($tmp, 10));
+                    $bInfo['VERSION'] = (float)substr($tmp, 10);
                     break;
             }
             // Client system
@@ -3264,22 +3018,13 @@ class GeneralUtility
      * \TYPO3\CMS\Core\Utility\GeneralUtility::validPathStr().
      *
      * @param string $filename The input filename/filepath to evaluate
-     * @param bool $_ - obsolete, will be removed in TYPO3 CMS 9
-     * @param bool $_2 - obsolete, will be removed in TYPO3 CMS 9
      * @return string Returns the absolute filename of $filename if valid, otherwise blank string.
      */
-    public static function getFileAbsFileName($filename, $_ = null, $_2 = null)
+    public static function getFileAbsFileName($filename)
     {
         if ((string)$filename === '') {
             return '';
         }
-        if ($_ !== null) {
-            self::deprecationLog('Parameter 2 of GeneralUtility::getFileAbsFileName is obsolete and can be omitted.');
-        }
-        if ($_2 !== null) {
-            self::deprecationLog('Parameter 3 of GeneralUtility::getFileAbsFileName is obsolete and can be omitted.');
-        }
-
         // Extension
         if (strpos($filename, 'EXT:') === 0) {
             list($extKey, $local) = explode('/', substr($filename, 4), 2);
@@ -3297,9 +3042,8 @@ class GeneralUtility
         if ((string)$filename !== '' && static::validPathStr($filename)) {
             // checks backpath.
             return $filename;
-        } else {
-            return '';
         }
+        return '';
     }
 
     /**
@@ -3312,12 +3056,11 @@ class GeneralUtility
      * @param string $theFile File path to evaluate
      * @return bool TRUE, $theFile is allowed path string, FALSE otherwise
      * @see http://php.net/manual/en/security.filesystem.nullbytes.php
-     * @todo Possible improvement: Should it rawurldecode the string first to check if any of these characters is encoded?
      */
     public static function validPathStr($theFile)
     {
         return strpos($theFile, '//') === false && strpos($theFile, '\\') === false
-            && !preg_match('#(?:^\\.\\.|/\\.\\./|[[:cntrl:]])#u', $theFile);
+            && preg_match('#(?:^\\.\\.|/\\.\\./|[[:cntrl:]])#u', $theFile) === 0;
     }
 
     /**
@@ -3378,6 +3121,7 @@ class GeneralUtility
             $destination = PATH_site . $destination;
         }
         if (static::isAllowedAbsPath($source) && static::isAllowedAbsPath($destination)) {
+            static::mkdir_deep($destination);
             $iterator = new \RecursiveIteratorIterator(
                 new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS),
                 \RecursiveIteratorIterator::SELF_FIRST
@@ -3427,7 +3171,7 @@ class GeneralUtility
             }
         }
         if (!empty($url) && empty($sanitizedUrl)) {
-            self::sysLog('The URL "' . $url . '" is not considered to be local and was denied.', 'core', self::SYSLOG_SEVERITY_NOTICE);
+            static::getLogger()->notice('The URL "' . $url . '" is not considered to be local and was denied.');
         }
         return $sanitizedUrl;
     }
@@ -3514,10 +3258,10 @@ class GeneralUtility
     {
         $temporaryPath = PATH_site . 'typo3temp/var/transient/';
         if (!is_dir($temporaryPath)) {
-            GeneralUtility::mkdir_deep($temporaryPath);
+            self::mkdir_deep($temporaryPath);
         }
         if ($fileSuffix === '') {
-            $tempFileName = static::fixWindowsFilePath(tempnam($temporaryPath, $filePrefix));
+            $tempFileName = $temporaryPath . basename(tempnam($temporaryPath, $filePrefix));
         } else {
             do {
                 $tempFileName = $temporaryPath . $filePrefix . mt_rand(1, PHP_INT_MAX) . $fileSuffix;
@@ -3539,7 +3283,7 @@ class GeneralUtility
     public static function stdAuthCode($uid_or_record, $fields = '', $codeLength = 8)
     {
         if (is_array($uid_or_record)) {
-            $recCopy_temp = array();
+            $recCopy_temp = [];
             if ($fields) {
                 $fieldArr = self::trimExplode(',', $fields, true);
                 foreach ($fieldArr as $k => $v) {
@@ -3587,9 +3331,11 @@ class GeneralUtility
      * @param string $language Language key
      * @param bool $sameLocation If TRUE, then locallang localization file name will be returned with same directory as $fileRef
      * @return string Returns the filename reference for the language unless error occurred in which case it will be NULL
+     * @deprecated in TYPO3 v9.0, will be removed in TYPO3 v10.0, as the functionality has been moved into AbstractXmlParser.
      */
     public static function llXmlAutoFileName($fileRef, $language, $sameLocation = false)
     {
+        trigger_error('This method will be removed in TYPO3 v10.0, the functionality has been moved into AbstractXmlParser', E_USER_DEPRECATED);
         // If $fileRef is already prefixed with "[language key]" then we should return it as is
         $fileName = basename($fileRef);
         if (self::isFirstPartOfStr($fileName, $language . '.')) {
@@ -3630,211 +3376,69 @@ class GeneralUtility
     }
 
     /**
-     * Looks for a sheet-definition in the input data structure array. If found it will return the data structure for the sheet given as $sheet (if found).
-     * If the sheet definition is in an external file that file is parsed and the data structure inside of that is returned.
-     *
-     * @param array $dataStructArray Input data structure, possibly with a sheet-definition and references to external data source files.
-     * @param string $sheet The sheet to return, preferably.
-     * @return array An array with two num. keys: key0: The data structure is returned in this key (array) UNLESS an error occurred in which case an error string is returned (string). key1: The used sheet key value!
-     */
-    public static function resolveSheetDefInDS($dataStructArray, $sheet = 'sDEF')
-    {
-        if (!is_array($dataStructArray)) {
-            return 'Data structure must be an array';
-        }
-        if (is_array($dataStructArray['sheets'])) {
-            $singleSheet = false;
-            if (!isset($dataStructArray['sheets'][$sheet])) {
-                $sheet = 'sDEF';
-            }
-            $dataStruct = $dataStructArray['sheets'][$sheet];
-            // If not an array, but still set, then regard it as a relative reference to a file:
-            if ($dataStruct && !is_array($dataStruct)) {
-                $file = self::getFileAbsFileName($dataStruct);
-                if ($file && @is_file($file)) {
-                    $dataStruct = self::xml2array(file_get_contents($file));
-                }
-            }
-        } else {
-            $singleSheet = true;
-            $dataStruct = $dataStructArray;
-            if (isset($dataStruct['meta'])) {
-                unset($dataStruct['meta']);
-            }
-            // Meta data should not appear there.
-            // Default sheet
-            $sheet = 'sDEF';
-        }
-        return array($dataStruct, $sheet, $singleSheet);
-    }
-
-    /**
-     * Resolves ALL sheet definitions in dataStructArray
-     * If no sheet is found, then the default "sDEF" will be created with the dataStructure inside.
-     *
-     * @param array $dataStructArray Input data structure, possibly with a sheet-definition and references to external data source files.
-     * @return array Output data structure with all sheets resolved as arrays.
-     */
-    public static function resolveAllSheetsInDS(array $dataStructArray)
-    {
-        if (is_array($dataStructArray['sheets'])) {
-            $out = array('sheets' => array());
-            foreach ($dataStructArray['sheets'] as $sheetId => $sDat) {
-                list($ds, $aS) = self::resolveSheetDefInDS($dataStructArray, $sheetId);
-                if ($sheetId == $aS) {
-                    $out['sheets'][$aS] = $ds;
-                }
-            }
-        } else {
-            list($ds) = self::resolveSheetDefInDS($dataStructArray);
-            $out = array('sheets' => array('sDEF' => $ds));
-        }
-        return $out;
-    }
-
-    /**
      * Calls a user-defined function/method in class
      * Such a function/method should look like this: "function proc(&$params, &$ref) {...}"
      *
-     * @param string $funcName Function/Method reference or Closure, '[file-reference":"]["&"]class/function["->"method-name]'. You can prefix this reference with "[file-reference]:" and \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName() will then be used to resolve the filename and subsequently include it by "require_once()" which means you don't have to worry about including the class file either! Example: "EXT:realurl/class.tx_realurl.php:&tx_realurl->encodeSpURL". However, using file references has been marked as deprecated and should be avoided, instead use the autoloading mechanism in place directly. Finally; you can prefix the class name with "&" if you want to reuse a former instance of the same object call ("singleton").
+     * @param string $funcName Function/Method reference or Closure.
      * @param mixed $params Parameters to be pass along (typically an array) (REFERENCE!)
      * @param mixed $ref Reference to be passed along (typically "$this" - being a reference to the calling object) (REFERENCE!)
-     * @param string $_ Not used anymore since 6.0
-     * @param int $errorMode Error mode (when class/function could not be found): 0 - call debug(), 1 - do nothing, 2 - raise an exception (allows to call a user function that may return FALSE)
-     * @return mixed Content from method/function call or FALSE if the class/method/function was not found
-     * @see getUserObj()
+     * @return mixed Content from method/function call
+     * @throws \InvalidArgumentException
      */
-    public static function callUserFunction($funcName, &$params, &$ref, $_ = '', $errorMode = 0)
+    public static function callUserFunction($funcName, &$params, &$ref)
     {
-        $content = false;
         // Check if we're using a closure and invoke it directly.
         if (is_object($funcName) && is_a($funcName, 'Closure')) {
-            return call_user_func_array($funcName, array(&$params, &$ref));
-        }
-        // Check persistent object and if found, call directly and exit.
-        if (isset($GLOBALS['T3_VAR']['callUserFunction'][$funcName]) && is_array($GLOBALS['T3_VAR']['callUserFunction'][$funcName])) {
-            return call_user_func_array(array(
-                &$GLOBALS['T3_VAR']['callUserFunction'][$funcName]['obj'],
-                $GLOBALS['T3_VAR']['callUserFunction'][$funcName]['method']
-            ), array(&$params, &$ref));
-        }
-        // Check file-reference prefix; if found, require_once() the file (should be library of code)
-        if (strpos($funcName, ':') !== false) {
-            // @deprecated since TYPO3 v8, will be removed in v9
-            self::deprecationLog('Using file references to resolve "' . $funcName . '" has been deprecated in TYPO3 v8 '
-                . 'when calling GeneralUtility::callUserFunction(), make sure the class is available via the class loader. '
-                . 'This functionality will be removed in TYPO3 v9.');
-            list($file, $funcRef) = self::revExplode(':', $funcName, 2);
-            $requireFile = self::getFileAbsFileName($file);
-            if ($requireFile) {
-                require_once $requireFile;
-            }
-        } else {
-            $funcRef = $funcName;
+            return call_user_func_array($funcName, [&$params, &$ref]);
         }
-        // Check for persistent object token, "&"
-        if ($funcRef[0] === '&') {
-            $funcRef = substr($funcRef, 1);
-            $storePersistentObject = true;
-        } else {
-            $storePersistentObject = false;
-        }
-        // Call function or method:
-        $parts = explode('->', $funcRef);
+        $funcName = trim($funcName);
+        $parts = explode('->', $funcName);
+        // Call function or method
         if (count($parts) === 2) {
-            // Class
+            // It's a class/method
             // Check if class/method exists:
             if (class_exists($parts[0])) {
-                // Get/Create object of class:
-                if ($storePersistentObject) {
-                    // Get reference to current instance of class:
-                    if (!is_object($GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]])) {
-                        $GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]] = self::makeInstance($parts[0]);
-                    }
-                    $classObj = $GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]];
-                } else {
-                    // Create new object:
-                    $classObj = self::makeInstance($parts[0]);
-                }
+                // Create object
+                $classObj = self::makeInstance($parts[0]);
                 if (method_exists($classObj, $parts[1])) {
-                    // If persistent object should be created, set reference:
-                    if ($storePersistentObject) {
-                        $GLOBALS['T3_VAR']['callUserFunction'][$funcName] = array(
-                            'method' => $parts[1],
-                            'obj' => &$classObj
-                        );
-                    }
                     // Call method:
-                    $content = call_user_func_array(array(&$classObj, $parts[1]), array(&$params, &$ref));
+                    $content = call_user_func_array([&$classObj, $parts[1]], [&$params, &$ref]);
                 } else {
                     $errorMsg = 'No method name \'' . $parts[1] . '\' in class ' . $parts[0];
-                    if ($errorMode == 2) {
-                        throw new \InvalidArgumentException($errorMsg, 1294585865);
-                    } elseif (!$errorMode) {
-                        debug($errorMsg, \TYPO3\CMS\Core\Utility\GeneralUtility::class . '::callUserFunction');
-                    }
+                    throw new \InvalidArgumentException($errorMsg, 1294585865);
                 }
             } else {
                 $errorMsg = 'No class named ' . $parts[0];
-                if ($errorMode == 2) {
-                    throw new \InvalidArgumentException($errorMsg, 1294585866);
-                } elseif (!$errorMode) {
-                    debug($errorMsg, \TYPO3\CMS\Core\Utility\GeneralUtility::class . '::callUserFunction');
-                }
+                throw new \InvalidArgumentException($errorMsg, 1294585866);
             }
+        } elseif (function_exists($funcName)) {
+            // It's a function
+            $content = call_user_func_array($funcName, [&$params, &$ref]);
         } else {
-            // Function
-            if (function_exists($funcRef)) {
-                $content = call_user_func_array($funcRef, array(&$params, &$ref));
-            } else {
-                $errorMsg = 'No function named: ' . $funcRef;
-                if ($errorMode == 2) {
-                    throw new \InvalidArgumentException($errorMsg, 1294585867);
-                } elseif (!$errorMode) {
-                    debug($errorMsg, \TYPO3\CMS\Core\Utility\GeneralUtility::class . '::callUserFunction');
-                }
-            }
+            $errorMsg = 'No function named: ' . $funcName;
+            throw new \InvalidArgumentException($errorMsg, 1294585867);
         }
         return $content;
     }
 
     /**
-     * This method should be avoided, as it will be deprecated soon. Instead use makeInstance() directly.
+     * This method should be avoided, as it will be deprecated completely in TYPO3 v9, and will be removed in TYPO3 v10.
+     * Instead use makeInstance() directly.
      *
      * Creates and returns reference to a user defined object.
      * This function can return an object reference if you like.
      *
-     * @param string $classRef Class reference, '[file-reference":"]class-name'.
-     *                         You can prefix the class name with "[file-reference]:" and
-     *                         GeneralUtility::getFileAbsFileName() will then be used to resolve the filename and
-     *                         subsequently include it by "require_once()" which means you don't have to worry about
-     *                         including the class file either! Example: "EXT:realurl/class.tx_realurl.php:tx_realurl".
-     *                         However, the file reference part is marked as deprecated as the class loading mechanism
-     *                         via composer or the autoloading part of TYPO3 should be used instead.
+     * @param string $className Class name
      * @return object The instance of the class asked for. Instance is created with GeneralUtility::makeInstance
      * @see callUserFunction()
+     * @deprecated
      */
-    public static function getUserObj($classRef)
+    public static function getUserObj($className)
     {
-        // Check file-reference prefix; if found, require_once() the file (should be library of code)
-        if (strpos($classRef, ':') !== false) {
-            // @deprecated since TYPO3 v8, will be removed in v9
-            self::deprecationLog('Using file references to resolve "' . $classRef . '" has been deprecated in TYPO3 v8 '
-                . 'when calling GeneralUtility::getUserObj(), make sure the class is available via the class loader. '
-                . 'This functionality will be removed in TYPO3 v9.');
-            list($file, $class) = self::revExplode(':', $classRef, 2);
-            $requireFile = self::getFileAbsFileName($file);
-            if ($requireFile) {
-                require_once $requireFile;
-            }
-        } else {
-            $class = $classRef;
-        }
-
+        trigger_error('This method will be removed in TYPO3 v10.0, use GeneralUtility::makeInstance() directly instead', E_USER_DEPRECATED);
         // Check if class exists:
-        if (class_exists($class)) {
-            $classObj = self::makeInstance($class);
-            return $classObj;
+        if (class_exists($className)) {
+            return self::makeInstance($className);
         }
     }
 
@@ -3853,7 +3457,7 @@ class GeneralUtility
      * the instance of a specific class.
      *
      * @param string $className name of the class to instantiate, must not be empty and not start with a backslash
-     * @param mixed $constructorArguments Arguments for the constructor
+     * @param array<int, mixed> $constructorArguments Arguments for the constructor
      * @return object the created instance
      * @throws \InvalidArgumentException if $className is empty or starts with a backslash
      */
@@ -3865,7 +3469,8 @@ class GeneralUtility
         // Never instantiate with a beginning backslash, otherwise things like singletons won't work.
         if ($className[0] === '\\') {
             throw new \InvalidArgumentException(
-                '$className "' . $className . '" must not start with a backslash.', 1420281366
+                '$className "' . $className . '" must not start with a backslash.',
+                1420281366
             );
         }
         if (isset(static::$finalClassNameCache[$className])) {
@@ -3891,6 +3496,9 @@ class GeneralUtility
         if ($instance instanceof SingletonInterface) {
             self::$singletonInstances[$finalClassName] = $instance;
         }
+        if ($instance instanceof LoggerAwareInterface) {
+            $instance->setLogger(static::makeInstance(LogManager::class)->getLogger($className));
+        }
         return $instance;
     }
 
@@ -3930,14 +3538,7 @@ class GeneralUtility
      */
     protected static function classHasImplementation($className)
     {
-        // If we are early in the bootstrap, the configuration might not yet be present
-        if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'])) {
-            return false;
-        }
-
-        return isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$className])
-                && is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$className])
-                && !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$className]['className']);
+        return !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$className]['className']);
     }
 
     /**
@@ -3955,7 +3556,6 @@ class GeneralUtility
      * @see makeInstance
      * @param string $className
      * @param \TYPO3\CMS\Core\SingletonInterface $instance
-     * @return void
      * @internal
      */
     public static function setSingletonInstance($className, SingletonInterface $instance)
@@ -3977,7 +3577,6 @@ class GeneralUtility
      * @throws \InvalidArgumentException
      * @param string $className
      * @param \TYPO3\CMS\Core\SingletonInterface $instance
-     * @return void
      * @internal
      */
     public static function removeSingletonInstance($className, SingletonInterface $instance)
@@ -4004,11 +3603,10 @@ class GeneralUtility
      *
      * @internal
      * @param array $newSingletonInstances $className => $object
-     * @return void
      */
     public static function resetSingletonInstances(array $newSingletonInstances)
     {
-        static::$singletonInstances = array();
+        static::$singletonInstances = [];
         foreach ($newSingletonInstances as $className => $instance) {
             static::setSingletonInstance($className, $instance);
         }
@@ -4044,7 +3642,6 @@ class GeneralUtility
      * @throws \InvalidArgumentException if class extends \TYPO3\CMS\Core\SingletonInterface
      * @param string $className
      * @param object $instance
-     * @return void
      */
     public static function addInstance($className, $instance)
     {
@@ -4053,7 +3650,7 @@ class GeneralUtility
             throw new \InvalidArgumentException('$instance must not be an instance of TYPO3\\CMS\\Core\\SingletonInterface. ' . 'For setting singletons, please use setSingletonInstance.', 1288969325);
         }
         if (!isset(self::$nonSingletonInstances[$className])) {
-            self::$nonSingletonInstances[$className] = array();
+            self::$nonSingletonInstances[$className] = [];
         }
         self::$nonSingletonInstances[$className][] = $instance;
     }
@@ -4065,7 +3662,6 @@ class GeneralUtility
      * @throws \InvalidArgumentException if $className is empty or if $instance is no instance of $className
      * @param string $className a class name
      * @param object $instance an object
-     * @return void
      */
     protected static function checkInstanceClassName($className, $instance)
     {
@@ -4086,12 +3682,11 @@ class GeneralUtility
      * Warning: This is a helper method for unit tests. Do not call this directly in production code!
      *
      * @see makeInstance
-     * @return void
      */
     public static function purgeInstances()
     {
-        self::$singletonInstances = array();
-        self::$nonSingletonInstances = array();
+        self::$singletonInstances = [];
+        self::$nonSingletonInstances = [];
     }
 
     /**
@@ -4099,7 +3694,6 @@ class GeneralUtility
      *
      * Used in unit tests only.
      *
-     * @return void
      * @internal
      */
     public static function flushInternalRuntimeCaches()
@@ -4117,17 +3711,17 @@ class GeneralUtility
      * @param mixed $excludeServiceKeys List of service keys which should be excluded in the search for a service. Array or comma list.
      * @return object|string[] The service object or an array with error infos.
      */
-    public static function makeInstanceService($serviceType, $serviceSubType = '', $excludeServiceKeys = array())
+    public static function makeInstanceService($serviceType, $serviceSubType = '', $excludeServiceKeys = [])
     {
         $error = false;
         if (!is_array($excludeServiceKeys)) {
             $excludeServiceKeys = self::trimExplode(',', $excludeServiceKeys, true);
         }
-        $requestInfo = array(
+        $requestInfo = [
             'requestedServiceType' => $serviceType,
             'requestedServiceSubType' => $serviceSubType,
             'requestedExcludeServiceKeys' => $excludeServiceKeys
-        );
+        ];
         while ($info = ExtensionManagementUtility::findService($serviceType, $serviceSubType, $excludeServiceKeys)) {
             // provide information about requested service to service object
             $info = array_merge($info, $requestInfo);
@@ -4138,24 +3732,24 @@ class GeneralUtility
                 // reset service and return object
                 $GLOBALS['T3_VAR']['makeInstanceService'][$info['className']]->reset();
                 return $GLOBALS['T3_VAR']['makeInstanceService'][$info['className']];
-            } else {
-                $obj = self::makeInstance($info['className']);
-                if (is_object($obj)) {
-                    if (!@is_callable(array($obj, 'init'))) {
-                        // use silent logging??? I don't think so.
-                        die('Broken service:' . DebugUtility::viewArray($info));
-                    }
-                    $obj->info = $info;
-                    // service available?
-                    if ($obj->init()) {
-                        // create persistent object
-                        $GLOBALS['T3_VAR']['makeInstanceService'][$info['className']] = $obj;
-                        return $obj;
-                    }
-                    $error = $obj->getLastErrorArray();
-                    unset($obj);
+            }
+            $obj = self::makeInstance($info['className']);
+            if (is_object($obj)) {
+                if (!@is_callable([$obj, 'init'])) {
+                    // use silent logging??? I don't think so.
+                    die('Broken service:' . DebugUtility::viewArray($info));
                 }
+                $obj->info = $info;
+                // service available?
+                if ($obj->init()) {
+                    // create persistent object
+                    $GLOBALS['T3_VAR']['makeInstanceService'][$info['className']] = $obj;
+                    return $obj;
+                }
+                $error = $obj->getLastErrorArray();
+                unset($obj);
             }
+
             // deactivate the service
             ExtensionManagementUtility::deactivateService($info['serviceType'], $info['serviceKey']);
         }
@@ -4163,137 +3757,39 @@ class GeneralUtility
     }
 
     /**
-     * Require a class for TYPO3
-     * Useful to require classes from inside other classes (not global scope). A limited set of global variables are available (see function)
-     *
-     * @param string $requireFile: Path of the file to be included
-     * @return void
-     * @deprecated since TYPO3 CMS 8, this file will be removed in TYPO3 CMS 9
-     */
-    public static function requireOnce($requireFile)
-    {
-        self::logDeprecatedFunction();
-        // Needed for require_once
-        global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;
-        require_once $requireFile;
-    }
-
-    /**
-     * Requires a class for TYPO3
-     * Useful to require classes from inside other classes (not global scope).
-     * A limited set of global variables are available (see function)
-     *
-     * @param string $requireFile: Path of the file to be included
-     * @return void
-     * @deprecated since TYPO3 CMS 8, this file will be removed in TYPO3 CMS 9
-     */
-    public static function requireFile($requireFile)
-    {
-        self::logDeprecatedFunction();
-        // Needed for require
-        global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;
-        require $requireFile;
-    }
-
-    /**
-     * Create a shortened "redirect" URL with specified length from an incoming URL
-     *
-     * @param string $inUrl Input URL
-     * @param int $l URL string length limit
-     * @param string $index_script_url URL of "index script" - the prefix of the "?RDCT=..." parameter. If not supplied it will default to \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR').'index.php'
-     * @return string Processed URL
-     */
-    public static function makeRedirectUrl($inUrl, $l = 0, $index_script_url = '')
-    {
-        if (strlen($inUrl) > $l) {
-            $md5 = substr(md5($inUrl), 0, 20);
-            $connection = self::makeInstance(ConnectionPool::class)->getConnectionForTable('cache_md5params');
-            $count = $connection->count(
-                '*',
-                'cache_md5params',
-                ['md5hash' => $md5]
-            );
-            if (!$count) {
-                $connection->insert(
-                    'cache_md5params',
-                    [
-                        'md5hash' => $md5,
-                        'tstamp'  => $GLOBALS['EXEC_TIME'],
-                        'type'    => 2,
-                        'params'  => $inUrl
-                    ]
-                );
-            }
-            $inUrl = ($index_script_url ?: self::getIndpEnv('TYPO3_REQUEST_DIR') . 'index.php') . '?RDCT=' . $md5;
-        }
-        return $inUrl;
-    }
-
-    /**
-     * Function to compensate for DPI resolution.
-     *
-     * @param float $fontSize font size for freetype function call
-     *
-     * @return float compensated font size based on 96 dpi
-     */
-    public static function freetypeDpiComp($fontSize)
-    {
-        // FreeType 2 always has 96 dpi.
-        $dpi = 96.0;
-        return $fontSize / $dpi * 72;
-    }
-
-    /**
      * Initialize the system log.
      *
-     * @return void
      * @see sysLog()
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10
      */
     public static function initSysLog()
     {
-        // For CLI logging name is <fqdn-hostname>:<TYPO3-path>
-        if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
-            $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] = self::getHostname() . ':' . PATH_site;
-        } else {
-            $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] = self::getIndpEnv('TYPO3_SITE_URL');
-        }
         // Init custom logging
-        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) {
-            $params = array('initLog' => true);
-            $fakeThis = false;
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] as $hookMethod) {
-                self::callUserFunction($hookMethod, $params, $fakeThis);
-            }
-        }
-        // Init TYPO3 logging
-        foreach (explode(';', $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog'], 2) as $log) {
-            list($type, $destination) = explode(',', $log, 3);
-            if ($type == 'syslog') {
-                if (TYPO3_OS == 'WIN') {
-                    $facility = LOG_USER;
-                } else {
-                    $facility = constant('LOG_' . strtoupper($destination));
-                }
-                openlog($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'], LOG_ODELAY, $facility);
-            }
+        $params = ['initLog' => true];
+        $fakeThis = false;
+        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] ?? [] as $hookMethod) {
+            self::callUserFunction($hookMethod, $params, $fakeThis);
         }
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] = MathUtility::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'], 0, 4);
         $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit'] = true;
     }
 
     /**
-     * Logs message to the system log.
+     * Logs message to custom "systemLog" handlers and logging API
+     *
      * This should be implemented around the source code, including the Core and both frontend and backend, logging serious errors.
      * If you want to implement the sysLog in your applications, simply add lines like:
      * \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog('[write message in English here]', 'extension_key', 'severity');
      *
      * @param string $msg Message (in English).
-     * @param string $extKey Extension key (from which extension you are calling the log) or "Core
+     * @param string $extKey Extension key (from which extension you are calling the log) or "Core"
      * @param int $severity \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_* constant
-     * @return void
+     * @deprecated
      */
     public static function sysLog($msg, $extKey, $severity = 0)
     {
+        trigger_error('Method sysLog() is deprecated since v9 and will be removed with v10', E_USER_DEPRECATED);
+
         $severity = MathUtility::forceIntegerInRange($severity, 0, 4);
         // Is message worth logging?
         if ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] > $severity) {
@@ -4303,9 +3799,9 @@ class GeneralUtility
         if (!$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit']) {
             self::initSysLog();
         }
-        // Do custom logging
-        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) {
-            $params = array('msg' => $msg, 'extKey' => $extKey, 'backTrace' => debug_backtrace(), 'severity' => $severity);
+        // Do custom logging; avoid calling debug_backtrace if there are no custom loggers.
+        if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) {
+            $params = ['msg' => $msg, 'extKey' => $extKey, 'backTrace' => debug_backtrace(), 'severity' => $severity];
             $fakeThis = false;
             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] as $hookMethod) {
                 self::callUserFunction($hookMethod, $params, $fakeThis);
@@ -4315,40 +3811,8 @@ class GeneralUtility
         if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog']) {
             return;
         }
-        $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
-        $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
-        // Use all configured logging options
-        foreach (explode(';', $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog'], 2) as $log) {
-            list($type, $destination, $level) = explode(',', $log, 4);
-            // Is message worth logging for this log type?
-            if ((int)$level > $severity) {
-                continue;
-            }
-            $msgLine = ' - ' . $extKey . ': ' . $msg;
-            // Write message to a file
-            if ($type == 'file') {
-                $file = fopen($destination, 'a');
-                if ($file) {
-                    fwrite($file, date(($dateFormat . ' ' . $timeFormat)) . $msgLine . LF);
-                    fclose($file);
-                    self::fixPermissions($destination);
-                }
-            } elseif ($type == 'mail') {
-                list($to, $from) = explode('/', $destination);
-                if (!self::validEmail($from)) {
-                    $from = MailUtility::getSystemFrom();
-                }
-                /** @var $mail \TYPO3\CMS\Core\Mail\MailMessage */
-                $mail = self::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
-                $mail->setTo($to)->setFrom($from)->setSubject('Warning - error in TYPO3 installation')->setBody('Host: ' . $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . LF . 'Extension: ' . $extKey . LF . 'Severity: ' . $severity . LF . LF . $msg);
-                $mail->send();
-            } elseif ($type == 'error_log') {
-                error_log($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . $msgLine, 0);
-            } elseif ($type == 'syslog') {
-                $priority = array(LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_CRIT);
-                syslog($priority[(int)$severity], $msgLine);
-            }
-        }
+
+        static::getLogger()->log(LogLevel::INFO - $severity, $msg, ['extension' => $extKey]);
     }
 
     /**
@@ -4356,19 +3820,20 @@ class GeneralUtility
      * This should be implemented around the source code, both frontend and backend, logging everything from the flow through an application, messages, results from comparisons to fatal errors.
      * The result is meant to make sense to developers during development or debugging of a site.
      * The idea is that this function is only a wrapper for external extensions which can set a hook which will be allowed to handle the logging of the information to any format they might wish and with any kind of filter they would like.
-     * If you want to implement the devLog in your applications, simply add lines like:
-     * if (TYPO3_DLOG) \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[write message in english here]', 'extension key');
+     * If you want to implement the devLog in your applications, simply add a line like:
+     * \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[write message in english here]', 'extension key');
      *
      * @param string $msg Message (in english).
      * @param string $extKey Extension key (from which extension you are calling the log)
      * @param int $severity Severity: 0 is info, 1 is notice, 2 is warning, 3 is fatal error, -1 is "OK" message
      * @param mixed $dataVar Additional data you want to pass to the logger.
-     * @return void
+     * @deprecated
      */
     public static function devLog($msg, $extKey, $severity = 0, $dataVar = false)
     {
+        trigger_error('Method devLog() is deprecated since v9 and will be removed with v10', E_USER_DEPRECATED);
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'])) {
-            $params = array('msg' => $msg, 'extKey' => $extKey, 'severity' => $severity, 'dataVar' => $dataVar);
+            $params = ['msg' => $msg, 'extKey' => $extKey, 'severity' => $severity, 'dataVar' => $dataVar];
             $fakeThis = false;
             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'] as $hookMethod) {
                 self::callUserFunction($hookMethod, $params, $fakeThis);
@@ -4380,62 +3845,75 @@ class GeneralUtility
      * Writes a message to the deprecation log.
      *
      * @param string $msg Message (in English).
-     * @return void
+     * @deprecated
      */
     public static function deprecationLog($msg)
     {
-        if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']) {
-            return;
-        }
-        // Legacy values (no strict comparison, $log can be boolean, string or int)
-        $log = $GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog'];
-        if ($log === true || $log == '1') {
-            $log = array('file');
-        } else {
-            $log = self::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog'], true);
-        }
-        $date = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ': ');
-        if (in_array('file', $log) !== false) {
-            // Write a longer message to the deprecation log
-            $destination = static::getDeprecationLogFileName();
-            $file = @fopen($destination, 'a');
-            if ($file) {
-                @fwrite($file, ($date . $msg . LF));
-                @fclose($file);
-                self::fixPermissions($destination);
-            }
-        }
-        if (in_array('devlog', $log) !== false) {
-            // Copy message also to the developer log
-            self::devLog($msg, 'Core', self::SYSLOG_SEVERITY_WARNING);
-        }
-        // Do not use console in login screen
-        if (in_array('console', $log) !== false && isset($GLOBALS['BE_USER']->user['uid'])) {
-            DebugUtility::debug($msg, $date, 'Deprecation Log');
-        }
+        static::writeDeprecationLogFileEntry(__METHOD__ . ' is deprecated since TYPO3 v9.0, will be removed in TYPO3 v10.0, use "trigger_error("Given reason", E_USER_DEPRECATED);" to log deprecations.');
+        trigger_error($msg, E_USER_DEPRECATED);
+    }
+
+    /**
+     * Logs the usage of a deprecated fluid ViewHelper argument.
+     * The log message will be generated automatically and contains the template path.
+     * With the third argument of this method it is possible to append some text to the log message.
+     *
+     * example usage:
+     *  if ($htmlEscape !== null) {
+     *      GeneralUtility::logDeprecatedViewHelperAttribute(
+     *          'htmlEscape',
+     *          $renderingContext,
+     *          'Please wrap the view helper in <f:format.raw> if you want to disable HTML escaping, which is enabled by default now.'
+     *      );
+     *  }
+     *
+     * The example above will create this deprecation log message:
+     * 15-02-17 23:12: [typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/HelpToolbarItemDropDown.html]
+     *   The property "htmlEscape" has been deprecated.
+     *   Please wrap the view helper in <f:format.raw> if you want to disable HTML escaping,
+     *   which is enabled by default now.
+     *
+     * @param string $property
+     * @param RenderingContextInterface $renderingContext
+     * @param string $additionalMessage
+     * @deprecated
+     */
+    public static function logDeprecatedViewHelperAttribute(string $property, RenderingContextInterface $renderingContext, string $additionalMessage = '')
+    {
+        static::writeDeprecationLogFileEntry(__METHOD__ . ' is deprecated since TYPO3 v9.0, will be removed in TYPO3 v10.0');
+        $template = $renderingContext->getTemplatePaths()->resolveTemplateFileForControllerAndActionAndFormat(
+            $renderingContext->getControllerName(),
+            $renderingContext->getControllerAction()
+        );
+        $template = str_replace(PATH_site, '', $template);
+        $message = [];
+        $message[] = '[' . $template . ']';
+        $message[] = 'The property "' . $property . '" has been marked as deprecated.';
+        $message[] = $additionalMessage;
+        $message[] = 'Please check also your partial and layout files of this template';
+        trigger_error(implode(' ', $message), E_USER_DEPRECATED);
     }
 
     /**
      * Gets the absolute path to the deprecation log file.
      *
      * @return string Absolute path to the deprecation log file
+     * @deprecated
      */
     public static function getDeprecationLogFileName()
     {
+        static::writeDeprecationLogFileEntry(__METHOD__ . ' is deprecated since TYPO3 v9.0, will be removed in TYPO3 v10.0');
         return PATH_typo3conf . 'deprecation_' . self::shortMD5((PATH_site . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) . '.log';
     }
 
     /**
      * Logs a call to a deprecated function.
      * The log message will be taken from the annotation.
-     *
-     * @return void
+     * @deprecated
      */
     public static function logDeprecatedFunction()
     {
-        if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']) {
-            return;
-        }
+        static::writeDeprecationLogFileEntry(__METHOD__ . ' is deprecated since TYPO3 v9.0, will be removed in TYPO3 v10.0');
         $trail = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
         if ($trail[1]['type']) {
             $function = new \ReflectionMethod($trail[1]['class'], $trail[1]['function']);
@@ -4446,11 +3924,11 @@ class GeneralUtility
         if (preg_match('/@deprecated\\s+(.*)/', $function->getDocComment(), $match)) {
             $msg = $match[1];
         }
-            // Write a longer message to the deprecation log: <function> <annotion> - <trace> (<source>)
+        // Write a longer message to the deprecation log: <function> <annotion> - <trace> (<source>)
         $logMsg = $trail[1]['class'] . $trail[1]['type'] . $trail[1]['function'];
         $logMsg .= '() - ' . $msg . ' - ' . DebugUtility::debugTrail();
         $logMsg .= ' (' . PathUtility::stripPathSitePrefix($function->getFileName()) . '#' . $function->getStartLine() . ')';
-        self::deprecationLog($logMsg);
+        trigger_error($logMsg, E_USER_DEPRECATED);
     }
 
     /**
@@ -4462,7 +3940,7 @@ class GeneralUtility
      * @param int $valueLength Long string values are shortened to this length. Default: 20
      * @return string Output string with key names and their value as string
      */
-    public static function arrayToLogString(array $arr, $valueList = array(), $valueLength = 20)
+    public static function arrayToLogString(array $arr, $valueList = [], $valueLength = 20)
     {
         $str = '';
         if (!is_array($valueList)) {
@@ -4478,25 +3956,8 @@ class GeneralUtility
     }
 
     /**
-     * Compile the command for running ImageMagick/GraphicsMagick.
-     *
-     * @param string $command Command to be run: identify, convert or combine/composite
-     * @param string $parameters The parameters string
-     * @param string $path Override the default path (e.g. used by the install tool)
-     * @return string Compiled command that deals with ImageMagick & GraphicsMagick
-     * @deprecated since TYPO3 CMS 8, will be removed in TYPO3 CMS 9. - use CommandUtility directly
-     */
-    public static function imageMagickCommand($command, $parameters, $path = '')
-    {
-        self::logDeprecatedFunction();
-        return CommandUtility::imageMagickCommand($command, $parameters, $path);
-    }
-
-    /**
      * Explode a string (normally a list of filenames) with whitespaces by considering quotes in that string.
      *
-     * This is mostly needed by the imageMagickCommand function above.
-     *
      * @param string $parameters The whole parameters string
      * @param bool $unQuote If set, the elements of the resulting array are unquoted.
      * @return array Exploded parameters
@@ -4540,8 +4001,8 @@ class GeneralUtility
     public static function quoteJSvalue($value)
     {
         return strtr(
-            json_encode((string)$value, JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_TAG),
-            array(
+            json_encode((string)$value, JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG),
+            [
                 '"' => '\'',
                 '\\\\' => '\\u005C',
                 ' ' => '\\u0020',
@@ -4549,47 +4010,18 @@ class GeneralUtility
                 '\\t' => '\\u0009',
                 '\\n' => '\\u000A',
                 '\\r' => '\\u000D'
-            )
+            ]
         );
     }
 
     /**
-     * Ends and flushes all output buffers
-     *
-     * @return void
-     * @deprecated since TYPO3 CMS 8, will be removed in TYPO3 CMS 9.
-     */
-    public static function flushOutputBuffers()
-    {
-        self::logDeprecatedFunction();
-        $obContent = '';
-        while ($content = ob_get_clean()) {
-            $obContent .= $content;
-        }
-        // If previously a "Content-Encoding: whatever" has been set, we have to unset it
-        if (!headers_sent()) {
-            $headersList = headers_list();
-            foreach ($headersList as $header) {
-                // Split it up at the :
-                list($key, $value) = self::trimExplode(':', $header, true);
-                // Check if we have a Content-Encoding other than 'None'
-                if (strtolower($key) === 'content-encoding' && strtolower($value) !== 'none') {
-                    header('Content-Encoding: None');
-                    break;
-                }
-            }
-        }
-        echo $obContent;
-    }
-
-    /**
      * Set the ApplicationContext
      *
      * This function is used by the Bootstrap to hand over the application context. It must not be used anywhere else,
      * because the context shall never be changed on runtime!
      *
      * @param \TYPO3\CMS\Core\Core\ApplicationContext $applicationContext
-     * @throws \RuntimeException if applicationContext is overriden
+     * @throws \RuntimeException if applicationContext is overridden
      * @internal This is not a public API method, do not use in own extensions
      */
     public static function presetApplicationContext(ApplicationContext $applicationContext)
@@ -4619,4 +4051,29 @@ class GeneralUtility
     {
         return in_array(PHP_SAPI, self::$supportedCgiServerApis, true);
     }
+
+    /**
+     * @return LoggerInterface
+     */
+    protected static function getLogger()
+    {
+        return static::makeInstance(LogManager::class)->getLogger(__CLASS__);
+    }
+
+    /**
+     * @param string $msg
+     * @deprecated
+     */
+    private static function writeDeprecationLogFileEntry($msg)
+    {
+        $date = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ': ');
+        // Write a longer message to the deprecation log
+        $destination = PATH_typo3conf . 'deprecation_' . self::shortMD5(PATH_site . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) . '.log';
+        $file = @fopen($destination, 'a');
+        if ($file) {
+            @fwrite($file, $date . $msg . LF);
+            @fclose($file);
+            self::fixPermissions($destination);
+        }
+    }
 }