Skip to content

Commit cf50b02

Browse files
authored
Merge pull request #59 from helhum/feature/add-ts-path-view-helpers
2 parents 2beaa2a + 523ffe9 commit cf50b02

11 files changed

Lines changed: 259 additions & 26 deletions

Classes/Configuration/RecordRenderingConfigurationBuilder.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function __construct(RenderingContext $renderingContext)
4141
* @return string[]
4242
*
4343
*/
44-
public function configurationFor($extensionName, $pluginName, $contextRecord = 'currentPage')
44+
public function configurationFor(string $extensionName, string $pluginName, string $contextRecord = 'currentPage')
4545
{
4646
list($tableName, $uid) = $this->resolveTableNameAndUidFromContextString($contextRecord);
4747
$pluginSignature = $this->buildPluginSignature($extensionName, $pluginName);
@@ -52,22 +52,33 @@ public function configurationFor($extensionName, $pluginName, $contextRecord = '
5252
];
5353
}
5454

55+
/**
56+
* @param string $renderingPath
57+
* @param string $contextRecord
58+
*
59+
* @throws \Helhum\TyposcriptRendering\Configuration\ConfigurationBuildingException
60+
* @return string[]
61+
*
62+
*/
63+
public function configurationForPath(string $renderingPath, string $contextRecord = 'currentPage')
64+
{
65+
list($tableName, $uid) = $this->resolveTableNameAndUidFromContextString($contextRecord);
66+
return [
67+
'record' => $tableName . '_' . $uid,
68+
'path' => $renderingPath,
69+
];
70+
}
71+
5572
/**
5673
* Resolves the table name and uid for the record the rendering is based upon.
5774
* Falls back to current page if none is available
5875
*
5976
* @param string $contextRecord
6077
*
61-
* @throws ConfigurationBuildingException
6278
* @return string[] table name as first and uid as second index of the array
63-
*
6479
*/
65-
protected function resolveTableNameAndUidFromContextString($contextRecord)
80+
protected function resolveTableNameAndUidFromContextString(string $contextRecord)
6681
{
67-
if (!is_string($contextRecord)) {
68-
throw new ConfigurationBuildingException(sprintf('Context record must be of type string "%s" given.', gettype($contextRecord)), 1416846201);
69-
}
70-
7182
if ($contextRecord === 'currentPage') {
7283
$tableNameAndUid = ['pages', $this->renderingContext->getFrontendController()->id];
7384
} else {

Classes/Uri/TyposcriptRenderingUri.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ private function parseViewHelperContext(ViewHelperContext $viewHelperContext): v
4040
$arguments = $viewHelperContext->getArguments();
4141
$controllerContext = $viewHelperContext->getControllerContext();
4242

43-
$pluginName = $arguments['pluginName'];
44-
$extensionName = $arguments['extensionName'];
43+
$pluginName = $arguments['pluginName'] ?? null;
44+
$extensionName = $arguments['extensionName'] ?? null;
4545
$contextRecord = $arguments['contextRecord'];
4646
$additionalParams = $arguments['additionalParams'];
47+
$renderingPath = $arguments['typoscriptObjectPath'] ?? null;
4748

4849
if ($pluginName === null) {
4950
$pluginName = $controllerContext->getRequest()->getPluginName();
@@ -61,7 +62,11 @@ private function parseViewHelperContext(ViewHelperContext $viewHelperContext): v
6162
$contextRecord = $viewHelperContext->getContentObject()->currentRecord;
6263
}
6364
}
64-
$renderingConfiguration = $this->buildTypoScriptRenderingConfiguration($extensionName, $pluginName, $contextRecord);
65+
if ($renderingPath === null) {
66+
$renderingConfiguration = $this->buildTypoScriptRenderingConfiguration($extensionName, $pluginName, $contextRecord);
67+
} else {
68+
$renderingConfiguration = $this->buildConfigurationForPath($renderingPath, $contextRecord);
69+
}
6570
$additionalParams['tx_typoscriptrendering']['context'] = json_encode($renderingConfiguration);
6671

6772
$uriBuilder = $controllerContext->getUriBuilder();
@@ -77,7 +82,16 @@ private function parseViewHelperContext(ViewHelperContext $viewHelperContext): v
7782
->setAddQueryStringMethod($arguments['addQueryStringMethod'])
7883
->setArgumentsToBeExcludedFromQueryString($arguments['argumentsToBeExcludedFromQueryString']);
7984

80-
$this->parseUri($uriBuilder->uriFor($arguments['action'], $arguments['arguments'], $arguments['controller'], $extensionName, $pluginName));
85+
$this->parseUri(
86+
$uriBuilder->uriFor(
87+
$arguments['action'] ?? null,
88+
$arguments['arguments'] ?? null,
89+
$arguments['controller'] ?? null,
90+
$extensionName,
91+
$pluginName
92+
),
93+
$renderingPath !== null
94+
);
8195
}
8296

