Commit 0e654ec7 authored by Benni Mack's avatar Benni Mack Committed by Wouter Wolters
Browse files

[TASK] Deprecate 2nd argument of GeneralUtility::explodeUrl2Array

Calling `GeneralUtility::explodeUrl2Array` with a second
parameter "true" can be simplified by using PHP's
native parse_str() method directly.

The second parameter is then deprecated.

All occurrences are replaced with "parse_str()" where
the second parameter was set to true.

Resolves: #85801
Releases: master
Change-Id: Ifd590bc17626cb93495f3f43935671e3f2296c7b
Reviewed-on: https://review.typo3.org/57770


Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
parent 2c26eaff
......@@ -194,7 +194,8 @@ class ShortcutRepository
}
$queryParts = parse_url($url);
$queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], true);
$queryParameters = [];
parse_str($queryParts['query'], $queryParameters);
if (!empty($queryParameters['scheme'])) {
throw new \RuntimeException('Shortcut URLs must be relative', 1518785877);
......@@ -484,7 +485,9 @@ class ShortcutRepository
list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
$queryParts = parse_url($row['url']);
$queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
// Explode GET vars recursively
$queryParameters = [];
parse_str($queryParts['query'], $queryParameters);
if ($row['module_name'] === 'xMOD_alt_doc.php' && is_array($queryParameters['edit'])) {
$shortcut['table'] = key($queryParameters['edit']);
......@@ -725,12 +728,14 @@ class ShortcutRepository
protected function getTokenUrl(string $url): string
{
$parsedUrl = parse_url($url);
$parameters = [];
parse_str($parsedUrl['query'], $parameters);
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
// parse the returnUrl and replace the module token of it
if (isset($parameters['returnUrl'])) {
$parsedReturnUrl = parse_url($parameters['returnUrl']);
$returnUrlParameters = [];
parse_str($parsedReturnUrl['query'], $returnUrlParameters);
if (strpos($parsedReturnUrl['path'], 'index.php') !== false && !empty($returnUrlParameters['route'])) {
......
......@@ -589,7 +589,8 @@ class NewContentElementController
// Exploding parameter string, if any (old style)
if ($wizardItems[$key]['params']) {
// Explode GET vars recursively
$tempGetVars = GeneralUtility::explodeUrl2Array($wizardItems[$key]['params'], true);
$tempGetVars = [];
parse_str($wizardItems[$key]['params'], $tempGetVars);
// If tt_content values are set, merge them into the tt_content_defValues array,
// unset them from $tempGetVars and re-implode $tempGetVars into the param string
// (in case remaining parameters are around).
......
......@@ -2644,9 +2644,10 @@ class BackendUtility
try {
$site = $siteFinder->getSiteByPageId((int)$pageUid, $rootLine);
// Create a multi-dimensional array out of the additional get vars
$additionalGetVars = GeneralUtility::explodeUrl2Array($additionalGetVars, true);
$additionalQueryParams = [];
parse_str($additionalGetVars, $additionalQueryParams);
$uriBuilder = GeneralUtility::makeInstance(PageUriBuilder::class);
$previewUrl = (string)$uriBuilder->buildUri($pageUid, $additionalGetVars, $anchorSection, ['rootLine' => $rootLine], $uriBuilder::ABSOLUTE_URL);
$previewUrl = (string)$uriBuilder->buildUri($pageUid, $additionalQueryParams, $anchorSection, ['rootLine' => $rootLine], $uriBuilder::ABSOLUTE_URL);
} catch (SiteNotFoundException $e) {
$previewUrl = self::createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript);
}
......
......@@ -1169,19 +1169,31 @@ class GeneralUtility
}
/**
* Explodes a string with GETvars (eg. "&id=1&type=2&ext[mykey]=3") into an array
* Explodes a string with GETvars (eg. "&id=1&type=2&ext[mykey]=3") into an array.
*
* Note! If you want to use a multi-dimensional string, consider this plain simple PHP code instead:
*
* $result = [];
* parse_str($queryParametersAsString, $result);
*
* However, if you do magic with a flat structure (e.g. keeping "ext[mykey]" as flat key in a one-dimensional array)
* then this method is for you.
*
* @param string $string GETvars string
* @param bool $multidim If set, the string will be parsed into a multidimensional array if square brackets are used in variable names (using PHP function parse_str())
* @return array Array of values. All values AND keys are rawurldecoded() as they properly should be. But this means that any implosion of the array again must rawurlencode it!
* @see implodeArrayForUrl()
*/
public static function explodeUrl2Array($string, $multidim = false)
public static function explodeUrl2Array($string, $multidim = null)
{
$output = [];
if ($multidim) {
trigger_error('GeneralUtility::explodeUrl2Array() with a multi-dimensional explode functionality will be removed in TYPO3 v10.0. is built-in PHP with "parse_str($input, $output);". Use the native PHP methods instead.', E_USER_DEPRECATED);
parse_str($string, $output);
} else {
if ($multidim !== null) {
trigger_error('GeneralUtility::explodeUrl2Array() does not need a second method argument anymore, and will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
}
$p = explode('&', $string);
foreach ($p as $v) {
if ($v !== '') {
......
.. include:: ../../Includes.txt
============================================================================
Deprecation: #85801 - GeneralUtility::explodeUrl2Array - 2nd method argument
============================================================================
See :issue:`85801`
Description
===========
The second argument in :php:`TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array()` has been deprecated.
Setting this (optional) argument to :php:`true` calls the native PHP function :php:`parse_str()`, which
should be used instead directly.
Impact
======
Calling the method with an explicitly set second argument will trigger a deprecation message.
Affected Installations
======================
Any TYPO3 installation with a custom extension calling the method above with a second method argument.
Migration
=========
If the second argument was set to :php:`true` before, use the native PHP function :php:`parse_str()`, if the
second parameter was set to :php:`false` before, just remove the second argument.
.. index:: PHP-API, FullyScanned, ext:core
\ No newline at end of file
......@@ -1027,8 +1027,7 @@ class GeneralUtilityTest extends UnitTestCase
// Tests concerning implodeArrayForUrl / explodeUrl2Array
//////////////////////////////////
/**
* Data provider for implodeArrayForUrlBuildsValidParameterString and
* explodeUrl2ArrayTransformsParameterStringToArray
* Data provider for implodeArrayForUrlBuildsValidParameterString
*
* @return array
*/
......@@ -1072,23 +1071,13 @@ class GeneralUtilityTest extends UnitTestCase
$this->assertSame($expected, GeneralUtility::implodeArrayForUrl('foo', $input, '', false, true));
}
/**
* @test
* @dataProvider implodeArrayForUrlDataProvider
*/
public function explodeUrl2ArrayTransformsParameterStringToNestedArray($name, $array, $input)
{
$expected = $array ? [$name => $array] : [];
$this->assertEquals($expected, GeneralUtility::explodeUrl2Array($input, true));
}
/**
* @test
* @dataProvider explodeUrl2ArrayDataProvider
*/
public function explodeUrl2ArrayTransformsParameterStringToFlatArray($input, $expected)
{
$this->assertEquals($expected, GeneralUtility::explodeUrl2Array($input, false));
$this->assertEquals($expected, GeneralUtility::explodeUrl2Array($input));
}
/**
......
......@@ -246,4 +246,28 @@ class GeneralUtilityTest extends UnitTestCase
$this->assertEquals($expectedQuoted, $actualQuoted, 'The exploded command does not match the expected');
$this->assertEquals($expectedUnquoted, $actualUnquoted, 'The exploded and unquoted command does not match the expected');
}
/**
* Data provider for explodeUrl2ArrayTransformsParameterStringToNestedArray
*
* @return array
*/
public function explodeUrl2ArrayDataProvider()
{
return [
'Empty input' => [[], ''],
'String parameters' => [['foo' => ['one' => '√', 'two' => 2]], '&foo[one]=%E2%88%9A&foo[two]=2'],
'Nested array parameters' => [['foo' => [['one' => '√', 'two' => 2]]], '&foo[0][one]=%E2%88%9A&foo[0][two]=2'],
'Keep blank parameters' => [['foo' => ['one' => '√', '']], '&foo[one]=%E2%88%9A&foo[0]=']
];
}
/**
* @test
* @dataProvider explodeUrl2ArrayDataProvider
*/
public function explodeUrl2ArrayTransformsParameterStringToNestedArray($expected, $input)
{
$this->assertEquals($expected, GeneralUtility::explodeUrl2Array($input, true));
}
}
......@@ -655,14 +655,16 @@ class UriBuilder
$arguments = array_replace_recursive(GeneralUtility::_POST(), GeneralUtility::_GET());
break;
default:
$arguments = GeneralUtility::explodeUrl2Array(GeneralUtility::getIndpEnv('QUERY_STRING'), true);
// Explode GET vars recursively
parse_str(GeneralUtility::getIndpEnv('QUERY_STRING'), $arguments);
}
} else {
$arguments = GeneralUtility::_GET();
}
foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) {
$argumentToBeExcluded = GeneralUtility::explodeUrl2Array($argumentToBeExcluded, true);
$arguments = ArrayUtility::arrayDiffAssocRecursive($arguments, $argumentToBeExcluded);
$argumentArrayToBeExcluded = [];
parse_str($argumentToBeExcluded, $argumentArrayToBeExcluded);
$arguments = ArrayUtility::arrayDiffAssocRecursive($arguments, $argumentArrayToBeExcluded);
}
} else {
$id = GeneralUtility::_GP('id');
......
......@@ -939,8 +939,9 @@ class FrontendLoginController extends AbstractPlugin implements LoggerAwareInter
if ($this->conf['preserveGETvars'] === 'all') {
$preserveQueryParts = $getVars;
} else {
$preserveQueryParts = GeneralUtility::trimExplode(',', $this->conf['preserveGETvars']);
$preserveQueryParts = GeneralUtility::explodeUrl2Array(implode('=1&', $preserveQueryParts) . '=1', true);
$preserveQueryStringProperties = GeneralUtility::trimExplode(',', $this->conf['preserveGETvars']);
$preserveQueryParts = [];
parse_str(implode('=1&', $preserveQueryStringProperties) . '=1', $preserveQueryParts);
$preserveQueryParts = \TYPO3\CMS\Core\Utility\ArrayUtility::intersectRecursive($getVars, $preserveQueryParts);
}
$parameters = GeneralUtility::implodeArrayForUrl('', $preserveQueryParts);
......
......@@ -5738,14 +5738,16 @@ class ContentObjectRenderer implements LoggerAwareInterface
ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_GET());
break;
default:
$currentQueryArray = GeneralUtility::explodeUrl2Array($this->getEnvironmentVariable('QUERY_STRING'), true);
$currentQueryArray = [];
parse_str($this->getEnvironmentVariable('QUERY_STRING'), $currentQueryArray);
}
if ($conf['exclude']) {
$exclude = str_replace(',', '&', $conf['exclude']);
$exclude = GeneralUtility::explodeUrl2Array($exclude, true);
$excludeString = str_replace(',', '&', $conf['exclude']);
$excludedQueryParts = [];
parse_str($excludeString, $excludedQueryParts);
// never repeat id
$exclude['id'] = 0;
$newQueryArray = ArrayUtility::arrayDiffAssocRecursive($currentQueryArray, $exclude);
$newQueryArray = ArrayUtility::arrayDiffAssocRecursive($currentQueryArray, $excludedQueryParts);
} else {
$newQueryArray = $currentQueryArray;
}
......
......@@ -230,7 +230,8 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
&& !trim($addQueryParams)
&& (empty($conf['addQueryString']) || !isset($conf['addQueryString.']))
) {
$currentQueryArray = GeneralUtility::explodeUrl2Array(GeneralUtility::getIndpEnv('QUERY_STRING'), true);
$currentQueryArray = [];
parse_str(GeneralUtility::getIndpEnv('QUERY_STRING'), $currentQueryArray);
$currentQueryParams = GeneralUtility::implodeArrayForUrl('', $currentQueryArray, '', false, true);
if (!trim($currentQueryParams)) {
......
......@@ -39,4 +39,10 @@ return [
'Deprecation-82899-ExtensionManagementUtilityMethods.rst',
],
],
'TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array' => [
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-85801-GeneralUtilityexplodeUrl2Array-2ndMethodArgument.rst',
],
],
];
......@@ -180,7 +180,8 @@ class RedirectService implements LoggerAwareInterface
// New query parameters overrule the ones that should be kept
$newQueryParamString = $url->getQuery();
if (!empty($newQueryParamString)) {
$newQueryParams = GeneralUtility::explodeUrl2Array($newQueryParamString, true);
$newQueryParams = [];
parse_str($newQueryParamString, $newQueryParams);
$queryParams = array_replace_recursive($queryParams, $newQueryParams);
}
$query = http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment