From 656fac87105d1282c4c6ea2c36389361b0e326e3 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Fri, 23 Sep 2022 17:27:17 +0200 Subject: [PATCH] [!!!][FEATURE] Use Routing for getQueryArguments / addQueryString With Typolink (and the typolink ViewHelpers), a new option is now available to allow to add ALL current queryParameters to the created URL when creating frontend links. 10 = TEXT 10.typolink.parameter = 12 10.typolink.addQueryString = untrusted addQueryString now allows to be set to "0" (do not do anything), or "1"/"true" or "untrusted" (new) which then makes it possible to add only "safe" query parameters which have been matched during the routing process. The breaking change here is that "addQueryString = 1" does - by default - only include the mapped query arguments from the Page Routing, avoiding unneeded GET parameters to be added by default. The affected method has been moved from ContentObjectRenderer to PageLinkBuilder now. Resolves: #98488 Releases: main Change-Id: I243cea29abc0903b59721cd31e9c380a0558bc9b Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75864 Tested-by: Oliver Hader <oliver.hader@typo3.org> Tested-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Oliver Hader <oliver.hader@typo3.org> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> --- ...ringOnlyIncludesResolvedQueryArguments.rst | 49 ++++++++++++ ...ontentObjectRenderer-getQueryArguments.rst | 36 +++++++++ ...SettingForTypolinkOptionAddQueryString.rst | 26 +++++++ .../ViewHelpers/Link/TypolinkViewHelper.php | 4 +- .../ViewHelpers/Uri/TypolinkViewHelper.php | 4 +- .../Link/TypolinkViewHelperTest.php | 16 ++-- .../Uri/TypolinkViewHelperTest.php | 16 ++-- .../ContentObject/ContentObjectRenderer.php | 2 + .../TypoScriptFrontendController.php | 2 +- .../Classes/Typolink/PageLinkBuilder.php | 41 +++++++++- .../ContentObjectRendererTest.php | 44 ----------- .../Unit/Typolink/PageLinkBuilderTest.php | 76 +++++++++++++++++++ .../Php/MethodCallMatcher.php | 7 ++ 13 files changed, 257 insertions(+), 66 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98488-TypolinkOptionAddQueryStringOnlyIncludesResolvedQueryArguments.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/12.0/Deprecation-98488-ContentObjectRenderer-getQueryArguments.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/12.0/Feature-98488-AdditionalSettingForTypolinkOptionAddQueryString.rst create mode 100644 typo3/sysext/frontend/Tests/Unit/Typolink/PageLinkBuilderTest.php diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98488-TypolinkOptionAddQueryStringOnlyIncludesResolvedQueryArguments.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98488-TypolinkOptionAddQueryStringOnlyIncludesResolvedQueryArguments.rst new file mode 100644 index 000000000000..a12830d42d36 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98488-TypolinkOptionAddQueryStringOnlyIncludesResolvedQueryArguments.rst @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt + +.. _breaking-98488-1664578695: + +========================================================================================== +Breaking: #98488 - Typolink option "addQueryString" only includes resolved query arguments +========================================================================================== + +See :issue:`98488` + +Description +=========== + +The Typolink option :typoscript:`typolink.addQueryString` previously set all given +GET parameters to a generated URL that were handed in to the request. + +This option is also used under the hood for the Fluid ViewHelpers +:html:`<f:link.typolink>` and :html:`<f:uri.typolink>`. + +With TYPO3 v9 and Routing, this option now only adds the query arguments that +have been resolved during the Routing process. This way, additional query arguments +are never added by default. + + +Impact +====== + +Setting :typoscript:`typolink.addQueryString = 1` now adds only arguments resolved +by Route Enhancers, any other query arguments are rejected. + + +Affected installations +====================== + +TYPO3 installations relying on `typolink.addQueryString`. + + +Migration +========= + +It is recommended to keep the setting as is, as TYPO3 can identify valid query arguments +via Routing. + +However, to ensure the previous behaviour, the option :typoscript:`typolink.addQueryString` can be set to `untrusted` to add all given. + +The same value is also possible for the Fluid ViewHelpers +:html:`<f:link.typolink>` and :html:`<f:uri.typolink>`. + +.. index:: Fluid, TypoScript, NotScanned, ext:frontend \ No newline at end of file diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Deprecation-98488-ContentObjectRenderer-getQueryArguments.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Deprecation-98488-ContentObjectRenderer-getQueryArguments.rst new file mode 100644 index 000000000000..4aba1229a60d --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Deprecation-98488-ContentObjectRenderer-getQueryArguments.rst @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +.. _deprecation-98488-1664576976: + +============================================================== +Deprecation: #98488 - ContentObjectRenderer->getQueryArguments +============================================================== + +See :issue:`98488` + +Description +=========== + +The public method :php:`ContentObjectRenderer->getQueryArguments()` has been +marked as deprecated. + + +Impact +====== + +Calling the method directly via PHP will trigger a PHP deprecation warning. + + +Affected installations +====================== + +TYPO3 installations with custom third-party extensions calling this method directly, +which is highly unlikely. + + +Migration +========= + +Use LinkFactory directly to create links with the typolink configuration option :typoscript:`typolink.addQueryString = untrusted` to create links with the same behaviour. + +.. index:: Frontend, TypoScript, FullyScanned, ext:frontend \ No newline at end of file diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Feature-98488-AdditionalSettingForTypolinkOptionAddQueryString.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-98488-AdditionalSettingForTypolinkOptionAddQueryString.rst new file mode 100644 index 000000000000..14144c828b2a --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-98488-AdditionalSettingForTypolinkOptionAddQueryString.rst @@ -0,0 +1,26 @@ +.. include:: /Includes.rst.txt + +.. _feature-98488-1664578785: + +========================================================================= +Feature: #98488 - Additional setting for Typolink option "addQueryString" +========================================================================= + +See :issue:`98488` + +Description +=========== + +The Typolink option :typoscript:`typolink.addQueryString` now also accepts the value `untrusted` to be used to retrieve all GET parameters of the current request. + +This value can also used under the hood for the Fluid ViewHelpers +:html:`<f:link.typolink>` and :html:`<f:uri.typolink>`. + + +Impact +====== + +Setting :typoscript:`typolink.addQueryString = untrusted` adds any given query parameters +just as it was done in TYPO3 v11 when using :typoscript:`typolink.addQueryString = 1`. + +.. index:: Fluid, TypoScript, ext:frontend \ No newline at end of file diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php index 7a0889d54bcd..a2e72d08e275 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php @@ -106,7 +106,7 @@ final class TypolinkViewHelper extends AbstractViewHelper $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false); $this->registerArgument('additionalParams', 'string', 'Additional query parameters to be attached to the resulting URL', false, ''); $this->registerArgument('additionalAttributes', 'array', 'Additional tag attributes to be added directly to the resulting HTML tag', false, []); - $this->registerArgument('addQueryString', 'bool', 'If set, the current query parameters will be kept in the URL', false, false); + $this->registerArgument('addQueryString', 'string', 'If set, the current query parameters will be kept in the URL. If set to "untrusted", then ALL query parameters will be added. Be aware, that this might lead to problems when the generated link is cached.', false, false); $this->registerArgument('addQueryStringExclude', 'string', 'Define parameters to be excluded from the query string (only active if addQueryString is set)', false, ''); $this->registerArgument('absolute', 'bool', 'Ensure the resulting URL is an absolute URL', false, false); $this->registerArgument('parts-as', 'string', 'Variable name containing typoLink parts (if any)', false, 'typoLinkParts'); @@ -157,7 +157,7 @@ final class TypolinkViewHelper extends AbstractViewHelper if (isset($arguments['language']) && $arguments['language'] !== null) { $instructions['language'] = $arguments['language']; } - if ($addQueryString) { + if ($addQueryString && $addQueryString !== 'false') { $instructions['addQueryString'] = $addQueryString; $instructions['addQueryString.'] = [ 'exclude' => $addQueryStringExclude, diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php index 993df53c8245..681dd29ad1a1 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php @@ -67,7 +67,7 @@ final class TypolinkViewHelper extends AbstractViewHelper $this->registerArgument('parameter', 'string', 'stdWrap.typolink style parameter string', true); $this->registerArgument('additionalParams', 'string', 'stdWrap.typolink additionalParams', false, ''); $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false); - $this->registerArgument('addQueryString', 'bool', 'If set, the current query parameters will be kept in the URL', false, false); + $this->registerArgument('addQueryString', 'string', 'If set, the current query parameters will be kept in the URL. If set to "untrusted", then ALL query parameters will be added. Be aware, that this might lead to problems when the generated link is cached.', false, false); $this->registerArgument('addQueryStringExclude', 'string', 'Define parameters to be excluded from the query string (only active if addQueryString is set)', false, ''); $this->registerArgument('absolute', 'bool', 'Ensure the resulting URL is an absolute URL', false, false); } @@ -101,7 +101,7 @@ final class TypolinkViewHelper extends AbstractViewHelper if (isset($arguments['language']) && $arguments['language'] !== null) { $instructions['language'] = $arguments['language']; } - if ($addQueryString) { + if ($addQueryString && $addQueryString !== 'false') { $instructions['addQueryString'] = $addQueryString; $instructions['addQueryString.'] = [ 'exclude' => $addQueryStringExclude, diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/TypolinkViewHelperTest.php b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/TypolinkViewHelperTest.php index 50e5f552870e..985fbe03f751 100644 --- a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/TypolinkViewHelperTest.php +++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/TypolinkViewHelperTest.php @@ -43,11 +43,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase '<a href="/en/">This is a testlink</a>', ], 'link: with add query string' => [ - '<f:link.typolink parameter="1" addQueryString="true">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="1" addQueryString="untrusted">This is a testlink</f:link.typolink>', '<a href="/en/?foo=bar&temp=test&cHash=286759dfcd3f566fa21091a0d77e9831">This is a testlink</a>', ], 'link: with add query string and exclude' => [ - '<f:link.typolink parameter="1" addQueryString="true" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="1" addQueryString="untrusted" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', '<a href="/en/?foo=bar&cHash=afa4b37588ab917af3cfe2cd4464029d">This is a testlink</a>', ], 't3://url link: default' => [ @@ -55,11 +55,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase '<a href="https://example.org?param=1">This is a testlink</a>', ], 't3://url link: with add query string' => [ - '<f:link.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="true">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="untrusted">This is a testlink</f:link.typolink>', '<a href="https://example.org?param=1">This is a testlink</a>', ], 't3://url link: with add query string and exclude' => [ - '<f:link.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="true" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="untrusted" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', '<a href="https://example.org?param=1">This is a testlink</a>', ], 'mailto: link: default' => [ @@ -67,11 +67,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase '<a href="mailto:foo@typo3.org">This is a testlink</a>', ], 'mailto: link: with add query string' => [ - '<f:link.typolink parameter="mailto:foo@typo3.org" addQueryString="true">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="mailto:foo@typo3.org" addQueryString="untrusted">This is a testlink</f:link.typolink>', '<a href="mailto:foo@typo3.org">This is a testlink</a>', ], 'mailto: link: with add query string and exclude' => [ - '<f:link.typolink parameter="mailto:foo@typo3.org" addQueryString="true" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="mailto:foo@typo3.org" addQueryString="untrusted" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', '<a href="mailto:foo@typo3.org">This is a testlink</a>', ], 'http://: link: default' => [ @@ -79,11 +79,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase '<a href="http://typo3.org/foo/?foo=bar">This is a testlink</a>', ], 'http://: link: with add query string' => [ - '<f:link.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="true">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="untrusted">This is a testlink</f:link.typolink>', '<a href="http://typo3.org/foo/?foo=bar">This is a testlink</a>', ], 'http://: link: with add query string and exclude' => [ - '<f:link.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="true" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', + '<f:link.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="untrusted" addQueryStringExclude="temp">This is a testlink</f:link.typolink>', '<a href="http://typo3.org/foo/?foo=bar">This is a testlink</a>', ], 'page with complex title and extended parameters' => [ diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/TypolinkViewHelperTest.php b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/TypolinkViewHelperTest.php index 60881332dbdc..a8b2cbb99c5f 100644 --- a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/TypolinkViewHelperTest.php +++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/TypolinkViewHelperTest.php @@ -54,11 +54,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase '/en/', ], 'uri: with add query string' => [ - '<f:uri.typolink parameter="1" addQueryString="true" />', + '<f:uri.typolink parameter="1" addQueryString="untrusted" />', '/en/?foo=bar&temp=test&cHash=286759dfcd3f566fa21091a0d77e9831', ], 'uri: with add query string and exclude' => [ - '<f:uri.typolink parameter="1" addQueryString="true" addQueryStringExclude="temp" />', + '<f:uri.typolink parameter="1" addQueryString="untrusted" addQueryStringExclude="temp" />', '/en/?foo=bar&cHash=afa4b37588ab917af3cfe2cd4464029d', ], 't3://url uri: default' => [ @@ -66,11 +66,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase 'https://example.org?param=1', ], 't3://url uri: with add query string' => [ - '<f:uri.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="true" />', + '<f:uri.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="untrusted" />', 'https://example.org?param=1', ], 't3://url uri: with add query string and exclude' => [ - '<f:uri.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="true" addQueryStringExclude="temp" />', + '<f:uri.typolink parameter="t3://url?url=https://example.org?param=1&other=dude" addQueryString="untrusted" addQueryStringExclude="temp" />', 'https://example.org?param=1', ], 'mailto: uri: default' => [ @@ -78,11 +78,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase 'mailto:foo@typo3.org', ], 'mailto: uri: with add query string' => [ - '<f:uri.typolink parameter="mailto:foo@typo3.org" addQueryString="true" />', + '<f:uri.typolink parameter="mailto:foo@typo3.org" addQueryString="untrusted" />', 'mailto:foo@typo3.org', ], 'mailto: uri: with add query string and exclude' => [ - '<f:uri.typolink parameter="mailto:foo@typo3.org" addQueryString="true" addQueryStringExclude="temp" />', + '<f:uri.typolink parameter="mailto:foo@typo3.org" addQueryString="untrusted" addQueryStringExclude="temp" />', 'mailto:foo@typo3.org', ], 'http://: uri: default' => [ @@ -90,11 +90,11 @@ class TypolinkViewHelperTest extends FunctionalTestCase 'http://typo3.org/foo/?foo=bar', ], 'http://: uri: with add query string' => [ - '<f:uri.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="true" />', + '<f:uri.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="untrusted" />', 'http://typo3.org/foo/?foo=bar', ], 'http://: uri: with add query string and exclude' => [ - '<f:uri.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="true" addQueryStringExclude="temp" />', + '<f:uri.typolink parameter="http://typo3.org/foo/?foo=bar" addQueryString="untrusted" addQueryStringExclude="temp" />', 'http://typo3.org/foo/?foo=bar', ], ]; diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php index 54824de3cb5a..304ec201d9ca 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php +++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php @@ -4673,9 +4673,11 @@ class ContentObjectRenderer implements LoggerAwareInterface * * @param array $conf Configuration * @return string The URL query part (starting with a &) + * @deprecated will be removed in TYPO3 v13.0 */ public function getQueryArguments($conf) { + trigger_error('Calling ContentObjectRenderer->getQueryArguments() will be removed in TYPO3 v13.0. Use LinkFactory directly to create links', E_USER_DEPRECATED); $currentQueryArray = $this->getRequest()->getQueryParams(); if ($conf['exclude'] ?? false) { $excludeString = str_replace(',', '&', $conf['exclude']); diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php index 6e24edb56773..a9a9967bb0d9 100644 --- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php +++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php @@ -1662,7 +1662,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface } return GeneralUtility::makeInstance(ContentObjectRenderer::class, $this)->createUrl([ 'parameter' => $parameter, - 'addQueryString' => true, + 'addQueryString' => 'untrusted', 'addQueryString.' => ['exclude' => 'id,type'], 'forceAbsoluteUrl' => true, ]); diff --git a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php index a3c9507206c4..74797cc68cc7 100644 --- a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php +++ b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php @@ -33,13 +33,16 @@ use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Http\Uri; use TYPO3\CMS\Core\LinkHandling\LinkService; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; +use TYPO3\CMS\Core\Routing\PageArguments; use TYPO3\CMS\Core\Routing\RouterInterface; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\Entity\SiteInterface; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Type\Bitmask\PageTranslationVisibility; +use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\HttpUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Utility\RootlineUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -219,7 +222,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder } $queryParameters = []; - $addQueryParams = ($conf['addQueryString'] ?? false) ? $this->contentObjectRenderer->getQueryArguments($conf['addQueryString.'] ?? []) : ''; + $addQueryParams = ($conf['addQueryString'] ?? false) ? $this->getQueryArguments($conf['addQueryString'], $conf['addQueryString.'] ?? []) : ''; $addQueryParams .= trim((string)$this->contentObjectRenderer->stdWrapValue('additionalParams', $conf)); if ($addQueryParams === '&' || ($addQueryParams[0] ?? '') !== '&') { $addQueryParams = ''; @@ -718,6 +721,42 @@ class PageLinkBuilder extends AbstractTypolinkBuilder } } + /** + * Gets the query arguments and assembles them for URLs. + * By default, only the resolved query arguments from the route are used, using "untrusted" as $queryInformation + * allows to also include ANY query parameter - use with care. + * + * Arguments may be removed or set, depending on configuration. + * + * @param bool|string|int $queryInformation is set to "1", "true", "0", "false" or "untrusted" + * @param array $configuration Configuration + * @return string The URL query part (starting with a &) or empty + */ + protected function getQueryArguments(bool|string|int $queryInformation, array $configuration): string + { + if (!$queryInformation || $queryInformation === 'false') { + return ''; + } + $request = $this->contentObjectRenderer->getRequest(); + $pageArguments = $request->getAttribute('routing'); + if (!$pageArguments instanceof PageArguments) { + return ''; + } + $currentQueryArray = $pageArguments->getRouteArguments(); + if ($queryInformation === 'untrusted') { + $currentQueryArray = array_replace_recursive($pageArguments->getQueryArguments(), $currentQueryArray); + } + if ($configuration['exclude'] ?? false) { + $excludeString = str_replace(',', '&', $configuration['exclude']); + $excludedQueryParts = []; + parse_str($excludeString, $excludedQueryParts); + $newQueryArray = ArrayUtility::arrayDiffKeyRecursive($currentQueryArray, $excludedQueryParts); + } else { + $newQueryArray = $currentQueryArray; + } + return HttpUtility::buildQueryString($newQueryArray, '&'); + } + /** * Check if we have a site object in the current request. if null, this usually means that * this class was called from CLI context. diff --git a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php index 2b34fe22246c..c0896577d55c 100644 --- a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php +++ b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php @@ -332,50 +332,6 @@ class ContentObjectRendererTest extends UnitTestCase self::assertNull($object); } - ///////////////////////////////////////// - // Tests concerning getQueryArguments() - ///////////////////////////////////////// - /** - * @test - */ - public function getQueryArgumentsExcludesParameters(): void - { - $queryParameters = [ - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => [ - 'key31' => 'value31', - 'key32' => [ - 'key321' => 'value321', - 'key322' => 'value322', - ], - ], - ]; - $request = new ServerRequest('https://example.com'); - $request = $request->withQueryParams($queryParameters); - $getQueryArgumentsConfiguration = []; - $getQueryArgumentsConfiguration['exclude'] = []; - $getQueryArgumentsConfiguration['exclude'][] = 'key1'; - $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]'; - $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]'; - $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']); - $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322'); - $this->subject->setRequest($request); - $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration); - self::assertEquals($expectedResult, $actualResult); - } - - /** - * Encodes square brackets in URL. - * - * @param string $string - * @return string - */ - private function rawUrlEncodeSquareBracketsInUrl(string $string): string - { - return str_replace(['[', ']'], ['%5B', '%5D'], $string); - } - ////////////////////////// // Tests concerning crop ////////////////////////// diff --git a/typo3/sysext/frontend/Tests/Unit/Typolink/PageLinkBuilderTest.php b/typo3/sysext/frontend/Tests/Unit/Typolink/PageLinkBuilderTest.php new file mode 100644 index 000000000000..e54c4ecfa5c6 --- /dev/null +++ b/typo3/sysext/frontend/Tests/Unit/Typolink/PageLinkBuilderTest.php @@ -0,0 +1,76 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Frontend\Tests\Unit\Typolink; + +use TYPO3\CMS\Core\Http\ServerRequest; +use TYPO3\CMS\Core\Routing\PageArguments; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\CMS\Frontend\Typolink\PageLinkBuilder; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; + +/** + * Test case + */ +class PageLinkBuilderTest extends UnitTestCase +{ + /** + * @test + */ + public function getQueryArgumentsExcludesParameters(): void + { + $queryParameters = [ + 'key1' => 'value1', + 'key2' => 'value2', + 'key3' => [ + 'key31' => 'value31', + 'key32' => [ + 'key321' => 'value321', + 'key322' => 'value322', + ], + ], + ]; + $request = new ServerRequest('https://example.com'); + $request = $request->withQueryParams($queryParameters); + $request = $request->withAttribute('routing', new PageArguments(1, '', $queryParameters, [], [])); + $configuration = []; + $configuration['exclude'] = []; + $configuration['exclude'][] = 'key1'; + $configuration['exclude'][] = 'key3[key31]'; + $configuration['exclude'][] = 'key3[key32][key321]'; + $configuration['exclude'] = implode(',', $configuration['exclude']); + $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322'); + $GLOBALS['TSFE'] = new \stdClass(); + $cObj = new ContentObjectRenderer(); + $cObj->setRequest($request); + $subject = $this->getAccessibleMock(PageLinkBuilder::class, ['dummy'], [], '', false); + $subject->_set('contentObjectRenderer', $cObj); + $actualResult = $subject->_call('getQueryArguments', 'untrusted', $configuration); + self::assertEquals($expectedResult, $actualResult); + } + + /** + * Encodes square brackets in URL. + * + * @param string $string + * @return string + */ + private function rawUrlEncodeSquareBracketsInUrl(string $string): string + { + return str_replace(['[', ']'], ['%5B', '%5D'], $string); + } +} diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index f9ff9b58f2d4..319da8e0d4b6 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -5358,4 +5358,11 @@ return [ 'Deprecation-98479-DeprecatedFileReferenceRelatedFunctionality.rst', ], ], + 'TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer->getQueryArguments' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-98488-ContentObjectRenderer-getQueryArguments.rst', + ], + ], ]; -- GitLab