8397
/**
@@ -95,4 +109,19 @@ public function buildTypoScriptRenderingConfiguration(string $extensionName, str
95109

96110
return $configurationBuilder->configurationFor($extensionName, $pluginName, $contextRecordId);
97111
}
112+
113+
private function buildConfigurationForPath(string $renderingPath, string $contextRecordId): array
114+
{
115+
$configurationBuilder = new RecordRenderingConfigurationBuilder(new RenderingContext($GLOBALS['TSFE']));
116+
117+
return $configurationBuilder->configurationForPath($renderingPath, $contextRecordId);
118+
}
119+
120+
protected function parseUri($uri, $removeControllerArgument = false)
121+
{
122+
if ($removeControllerArgument) {
123+
$uri = str_replace('&tx__%5Bcontroller%5D=Standard', '', $uri);
124+
}
125+
parent::parseUri($uri);
126+
}
98127
}

Classes/ViewHelpers/Link/ActionViewHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
2020

2121
/**
22-
* A view helper for creating links to extbase actions.
22+
* A view helper for creating links to render individual extbase actions.
2323
*
2424
* = Examples =
2525
*
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
declare(strict_types=1);
3+
namespace Helhum\TyposcriptRendering\ViewHelpers\Link;
4+
5+
/*
6+
* This file is part of the TypoScript Rendering TYPO3 extension.
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
13+
* LICENSE file that was distributed with this source code.
14+
*
15+
*/
16+
17+
use Helhum\TyposcriptRendering\Uri\TyposcriptRenderingUri;
18+
use Helhum\TyposcriptRendering\Uri\ViewHelperContext;
19+
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
20+
21+
/**
22+
* A view helper for creating links to render arbitrary TypoScript objects.
23+
*
24+
* = Examples =
25+
*
26+
* <code title="link to the given TypoScript object">
27+
* <t:link.cObject typoscriptObjectPath="lib.userProfile">action link</f:link.action>
28+
* </code>
29+
* <output>
30+
* <a href="index.php?id=123&amp;tx_typoscriptrendering[context]={"record":"tt_content_123","path":"lib.userProfile"}&amp;cHash=xyz">action link</f:link.action>
31+
* (depending on the current page and your TS configuration)
32+
* </output>
33+
*/
34+
class CObjectViewHelper extends AbstractTagBasedViewHelper
35+
{
36+
/**
37+
* @var string
38+
*/
39+
protected $tagName = 'a';
40+
41+
/**
42+
* Arguments initialization
43+
*/
44+
public function initializeArguments()
45+
{
46+
parent::initializeArguments();
47+
$this->registerUniversalTagAttributes();
48+
$this->registerArgument('typoscriptObjectPath', 'string', 'TypoScript rendering path');
49+
$this->registerArgument('contextRecord', 'string', 'The record that the rendering should depend upon. e.g. current (default: record is fetched from current Extbase plugin), tt_content:12 (tt_content record with uid 12), pages:15 (pages record with uid 15), \'currentPage\' record of current page', false, 'current');
50+
$this->registerTagAttribute('name', 'string', 'Specifies the name of an anchor');
51+
$this->registerTagAttribute('rel', 'string', 'Specifies the relationship between the current document and the linked document');
52+
$this->registerTagAttribute('rev', 'string', 'Specifies the relationship between the linked document and the current document');
53+
$this->registerTagAttribute('target', 'string', 'Specifies where to open the linked document');
54+
$this->registerArgument('pageUid', 'int', 'Target page. See TypoLink destination');
55+
$this->registerArgument('pageType', 'int', 'Type of the target page. See typolink.parameter', false, 0);
56+
$this->registerArgument('noCache', 'bool', 'Set this to disable caching for the target page. You should not need this.', false, false);
57+
$this->registerArgument('section', 'string', 'The anchor to be added to the URI', false, '');
58+
$this->registerArgument('format', 'string', 'The requested format, e.g. ".html', false, '');
59+
$this->registerArgument('linkAccessRestrictedPages', 'bool', 'If set, links pointing to access restricted pages will still link to the page even though the page cannot be accessed.', false, false);
60+
$this->registerArgument('additionalParams', 'array', 'Additional query parameters that won\'t be prefixed like $arguments (overrule $arguments)', false, []);
61+
$this->registerArgument('absolute', 'bool', 'If set, the URI of the rendered link is absolute', false, false);
62+
$this->registerArgument('addQueryString', 'bool', 'If set, the current query parameters will be kept in the URI', false, false);
63+
$this->registerArgument('argumentsToBeExcludedFromQueryString', 'array', 'Arguments to be removed from the URI. Only active if $addQueryString = TRUE', false, []);
64+
$this->registerArgument('addQueryStringMethod', 'string', 'Set which parameters will be kept. Only active if $addQueryString = TRUE');
65+
}
66+
67+
/**
68+
* @return string Rendered link
69+
*/
70+
public function render()
71+
{
72+
$uri = (new TyposcriptRenderingUri())->withViewHelperContext(
73+
new ViewHelperContext(
74+
$this->renderingContext,
75+
$this->arguments
76+
)
77+
);
78+
79+
$this->tag->addAttribute('href', $uri);
80+
$this->tag->setContent($this->renderChildren());
81+
$this->tag->forceClosingTag(true);
82+
83+
return $this->tag->render();
84+
}
85+
}

