‪TYPO3CMS  ‪main
ActionViewHelperTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
33 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
34 
35 final class ‪ActionViewHelperTest extends FunctionalTestCase
36 {
38 
39  protected const ‪LANGUAGE_PRESETS = [
40  'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
41  ];
42 
43  protected array ‪$configurationToUseInTestInstance = [
44  'FE' => [
45  'cacheHash' => [
46  'excludedParameters' => [
47  'untrusted',
48  ],
49  ],
50  ],
51  ];
52 
53  #[Test]
54  public function ‪renderThrowsExceptionWithoutARequest(): void
55  {
56  $this->expectException(\RuntimeException::class);
57  $this->expectExceptionCode(1690365240);
58  $view = new ‪StandaloneView();
59  $view->setRequest();
60  $view->setTemplateSource('<f:link.action />');
61  $view->render();
62  }
63 
64  #[Test]
66  {
67  $request = new ‪ServerRequest();
68  $request = $request->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_FE);
69  $request = $request->withAttribute('routing', new ‪PageArguments(1, '0', []));
70  $this->expectException(\RuntimeException::class);
71  $this->expectExceptionCode(1690370264);
72  $view = new ‪StandaloneView();
73  $view->setRequest($request);
74  $view->setTemplateSource('<f:link.action />');
75  $view->render();
76  }
77 
78  #[Test]
80  {
81  $request = new ‪ServerRequest('http://localhost/typo3/');
82  $request = $request->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_BE);
83  $request = $request->withQueryParams(['route' => 'web_layout']);
84  $this->expectException(\RuntimeException::class);
85  $this->expectExceptionCode(1690365240);
86  $view = new ‪StandaloneView();
87  $view->setRequest($request);
88  $view->setTemplateSource('<f:link.action />');
89  $view->render();
90  }
91 
93  {
94  yield 'link to root page with plugin' => [
95  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link to root page with plugin</f:link.action>',
96  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with plugin</a>',
97  ];
98 
99  yield 'link to root page with plugin and section' => [
100  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13">link to root page with plugin and section</f:link.action>',
101  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13">link to root page with plugin and section</a>',
102  ];
103 
104  yield 'link to root page with page type' => [
105  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234">link to root page with page type</f:link.action>',
106  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with page type</a>',
107  ];
108  // see: https://forge.typo3.org/issues/101432
109  yield 'link with target renders the correct target attribute if intTarget is configured' => [
110  '<f:link.action pageUid="3" target="home" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link me</f:link.action>',
111  '<a target="home" href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=47522c99ab9100cb401cdaeb02504e1f">link me</a>',
112  [
113  'config.' => [
114  'intTarget' => '_self',
115  ],
116  ],
117  ];
118  // see: https://forge.typo3.org/issues/101432
119  yield 'link skips configured intTarget if no target viewhelper attribute is provided' => [
120  '<f:link.action pageUid="3" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link me</f:link.action>',
121  '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=47522c99ab9100cb401cdaeb02504e1f">link me</a>',
122  [
123  'config' => [
124  'intTarget' => '_self',
125  ],
126  ],
127  ];
128  }
129 
130  #[DataProvider('renderInFrontendWithCoreContextAndAllNecessaryExtbaseArgumentsDataProvider')]
131  #[Test]
132  public function ‪renderInFrontendWithCoreContextAndAllNecessaryExtbaseArguments(string $template, string $expected, array $frontendTypoScriptConfigArray = []): void
133  {
134  $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
136  'test',
137  $this->‪buildSiteConfiguration(1, '/'),
138  );
139  $frontendTypoScript = new ‪FrontendTypoScript(new ‪RootNode(), [], [], []);
140  $frontendTypoScript->setConfigArray($frontendTypoScriptConfigArray);
141  $request = new ‪ServerRequest();
142  $request = $request->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_FE);
143  $request = $request->withAttribute('routing', new ‪PageArguments(1, '0', ['untrusted' => 123]));
144  $request = $request->withAttribute('currentContentObject', $this->get(ContentObjectRenderer::class));
145  $request = $request->withAttribute('frontend.typoscript', $frontendTypoScript);
146  ‪$GLOBALS['TYPO3_REQUEST'] = $request;
147  $view = new ‪StandaloneView();
148  $view->setRequest($request);
149  $view->setTemplateSource($template);
150  $result = $view->render();
151  self::assertSame($expected, $result);
152  }
153 
154  public static function ‪renderInFrontendWithExtbaseContextDataProvider(): \Generator
155  {
156  // with all extbase arguments provided
157  yield 'link to root page with plugin' => [
158  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link to root page with plugin</f:link.action>',
159  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with plugin</a>',
160  ];
161 
162  yield 'link to root page with plugin and section' => [
163  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13">link to root page with plugin and section</f:link.action>',
164  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13">link to root page with plugin and section</a>',
165  ];
166 
167  yield 'link to root page with page type' => [
168  '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234">link to root page with page type</f:link.action>',
169  '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with page type</a>',
170  ];
171  // without all extbase arguments provided
172  yield 'renderProvidesATagForValidLinkTarget' => [
173  '<f:link.action>index.php</f:link.action>',
174  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">index.php</a>',
175  ];
176  yield 'renderWillProvideEmptyATagForNonValidLinkTarget' => [
177  '<f:link.action></f:link.action>',
178  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3"></a>',
179  ];
180  yield 'link to root page in extbase context' => [
181  '<f:link.action pageUid="1">linkMe</f:link.action>',
182  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">linkMe</a>',
183  ];
184  yield 'link to root page with section' => [
185  '<f:link.action pageUid="1" section="c13">linkMe</f:link.action>',
186  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3#c13">linkMe</a>',
187  ];
188  yield 'link to root page with page type in extbase context' => [
189  '<f:link.action pageUid="1" pageType="1234">linkMe</f:link.action>',
190  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">linkMe</a>',
191  ];
192  yield 'link to root page with untrusted query arguments' => [
193  '<f:link.action addQueryString="untrusted"></f:link.action>',
194  '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;untrusted=123&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3"></a>',
195  ];
196  yield 'link to page sub page' => [
197  '<f:link.action pageUid="3">linkMe</f:link.action>',
198  '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=d9289022f99f8cbc8080832f61e46509">linkMe</a>',
199  ];
200  yield 'arguments one level' => [
201  '<f:link.action pageUid="3" arguments="{foo: \'bar\'}">haiku title</f:link.action>',
202  '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bfoo%5D=bar&amp;cHash=74dd4635cee85b19b67cd9b497ec99e9">haiku title</a>',
203  ];
204  yield 'additional parameters two levels' => [
205  '<f:link.action pageUid="3" additionalParams="{tx_examples_haiku: {action: \'show\', haiku: 42}}">haiku title</f:link.action>',
206  '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bhaiku%5D=42&amp;cHash=aefc37bc2323ebd8c8e39c222adb7413">haiku title</a>',
207  ];
208  // see: https://forge.typo3.org/issues/101432
209  yield 'link with target renders the correct target attribute if intTarget is configured' => [
210  '<f:link.action pageUid="3" target="home" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link me</f:link.action>',
211  '<a target="home" href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=47522c99ab9100cb401cdaeb02504e1f">link me</a>',
212  [
213  'config.' => [
214  'intTarget' => '_self',
215  ],
216  ],
217  ];
218  // see: https://forge.typo3.org/issues/101432
219  yield 'link skips configured intTarget if no target viewhelper attribute is provided' => [
220  '<f:link.action pageUid="3" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link me</f:link.action>',
221  '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=47522c99ab9100cb401cdaeb02504e1f">link me</a>',
222  [
223  'config' => [
224  'intTarget' => '_self',
225  ],
226  ],
227  ];
228  }
229 
230  #[DataProvider('renderInFrontendWithExtbaseContextDataProvider')]
231  #[Test]
232  public function ‪renderInFrontendWithExtbaseContext(string $template, string $expected, array $frontendTypoScriptConfigArray = []): void
233  {
234  $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
236  'test',
237  $this->‪buildSiteConfiguration(1, '/'),
238  );
239  $frontendTypoScript = new ‪FrontendTypoScript(new ‪RootNode(), [], [], []);
240  $frontendTypoScript->setSetupArray([]);
241  $frontendTypoScript->setConfigArray($frontendTypoScriptConfigArray);
242  $extbaseRequestParameters = new ‪ExtbaseRequestParameters();
243  $extbaseRequestParameters->setControllerExtensionName('Examples');
244  $extbaseRequestParameters->setControllerName('Detail');
245  $extbaseRequestParameters->setControllerActionName('show');
246  $extbaseRequestParameters->setPluginName('Haiku');
247  $request = new ‪ServerRequest();
248  $request = $request->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_FE);
249  $request = $request->withAttribute('routing', new ‪PageArguments(1, '0', ['untrusted' => 123]));
250  $request = $request->withAttribute('extbase', $extbaseRequestParameters);
251  $request = $request->withAttribute('currentContentObject', $this->get(ContentObjectRenderer::class));
252  $request = $request->withAttribute('frontend.typoscript', $frontendTypoScript);
253  $pageInformation = new ‪PageInformation();
254  $pageInformation->setId(1);
255  $request = $request->withAttribute('frontend.page.information', $pageInformation);
256  $request = new ‪Request($request);
257  ‪$GLOBALS['TYPO3_REQUEST'] = $request;
258  $view = new ‪StandaloneView();
259  $view->setRequest($request);
260  $view->setTemplateSource($template);
261  $result = $view->render();
262  self::assertSame($expected, $result);
263  }
264 }
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:26
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder
Definition: SystemEnvironmentBuilder.php:41
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait
Definition: SiteBasedTestTrait.php:37
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\writeSiteConfiguration
‪writeSiteConfiguration(string $identifier, array $site=[], array $languages=[], array $errorHandling=[])
Definition: SiteBasedTestTrait.php:50
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_BE
‪const REQUESTTYPE_BE
Definition: SystemEnvironmentBuilder.php:45
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildSiteConfiguration
‪buildSiteConfiguration(int $rootPageId, string $base='')
Definition: SiteBasedTestTrait.php:88
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:39
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:30
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\TypoScript\AST\Node\RootNode
Definition: RootNode.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:102
‪TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters
Definition: ExtbaseRequestParameters.php:35
‪TYPO3\CMS\Core\TypoScript\FrontendTypoScript
Definition: FrontendTypoScript.php:30
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_FE
‪const REQUESTTYPE_FE
Definition: SystemEnvironmentBuilder.php:43
‪TYPO3\CMS\Extbase\Mvc\Request
Definition: Request.php:35
‪TYPO3\CMS\Frontend\Page\PageInformation
Definition: PageInformation.php:28