From bd606fda2f54db89ba8803a78726d4438b25592f Mon Sep 17 00:00:00 2001
From: Sebastian Hofer <sebastian.hofer@marit.ag>
Date: Mon, 27 Nov 2017 19:08:22 +0100
Subject: [PATCH] [FEATURE] Add support for addQueryString to
 TypolinkViewHelper

This enables {Link,Uri}/TypoLinkViewHelper to support addQueryString,
addQueryString.method and addQueryString.exclude.

Resolves: #81358
Releases: master
Change-Id: I96f0a2035997513eced06ba543a718b164b9da63
Reviewed-on: https://review.typo3.org/54798
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
---
 .../ViewHelpers/Link/TypolinkViewHelper.php   |  11 ++
 .../ViewHelpers/Uri/TypolinkViewHelper.php    |  11 ++
 .../Fixtures/link_typolink_viewhelper.html    |   5 +
 .../Functional/ViewHelpers/Fixtures/pages.xml |   7 +
 .../Fixtures/uri_typolink_viewhelper.html     |   5 +
 .../ViewHelpers/TypolinkViewHelperTest.php    | 136 ++++++++++++++++++
 .../Link/TypolinkViewHelperTest.php           |  63 +++++++-
 7 files changed, 235 insertions(+), 3 deletions(-)
 create mode 100644 typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/link_typolink_viewhelper.html
 create mode 100644 typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/pages.xml
 create mode 100644 typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/uri_typolink_viewhelper.html
 create mode 100644 typo3/sysext/fluid/Tests/Functional/ViewHelpers/TypolinkViewHelperTest.php

diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php
index ac02693f27ed..55a52968e95a 100644
--- a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php
+++ b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php
@@ -74,6 +74,9 @@ class TypolinkViewHelper extends AbstractViewHelper
         $this->registerArgument('additionalParams', 'string', '', false, '');
         $this->registerArgument('additionalAttributes', 'array', '', false, []);
         $this->registerArgument('useCacheHash', 'bool', '', false, false);