Classes/ViewHelpers/Uri/ActionViewHelper.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
use Helhum\TyposcriptRendering\Uri\TyposcriptRenderingUri;
1818
use Helhum\TyposcriptRendering\Uri\ViewHelperContext;
19+
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
1920
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
2021
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
2122

2223
/**
23-
* A view helper for creating Ajax URIs to extbase actions.
24+
* A view helper for creating URIs to render individual extbase actions.
2425
*
2526
* = Examples =
2627
*
@@ -32,7 +33,7 @@
3233
* (depending on the current page and your TS configuration)
3334
* </output>
3435
*/
35-
class ActionViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
36+
class ActionViewHelper extends AbstractViewHelper
3637
{
3738
use CompileWithRenderStatic;
3839

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
declare(strict_types=1);
3+
namespace Helhum\TyposcriptRendering\ViewHelpers\Uri;
4+
5+
/*
6+
* This file is part of the TypoScript Rendering TYPO3 extension.
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
13+
* LICENSE file that was distributed with this source code.
14+
*
15+
*/
16+
17+
use Helhum\TyposcriptRendering\Uri\TyposcriptRenderingUri;
18+
use Helhum\TyposcriptRendering\Uri\ViewHelperContext;
19+
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
20+
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
21+
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
22+
23+
/**
24+
* A view helper for creating URIs to render arbitrary TypoScript objects.
25+
*
26+
* = Examples =
27+
*
28+
* <code title="URI to the given rendering path">
29+
* <t:uri.cObject renderingPath="lib.userProfile"/>
30+
* </code>
31+
* <output>
32+
* index.php?id=123&tx_typoscriptrendering[context]={"record":"tt_content_123","path":"lib.userProfile"}&cHash=xyz
33+
* (depending on the current page and your TS configuration)
34+
* </output>
35+
*/
36+
class CObjectViewHelper extends AbstractViewHelper
37+
{
38+
use CompileWithRenderStatic;
39+
40+
/**
41+
* Initialize arguments
42+
*
43+
* @api
44+
*/
45+
public function initializeArguments()
46+
{
47+
$this->registerArgument('typoscriptObjectPath', 'string', 'TypoScript rendering path');
48+
$this->registerArgument('contextRecord', 'string', 'The record that the rendering should depend upon. e.g. current (default: record is fetched from current Extbase plugin), tt_content:12 (tt_content record with uid 12), pages:15 (pages record with uid 15), \'currentPage\' record of current page', false, 'current');
49+
$this->registerArgument('pageUid', 'int', 'Target page. See TypoLink destination');
50+
$this->registerArgument('pageType', 'int', 'Type of the target page. See typolink.parameter', false, 0);
51+
$this->registerArgument('noCache', 'bool', 'Set this to disable caching for the target page. You should not need this.', false, false);
52+
$this->registerArgument('section', 'string', 'The anchor to be added to the URI', false, '');
53+
$this->registerArgument('format', 'string', 'The requested format, e.g. ".html', false, '');
54+
$this->registerArgument('linkAccessRestrictedPages', 'bool', 'If set, links pointing to access restricted pages will still link to the page even though the page cannot be accessed.', false, false);
55+
$this->registerArgument('additionalParams', 'array', 'additional query parameters that won\'t be prefixed like $arguments (overrule $arguments)', false, []);
56+
$this->registerArgument('absolute', 'bool', 'If set, an absolute URI is rendered', false, false);
57+
$this->registerArgument('addQueryString', 'bool', 'If set, the current query parameters will be kept in the URI', false, false);
58+
$this->registerArgument('argumentsToBeExcludedFromQueryString', 'array', 'arguments to be removed from the URI. Only active if $addQueryString = TRUE', false, []);
59+
$this->registerArgument('addQueryStringMethod', 'string', 'Set which parameters will be kept. Only active if $addQueryString = TRUE');
60+
}
61+
62+
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
63+
{
64+
$uri = (new TyposcriptRenderingUri())->withViewHelperContext(
65+
new ViewHelperContext(
66+
$renderingContext,
67+
$arguments
68+
)
69+
);
70+
71+
return (string)$uri;
72+
}
73+
}

Tests/Functional/Fixtures/Frontend/Basic.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,27 @@ lib.link {
2626
parameter = 1
2727
}
2828
}
29+
lib.foo = TEXT
30+
lib.foo.value = FOO
2931

