From ad01e430bc2ba519312e3bfdd82d3dafd5002023 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Tue, 7 Apr 2020 11:16:52 +0200 Subject: [PATCH] [TASK] Deprecate various GeneralUtility methods Some methods in GeneralUtility nowadays are wrappers to native PHP methods. We encourage people to use the PHP API directly. * GeneralUtility::IPv6Hex2Bin() * GeneralUtility::IPv6Bin2Hex() * GeneralUtility::compressIPv6() * GeneralUtility::milliseconds() In addition, these methods are unused by Core * GeneralUtility::linkThisUrl() * GeneralUtility::flushDirectory() Reasoning: In order to make our code less coupled, TYPO3 Core should use native PHP where it makes sense, instead of relying on GeneralUtility in all places. Resolves: #91001 Releases: master Change-Id: I9e3a2f4a4bb42facad2d79f959b36482dba23ec8 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64091 Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Alexander Schnitzler <git@alexanderschnitzler.de> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Alexander Schnitzler <git@alexanderschnitzler.de> Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> --- .../Cache/Backend/SimpleFileBackend.php | 18 +++- .../core/Classes/Utility/GeneralUtility.php | 19 ++-- ...001-VariousMethodsWithinGeneralUtility.rst | 57 ++++++++++++ .../Tests/Unit/Utility/GeneralUtilityTest.php | 77 ---------------- .../Utility/GeneralUtilityTest.php | 88 +++++++++++++++++++ .../Classes/Controller/SearchController.php | 7 +- .../sysext/indexed_search/Classes/Indexer.php | 4 +- .../Classes/Utility/IndexedSearchUtility.php | 10 +++ .../Php/MethodCallStaticMatcher.php | 42 +++++++++ 9 files changed, 234 insertions(+), 88 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-91001-VariousMethodsWithinGeneralUtility.rst diff --git a/typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php b/typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php index d2961ff88145..83e30181d38a 100644 --- a/typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php +++ b/typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php @@ -297,10 +297,26 @@ class SimpleFileBackend extends AbstractBackend implements PhpCapableBackendInte /** * Removes all cache entries of this cache. + * Flushes a directory by first moving to a temporary resource, and then + * triggering the remove process. This way directories can be flushed faster + * to prevent race conditions on concurrent processes accessing the same directory. */ public function flush() { - GeneralUtility::flushDirectory($this->cacheDirectory, true); + $directory = $this->cacheDirectory; + if (is_link($directory)) { + // Avoid attempting to rename the symlink see #87367 + $directory = realpath($directory); + } + + if (is_dir($directory)) { + $temporaryDirectory = rtrim($directory, '/') . '.' . StringUtility::getUniqueId('remove'); + if (rename($directory, $temporaryDirectory)) { + GeneralUtility::mkdir($directory); + clearstatcache(); + GeneralUtility::rmdir($temporaryDirectory, true); + } + } } /** diff --git a/typo3/sysext/core/Classes/Utility/GeneralUtility.php b/typo3/sysext/core/Classes/Utility/GeneralUtility.php index 9c6f0c1c1117..468bb9c6aa24 100644 --- a/typo3/sysext/core/Classes/Utility/GeneralUtility.php +++ b/typo3/sysext/core/Classes/Utility/GeneralUtility.php @@ -314,8 +314,8 @@ class GeneralUtility } elseif ($maskInt == 128) { $success = $test === $baseIP; } else { - $testBin = self::IPv6Hex2Bin($test); - $baseIPBin = self::IPv6Hex2Bin($baseIP); + $testBin = inet_pton($test); + $baseIPBin = inet_pton($baseIP); $success = true; // Modulo is 0 if this is a 8-bit-boundary $maskIntModulo = $maskInt % 8; @@ -344,10 +344,11 @@ class GeneralUtility * * @param string $hex IPv6 address in hex-presentation * @return string Binary representation (16 characters, 128 characters) - * @see IPv6Bin2Hex() + * @deprecated - will be removed in TYPO3 v11.0. Use the native PHP function inet_pton($hex) instead. */ public static function IPv6Hex2Bin($hex) { + trigger_error('GeneralUtility::IPv6Hex2Bin() will be removed in TYPO3 v11.0. Use the native PHP function inet_pton($hex) instead.', E_USER_DEPRECATED); return inet_pton($hex); } @@ -356,10 +357,11 @@ class GeneralUtility * * @param string $bin IPv6 address in hex-presentation * @return string Binary representation (16 characters, 128 characters) - * @see IPv6Hex2Bin() + * @deprecated - will be removed in TYPO3 v11.0. Use the native PHP function inet_ntop($bin) instead. */ public static function IPv6Bin2Hex($bin) { + trigger_error('GeneralUtility::IPv6Bin2Hex() will be removed in TYPO3 v11.0. Use the native PHP function inet_ntop($bin) instead.', E_USER_DEPRECATED); return inet_ntop($bin); } @@ -368,7 +370,6 @@ class GeneralUtility * * @param string $address Given IPv6 address * @return string Normalized address - * @see compressIPv6() */ public static function normalizeIPv6($address) { @@ -432,9 +433,11 @@ class GeneralUtility * @param string $address Given IPv6 address * @return string Compressed address * @see normalizeIPv6() + * @deprecated will be removed in TYPO3 v11.0. Use the native PHP functions inet_ntop(inet_pton($address)) instead. */ public static function compressIPv6($address) { + trigger_error('GeneralUtility::compressIPv6() will be removed in TYPO3 v11.0. Use the native PHP functions inet_ntop(inet_pton($address)) instead.', E_USER_DEPRECATED); return inet_ntop(inet_pton($address)); } @@ -2104,9 +2107,11 @@ class GeneralUtility * @param bool $keepOriginalDirectory Whether to only empty the directory and not remove it * @param bool $flushOpcodeCache Also flush the opcode cache right after renaming the directory. * @return bool Whether the action was successful + * @deprecated will be removed in TYPO3 v11.0. This is a specific logic needed for the caching framework, and should be implemented where needed directly. */ public static function flushDirectory($directory, $keepOriginalDirectory = false, $flushOpcodeCache = false) { + trigger_error('GeneralUtility::flushDirectory() will be removed in TYPO3 v11.0. This is a specific logic needed for the caching framework, and should be implemented where needed directly.', E_USER_DEPRECATED); $result = false; if (is_link($directory)) { @@ -2511,9 +2516,11 @@ class GeneralUtility * @param string $url URL string * @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. + * @deprecated will be removed in TYPO3 v11.0. Use PSR-7 URI objects instead. */ public static function linkThisUrl($url, array $getParams = []) { + trigger_error('GeneralUtility::linkThisUrl() will be removed in TYPO3 v11.0. Use PSR-7 URI objects instead.', E_USER_DEPRECATED); $parts = parse_url($url); $getP = []; if ($parts['query']) { @@ -2916,9 +2923,11 @@ class GeneralUtility * Gets the unixtime as milliseconds. * * @return int The unixtime as milliseconds + * @deprecated will be removed in TYPO3 v11.0. Use the native PHP functions round(microtime(true) * 1000) instead. */ public static function milliseconds() { + trigger_error('GeneralUtility::milliseconds() will be removed in TYPO3 v11.0. Use the native PHP functions round(microtime(true) * 1000) instead.', E_USER_DEPRECATED); return round(microtime(true) * 1000); } diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91001-VariousMethodsWithinGeneralUtility.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91001-VariousMethodsWithinGeneralUtility.rst new file mode 100644 index 000000000000..8dc4601937b6 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91001-VariousMethodsWithinGeneralUtility.rst @@ -0,0 +1,57 @@ +.. include:: ../../Includes.txt + +=========================================================== +Deprecation: #91001 - Various methods within GeneralUtility +=========================================================== + +See :issue:`91001` + +Description +=========== + +The following methods within GeneralUtility have been marked as deprecated, +as the native PHP methods can be used directly: + +* :php:`GeneralUtility::IPv6Hex2Bin()` +* :php:`GeneralUtility::IPv6Bin2Hex()` +* :php:`GeneralUtility::compressIPv6()` +* :php:`GeneralUtility::milliseconds()` + +In addition, these methods are unused by Core and marked as deprecated as well: + +* :php:`GeneralUtility::linkThisUrl()` +* :php:`GeneralUtility::flushDirectory()` + + +Impact +====== + +Calling any methods directly from PHP will trigger a PHP deprecation notice. + + +Affected Installations +====================== + +TYPO3 installations with third-party extensions using any of these methods. + + +Migration +========= + +As the following methods are just wrappers around native PHP methods, it is +recommended to switch to native PHP to speed up performance: + +* :php:`GeneralUtility::IPv6Hex2Bin($hex)`: :php:`inet_pton($hex)` +* :php:`GeneralUtility::IPv6Bin2Hex($bin)`: :php:`inet_ntop($bin)` +* :php:`GeneralUtility::compressIPv6($address)`: :php:`inet_ntop(inet_pton($address))` +* :php:`GeneralUtility::milliseconds()`: :php:`round(microtime(true) * 1000)` + +As for :php:`GeneralUtility::linkThisUrl()` it is recommended to migrate to +PSR-7 (UriInterface). + +The method :php:`GeneralUtility::flushDirectory()` uses a clearing +folder structure which is only used for caching to avoid race-conditioning. It +is recommended to use :php:`GeneralUtility::rmdir()` or implement the code +directly in the third-party extension. + +.. index:: PHP-API, FullyScanned, ext:core diff --git a/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php b/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php index cc2d97f5c72c..421ba277a502 100644 --- a/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php +++ b/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php @@ -346,63 +346,6 @@ class GeneralUtilityTest extends UnitTestCase self::assertFalse(GeneralUtility::cmpIPv6($ip, $list)); } - /////////////////////////////// - // Tests concerning IPv6Hex2Bin - /////////////////////////////// - /** - * Data provider for IPv6Hex2BinCorrect - * - * @return array Data sets - */ - public static function IPv6Hex2BinDataProviderCorrect() - { - return [ - 'empty 1' => ['::', str_pad('', 16, "\x00")], - 'empty 2, already normalized' => ['0000:0000:0000:0000:0000:0000:0000:0000', str_pad('', 16, "\x00")], - 'already normalized' => ['0102:0304:0000:0000:0000:0000:0506:0078', "\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78"], - 'expansion in middle 1' => ['1::2', "\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02"], - 'expansion in middle 2' => ['beef::fefa', "\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa"], - ]; - } - - /** - * @test - * @dataProvider IPv6Hex2BinDataProviderCorrect - */ - public function IPv6Hex2BinCorrectlyConvertsAddresses($hex, $binary) - { - self::assertTrue(GeneralUtility::IPv6Hex2Bin($hex) === $binary); - } - - /////////////////////////////// - // Tests concerning IPv6Bin2Hex - /////////////////////////////// - /** - * Data provider for IPv6Bin2HexCorrect - * - * @return array Data sets - */ - public static function IPv6Bin2HexDataProviderCorrect() - { - return [ - 'empty' => [str_pad('', 16, "\x00"), '::'], - 'non-empty front' => ["\x01" . str_pad('', 15, "\x00"), '100::'], - 'non-empty back' => [str_pad('', 15, "\x00") . "\x01", '::1'], - 'normalized' => ["\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78", '102:304::506:78'], - 'expansion in middle 1' => ["\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02", '1::2'], - 'expansion in middle 2' => ["\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa", 'beef::fefa'], - ]; - } - - /** - * @test - * @dataProvider IPv6Bin2HexDataProviderCorrect - */ - public function IPv6Bin2HexCorrectlyConvertsAddresses($binary, $hex) - { - self::assertEquals(GeneralUtility::IPv6Bin2Hex($binary), $hex); - } - //////////////////////////////////////////////// // Tests concerning normalizeIPv6 / compressIPv6 //////////////////////////////////////////////// @@ -432,26 +375,6 @@ class GeneralUtilityTest extends UnitTestCase self::assertEquals($normalized, GeneralUtility::normalizeIPv6($compressed)); } - /** - * @test - * @dataProvider normalizeCompressIPv6DataProviderCorrect - */ - public function compressIPv6CorrectlyCompressesAddresses($compressed, $normalized) - { - self::assertEquals($compressed, GeneralUtility::compressIPv6($normalized)); - } - - /** - * @test - */ - public function compressIPv6CorrectlyCompressesAddressWithSomeAddressOnRightSide() - { - if (strtolower(PHP_OS) === 'darwin') { - self::markTestSkipped('This test does not work on OSX / Darwin OS.'); - } - self::assertEquals('::f0f', GeneralUtility::compressIPv6('0000:0000:0000:0000:0000:0000:0000:0f0f')); - } - /////////////////////////////// // Tests concerning validIP /////////////////////////////// diff --git a/typo3/sysext/core/Tests/UnitDeprecated/Utility/GeneralUtilityTest.php b/typo3/sysext/core/Tests/UnitDeprecated/Utility/GeneralUtilityTest.php index 0ea1a5133b80..cf0d101680b3 100644 --- a/typo3/sysext/core/Tests/UnitDeprecated/Utility/GeneralUtilityTest.php +++ b/typo3/sysext/core/Tests/UnitDeprecated/Utility/GeneralUtilityTest.php @@ -251,4 +251,92 @@ class GeneralUtilityTest extends UnitTestCase $requestFactory->request(Argument::any(), Argument::any(), ['headers' => $expectedHeaders])->shouldHaveBeenCalled(); } + + /** + * Data provider for IPv6Hex2BinCorrect + * + * @return array Data sets + */ + public static function IPv6Hex2BinDataProviderCorrect() + { + return [ + 'empty 1' => ['::', str_pad('', 16, "\x00")], + 'empty 2, already normalized' => ['0000:0000:0000:0000:0000:0000:0000:0000', str_pad('', 16, "\x00")], + 'already normalized' => ['0102:0304:0000:0000:0000:0000:0506:0078', "\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78"], + 'expansion in middle 1' => ['1::2', "\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02"], + 'expansion in middle 2' => ['beef::fefa', "\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa"], + ]; + } + + /** + * @test + * @dataProvider IPv6Hex2BinDataProviderCorrect + */ + public function IPv6Hex2BinCorrectlyConvertsAddresses($hex, $binary) + { + self::assertTrue(GeneralUtility::IPv6Hex2Bin($hex) === $binary); + } + + /** + * Data provider for IPv6Bin2HexCorrect + * + * @return array Data sets + */ + public static function IPv6Bin2HexDataProviderCorrect() + { + return [ + 'empty' => [str_pad('', 16, "\x00"), '::'], + 'non-empty front' => ["\x01" . str_pad('', 15, "\x00"), '100::'], + 'non-empty back' => [str_pad('', 15, "\x00") . "\x01", '::1'], + 'normalized' => ["\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78", '102:304::506:78'], + 'expansion in middle 1' => ["\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02", '1::2'], + 'expansion in middle 2' => ["\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa", 'beef::fefa'], + ]; + } + + /** + * @test + * @dataProvider IPv6Bin2HexDataProviderCorrect + */ + public function IPv6Bin2HexCorrectlyConvertsAddresses($binary, $hex) + { + self::assertEquals(GeneralUtility::IPv6Bin2Hex($binary), $hex); + } + + /** + * Data provider for normalizeIPv6ReturnsCorrectlyNormalizedFormat + * + * @return array Data sets + */ + public static function normalizeCompressIPv6DataProviderCorrect() + { + return [ + 'empty' => ['::', '0000:0000:0000:0000:0000:0000:0000:0000'], + 'localhost' => ['::1', '0000:0000:0000:0000:0000:0000:0000:0001'], + 'expansion in middle 1' => ['1::2', '0001:0000:0000:0000:0000:0000:0000:0002'], + 'expansion in middle 2' => ['1:2::3', '0001:0002:0000:0000:0000:0000:0000:0003'], + 'expansion in middle 3' => ['1::2:3', '0001:0000:0000:0000:0000:0000:0002:0003'], + 'expansion in middle 4' => ['1:2::3:4:5', '0001:0002:0000:0000:0000:0003:0004:0005'] + ]; + } + + /** + * @test + * @dataProvider normalizeCompressIPv6DataProviderCorrect + */ + public function compressIPv6CorrectlyCompressesAddresses($compressed, $normalized) + { + self::assertEquals($compressed, GeneralUtility::compressIPv6($normalized)); + } + + /** + * @test + */ + public function compressIPv6CorrectlyCompressesAddressWithSomeAddressOnRightSide() + { + if (strtolower(PHP_OS) === 'darwin') { + self::markTestSkipped('This test does not work on OSX / Darwin OS.'); + } + self::assertEquals('::f0f', GeneralUtility::compressIPv6('0000:0000:0000:0000:0000:0000:0000:0f0f')); + } } diff --git a/typo3/sysext/indexed_search/Classes/Controller/SearchController.php b/typo3/sysext/indexed_search/Classes/Controller/SearchController.php index cb9c216c855a..85d856b5eadf 100644 --- a/typo3/sysext/indexed_search/Classes/Controller/SearchController.php +++ b/typo3/sysext/indexed_search/Classes/Controller/SearchController.php @@ -33,6 +33,7 @@ use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Core\Utility\RootlineUtility; use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; +use TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility; /** * Index search frontend @@ -276,20 +277,20 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle $resultsets = []; foreach ($indexCfgs as $freeIndexUid) { // Get result rows - $tstamp1 = GeneralUtility::milliseconds(); + $tstamp1 = IndexedSearchUtility::milliseconds(); if ($hookObj = $this->hookRequest('getResultRows')) { $resultData = $hookObj->getResultRows($this->searchWords, $freeIndexUid); } else { $resultData = $this->searchRepository->doSearch($this->searchWords, $freeIndexUid); } // Display search results - $tstamp2 = GeneralUtility::milliseconds(); + $tstamp2 = IndexedSearchUtility::milliseconds(); if ($hookObj = $this->hookRequest('getDisplayResults')) { $resultsets[$freeIndexUid] = $hookObj->getDisplayResults($this->searchWords, $resultData, $freeIndexUid); } else { $resultsets[$freeIndexUid] = $this->getDisplayResults($this->searchWords, $resultData, $freeIndexUid); } - $tstamp3 = GeneralUtility::milliseconds(); + $tstamp3 = IndexedSearchUtility::milliseconds(); // Create header if we are searching more than one indexing configuration if (count($indexCfgs) > 1) { if ($freeIndexUid > 0) { diff --git a/typo3/sysext/indexed_search/Classes/Indexer.php b/typo3/sysext/indexed_search/Classes/Indexer.php index cd9734188d78..8a55198d8f00 100644 --- a/typo3/sysext/indexed_search/Classes/Indexer.php +++ b/typo3/sysext/indexed_search/Classes/Indexer.php @@ -347,7 +347,7 @@ class Indexer } $this->log_pull(); // Set parsetime - $this->updateParsetime($this->hash['phash'], GeneralUtility::milliseconds() - $Pstart); + $this->updateParsetime($this->hash['phash'], IndexedSearchUtility::milliseconds() - $Pstart); // Checking external files if configured for. $this->log_push('Checking external files', ''); if ($this->conf['index_externals']) { @@ -926,7 +926,7 @@ class Indexer } $this->log_pull(); // Set parsetime - $this->updateParsetime($phash_arr['phash'], GeneralUtility::milliseconds() - $Pstart); + $this->updateParsetime($phash_arr['phash'], IndexedSearchUtility::milliseconds() - $Pstart); } else { // Update the timestamp $this->updateTstamp($phash_arr['phash'], $fileInfo['mtime']); diff --git a/typo3/sysext/indexed_search/Classes/Utility/IndexedSearchUtility.php b/typo3/sysext/indexed_search/Classes/Utility/IndexedSearchUtility.php index a4fef6f0d938..b2f0f50cef8a 100644 --- a/typo3/sysext/indexed_search/Classes/Utility/IndexedSearchUtility.php +++ b/typo3/sysext/indexed_search/Classes/Utility/IndexedSearchUtility.php @@ -163,4 +163,14 @@ class IndexedSearchUtility return null; } + + /** + * Gets the unixtime as milliseconds. + * + * @return int The unixtime as milliseconds + */ + public static function milliseconds() + { + return round(microtime(true) * 1000); + } } diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php index e0384608f01e..f0d13615982d 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php @@ -980,4 +980,46 @@ return [ 'Deprecation-90147-UnifiedFileNameValidator.rst' ], ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::IPv6Hex2Bin' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::IPv6Bin2Hex' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::compressIPv6' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::linkThisUrl' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 2, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], + 'TYPO3\CMS\Core\Utility\GeneralUtility::flushDirectory' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 3, + 'restFiles' => [ + 'Deprecation-91001-VariousMethodsWithinGeneralUtility.rst' + ], + ], ]; -- GitLab