+        $this->registerArgument('addQueryString', 'bool', '', false, false);
+        $this->registerArgument('addQueryStringMethod', 'string', '', false, 'GET');
+        $this->registerArgument('addQueryStringExclude', 'string', '', false, '');
     }
 
     /**
@@ -95,6 +98,9 @@ class TypolinkViewHelper extends AbstractViewHelper
         $additionalParams = $arguments['additionalParams'];
         $additionalAttributes = $arguments['additionalAttributes'];
         $useCacheHash = $arguments['useCacheHash'];
+        $addQueryString = $arguments['addQueryString'];
+        $addQueryStringMethod = $arguments['addQueryStringMethod'];
+        $addQueryStringExclude = $arguments['addQueryStringExclude'];
 
         // Merge the $parameter with other arguments
         $typolinkParameter = self::createTypolinkParameterArrayFromArguments($parameter, $target, $class, $title, $additionalParams);
@@ -120,6 +126,11 @@ class TypolinkViewHelper extends AbstractViewHelper
                         'parameter' => $typolinkParameter,
                         'ATagParams' => $aTagParams,
                         'useCacheHash' => $useCacheHash,
+                        'addQueryString' => $addQueryString,
+                        'addQueryString.' => [
+                            'method' => $addQueryStringMethod,
+                            'exclude' => $addQueryStringExclude
+                        ]
                     ]
                 ]
             );
diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php
index 43dfe3534a22..e8400c46b94c 100644
--- a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php
+++ b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php
@@ -57,6 +57,9 @@ class TypolinkViewHelper extends AbstractViewHelper
         $this->registerArgument('parameter', 'string', 'stdWrap.typolink style parameter string', true);
         $this->registerArgument('additionalParams', 'string', 'stdWrap.typolink additionalParams', false, '');
         $this->registerArgument('useCacheHash', 'bool', '', false, false);
+        $this->registerArgument('addQueryString', 'bool', '', false, false);
+        $this->registerArgument('addQueryStringMethod', 'string', '', false, 'GET');
+        $this->registerArgument('addQueryStringExclude', 'string', '', false, '');
     }
 
     /**
@@ -71,6 +74,9 @@ class TypolinkViewHelper extends AbstractViewHelper
         $parameter = $arguments['parameter'];
         $additionalParams = $arguments['additionalParams'];
         $useCacheHash = $arguments['useCacheHash'];
+        $addQueryString = $arguments['addQueryString'];
+        $addQueryStringMethod = $arguments['addQueryStringMethod'];
+        $addQueryStringExclude = $arguments['addQueryStringExclude'];
 
         $content = '';
         if ($parameter) {
@@ -79,6 +85,11 @@ class TypolinkViewHelper extends AbstractViewHelper
                 [
                     'parameter' => self::createTypolinkParameterFromArguments($parameter, $additionalParams),
                     'useCacheHash' => $useCacheHash,
+                    'addQueryString' => $addQueryString,
+                    'addQueryString.' => [
+                        'method' => $addQueryStringMethod,
+                        'exclude' => $addQueryStringExclude
+                    ]
                 ]
             );
         }
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/link_typolink_viewhelper.html b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/link_typolink_viewhelper.html
new file mode 100644
index 000000000000..116546d7d016
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/link_typolink_viewhelper.html
@@ -0,0 +1,5 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+
+<f:link.typolink parameter="{uid}" addQueryString="{addQueryString}" addQueryStringMethod="{addQueryStringMethod}"
+                 addQueryStringExclude="{addQueryStringExclude}">This is a testlink</f:link.typolink>
+<f:link.typolink parameter="{uid}">This is a testlink</f:link.typolink>
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/pages.xml b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/pages.xml
new file mode 100644
index 000000000000..117accc506b4
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/pages.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+	<pages>
+		<uid>1</uid>
+		<title>Seitentitel</title>
+	</pages>
+</dataset>
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/uri_typolink_viewhelper.html b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/uri_typolink_viewhelper.html
new file mode 100644
index 000000000000..7d4bdbda97b2
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/uri_typolink_viewhelper.html
@@ -0,0 +1,5 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+
+<f:uri.typolink parameter="{uid}" addQueryString="{addQueryString}" addQueryStringMethod="{addQueryStringMethod}"
+                 addQueryStringExclude="{addQueryStringExclude}" />
+<f:uri.typolink parameter="{uid}" />
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/TypolinkViewHelperTest.php b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/TypolinkViewHelperTest.php
new file mode 100644
index 000000000000..56550aa99c5c
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/TypolinkViewHelperTest.php
@@ -0,0 +1,136 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Fluid\View\StandaloneView;
+
+class TypolinkViewHelperTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
+{
+    /**
+     * @var array
+     */
+    protected $testExtensionsToLoad = ['typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test'];
+
+    /**
+     * @var array
+     */
+    protected $coreExtensionsToLoad = ['fluid'];
+
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $this->importDataSet('typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/pages.xml');
+
+        $_GET = [
+            'foo' => 'bar',
+            'temp' => 'test',
+        ];
+    }
+
+    /**
+     * @param bool $addQueryString
+     * @param string $addQueryStringMethod
+     * @param string $addQueryStringExclude
+     * @param string $expected
+     * @param string $template
+     *
+     * @test
+     * @dataProvider renderCreatesCorrectLinkProvider
+     */
+    public function renderCreatesCorrectLink(
+        bool $addQueryString,
+        string $addQueryStringMethod,
+        string $addQueryStringExclude,
+        string $expected,
+        string $template
+    ) {
+        $view = new StandaloneView();
+        $view->setTemplatePathAndFilename('typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/' . $template . '.html');
+        $view->assignMultiple([
+            'uid' => 1,
+            'addQueryString' => $addQueryString,
+            'addQueryStringMethod' => $addQueryStringMethod,
+            'addQueryStringExclude' => $addQueryStringExclude,
+        ]);
+        $this->assertEquals($expected, trim(preg_replace('/\s+/', ' ', $view->render())));
+    }
+
+    /**
+     * @return array
+     */
+    public function renderCreatesCorrectLinkProvider(): array
+    {
+        return [
+            'link: default' => [
+                'addQueryString' => false,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => '',
+                'expected' => '<a href="index.php?id=1">This is a testlink</a> <a href="index.php?id=1">This is a testlink</a>',
+                'template' => 'link_typolink_viewhelper',
+            ],
+            'link: with add query string' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => '',
+                'expected' => '<a href="index.php?id=1&amp;foo=bar&amp;temp=test">This is a testlink</a> <a href="index.php?id=1">This is a testlink</a>',
+                'template' => 'link_typolink_viewhelper',
+            ],
+            'link: with add query string and exclude' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => 'temp',
+                'expected' => '<a href="index.php?id=1&amp;foo=bar">This is a testlink</a> <a href="index.php?id=1">This is a testlink</a>',
+                'template' => 'link_typolink_viewhelper',
+            ],
+            'link: with add query string and method POST' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'POST',
+                'addQueryStringExclude' => 'temp',
+                'expected' => '<a href="index.php?id=1">This is a testlink</a> <a href="index.php?id=1">This is a testlink</a>',
+                'template' => 'link_typolink_viewhelper',
+            ],
+            'uri: default' => [
+                'addQueryString' => false,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => '',
+                'expected' => 'index.php?id=1 index.php?id=1',
+                'template' => 'uri_typolink_viewhelper',
+            ],
+            'uri: with add query string' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => '',
+                'expected' => 'index.php?id=1&amp;foo=bar&amp;temp=test index.php?id=1',
+                'template' => 'uri_typolink_viewhelper',
+            ],
+            'uri: with add query string and exclude' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'GET',
+                'addQueryStringExclude' => 'temp',
+                'expected' => 'index.php?id=1&amp;foo=bar index.php?id=1',
+                'template' => 'uri_typolink_viewhelper',
+            ],
+            'uri: with add query string and method POST' => [
+                'addQueryString' => true,
+                'addQueryStringMethod' => 'POST',
+                'addQueryStringExclude' => 'temp',
+                'expected' => 'index.php?id=1 index.php?id=1',
+                'template' => 'uri_typolink_viewhelper',
+            ],
+        ];
+    }
+}
diff --git a/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/TypolinkViewHelperTest.php b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/TypolinkViewHelperTest.php
index 5de44405ed4b..c09d2acf904b 100644
--- a/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/TypolinkViewHelperTest.php
+++ b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/TypolinkViewHelperTest.php
@@ -61,6 +61,50 @@ class TypolinkViewHelperTest extends ViewHelperBaseTestcase
         $this->assertEquals('foo', $this->subject->render());
     }
 