3032
lib.fluid = FLUIDTEMPLATE
3133
lib.fluid.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/Template.html
3234

3335
lib.viewHelper = FLUIDTEMPLATE
3436
lib.viewHelper.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/ViewHelperTemplate.html
37+
3538
lib.linkViewHelper = FLUIDTEMPLATE
3639
lib.linkViewHelper.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/LinkViewHelperTemplate.html
40+
41+
lib.cObjectUriViewHelper = FLUIDTEMPLATE
42+
lib.cObjectUriViewHelper.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/CObjectUriViewHelperTemplate.html
43+
44+
lib.cObjectLinkViewHelper = FLUIDTEMPLATE
45+
lib.cObjectLinkViewHelper.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/CObjectLinkViewHelperTemplate.html
46+
3747
lib.oldViewHelper = FLUIDTEMPLATE
3848
lib.oldViewHelper.file = EXT:typoscript_rendering/Tests/Functional/Fixtures/Frontend/OldViewHelperTemplate.html
49+
3950
tt_content.typoscriptrendering_plugintest.20 = TEXT
4051

4152
page = PAGE
@@ -51,7 +62,6 @@ page {
5162
}
5263

5364

54-
5565
[globalVar = GP:L = 1]
5666
config.sys_language_uid = 1
5767
[end]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html xmlns="http://www.w3.org/1999/xhtml"
2+
xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
3+
xmlns:t="http://typo3.org/ns/Helhum/TyposcriptRendering/ViewHelpers"
4+
data-namespace-typo3-fluid="true">
5+
<t:link.cObject typoscriptObjectPath="lib.foo" contextRecord="currentPage">Link</t:link.cObject>
6+
</html>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html xmlns="http://www.w3.org/1999/xhtml"
2+
xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
3+
xmlns:t="http://typo3.org/ns/Helhum/TyposcriptRendering/ViewHelpers"
4+
data-namespace-typo3-fluid="true">
5+
<t:uri.cObject typoscriptObjectPath="lib.foo" contextRecord="currentPage"/>
6+
</html>

Tests/Functional/RenderingTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ public function viewHelperOutputsUri()
4747
$this->assertSame($expectedContent, $actualContentWithoutCHash);
4848
}
4949

50+
/**
51+
* @test
52+
*/
53+
public function cObjectUriViewHelperOutputsUri()
54+
{
55+
$requestArguments = ['url' => $this->getRenderUrl(1, 1, 'lib.cObjectUriViewHelper')];
56+
$actualContentWithoutCHash = preg_replace('/&amp;cHash=[a-z0-9]*/', '', trim($this->fetchFrontendResponse($requestArguments)->getContent()));
57+
$expectedContent = '/index.php?id=1&amp;L=1&amp;tx_typoscriptrendering%5Bcontext%5D=%7B%22record%22%3A%22pages_1%22%2C%22path%22%3A%22lib.foo%22%7D';
58+
$this->assertSame($expectedContent, $actualContentWithoutCHash);
59+
}
60+
61+
/**
62+
* @test
63+
*/
64+
public function cObjectLinkViewHelperOutputsUri()
65+
{
66+
$requestArguments = ['url' => $this->getRenderUrl(1, 1, 'lib.cObjectLinkViewHelper')];
67+
$actualContentWithoutCHash = preg_replace('/&amp;cHash=[a-z0-9]*/', '', trim($this->fetchFrontendResponse($requestArguments)->getContent()));
68+
$expectedContent = '<a href="/index.php?id=1&amp;L=1&amp;tx_typoscriptrendering%5Bcontext%5D=%7B%22record%22%3A%22pages_1%22%2C%22path%22%3A%22lib.foo%22%7D">Link</a>';
69+
$this->assertSame($expectedContent, $actualContentWithoutCHash);
70+
}
71+
5072
/**
5173
* @test
5274
*/

0 commit comments

Comments
 (0)