+    /**
+     * @test
+     */
+    public function renderCallsStdWrapWithrightParameters()
+    {
+        $addQueryString = true;
+        $addQueryStringMethod = 'GET,POST';
+        $addQueryStringExclude = 'cHash';
+
+        $this->subject->expects($this->any())->method('renderChildren')->will($this->returnValue('innerContent'));
+        $this->subject->setArguments([
+            'parameter' => '42',
+            'target' => '',
+            'class' => '',
+            'title' => '',
+            'additionalParams' => '',
+            'additionalAttributes' => [],
+            'addQueryString' => $addQueryString,
+            'addQueryStringMethod' => $addQueryStringMethod,
+            'addQueryStringExclude' => $addQueryStringExclude,
+        ]);
+        $contentObjectRendererMock = $this->createMock(ContentObjectRenderer::class);
+        $contentObjectRendererMock->expects($this->once())
+            ->method('stdWrap')
+            ->with(
+                'innerContent',
+                [
+                    'typolink.' => [
+                        'parameter' => '42',
+                        'ATagParams' => '',
+                        'useCacheHash' => false,
+                        'addQueryString' => $addQueryString,
+                        'addQueryString.' => [
+                            'method' => $addQueryStringMethod,
+                            'exclude' => $addQueryStringExclude,
+                        ],
+                    ],
+                ]
+            )
+            ->will($this->returnValue('foo'));
+        GeneralUtility::addInstance(ContentObjectRenderer::class, $contentObjectRendererMock);
+        $this->assertEquals('foo', $this->subject->render());
+    }
+
     /**
      * @return array
      */
@@ -160,9 +204,22 @@ class TypolinkViewHelperTest extends ViewHelperBaseTestcase
      * @param string $additionalParametersFromFluid
      * @param string $expected
      */
-    public function createTypolinkParameterArrayFromArgumentsReturnsExpectedArray($input, $targetFromFluid, $classFromFluid, $titleFromFluid, $additionalParametersFromFluid, $expected)
-    {
-        $result = $this->subject->_call('createTypolinkParameterArrayFromArguments', $input, $targetFromFluid, $classFromFluid, $titleFromFluid, $additionalParametersFromFluid);
+    public function createTypolinkParameterArrayFromArgumentsReturnsExpectedArray(
+        $input,
+        $targetFromFluid,
+        $classFromFluid,
+        $titleFromFluid,
+        $additionalParametersFromFluid,
+        $expected
+    ) {
+        $result = $this->subject->_call(
+            'createTypolinkParameterArrayFromArguments',
+            $input,
+            $targetFromFluid,
+            $classFromFluid,
+            $titleFromFluid,
+            $additionalParametersFromFluid
+        );
         $this->assertSame($expected, $result);
     }
 }
-- 
GitLab