Commit ccb1c2c8 authored by Oliver Hader's avatar Oliver Hader Committed by Andreas Fernandez
Browse files

[FEATURE] Expose internal typoLinkParts in TypolinkViewHelper

Parameters being generated internally by TypoLink using
`<f:link.typolink parts-as="typoLinkParts">` view helper are
exposed as variable and can be used in Fluid templates again,
which are:

* url
* target
* class
* title
* additionalParams

Resolves: #90026
Releases: master
Change-Id: I6c3386ed1f177aeb98171056f5d8bd2991d6cf46
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62769


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 893ee207
.. include:: ../../Includes.txt
=====================================================================
Feature: #90026 - Expose internal typoLinkParts in TypolinkViewHelper
=====================================================================
See :issue:`90026`
Description
===========
Parameters being generated internally by TypoLink using
:html:`<f:link.typolink parts-as="typoLinkParts">` view helper are exposed as
variable and can be used in Fluid templates again.
View helper attribute `parts-as` (default `typoLinkParts`) allows to define
variable name to be used containing the following internal parts:
* url
* target
* class
* title
* additionalParams
Details for these internal parts are documented for :ts:`typolink.parameter`
in `TypoScript reference`_
.. _TypoScript reference: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Functions/Typolink.html?highlight=typolink#parameter
Impact
======
Multiple instructions for attribute `parameter` (e.g. persisted to entity
record) can be used individually.
.. code-block: html
<f:link.typolink parameter="123 _top news title" parts-as="parts">
{parts.url}
{parts.target}
{parts.class}
{parts.title}
{parts.additionalParams}
</f:link.typolink>
.. index:: Fluid, Frontend, ext:fluid
......@@ -100,6 +100,7 @@ class TypolinkViewHelper extends AbstractViewHelper
$this->registerArgument('addQueryStringMethod', 'string', '', false, 'GET');
$this->registerArgument('addQueryStringExclude', 'string', '', 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');
}
/**
......@@ -118,6 +119,7 @@ class TypolinkViewHelper extends AbstractViewHelper
trigger_error('Using the argument "useCacheHash" in <f:link.typolink> ViewHelper has no effect anymore. Remove the argument in your fluid template, as it will result in a fatal error.', E_USER_DEPRECATED);
}
$parameter = $arguments['parameter'] ?? '';
$partsAs = $arguments['parts-as'] ?? 'typoLinkParts';
$typoLinkCodec = GeneralUtility::makeInstance(TypoLinkCodecService::class);
$typoLinkConfiguration = $typoLinkCodec->decode($parameter);
......@@ -125,8 +127,14 @@ class TypolinkViewHelper extends AbstractViewHelper
$mergedTypoLinkConfiguration = static::mergeTypoLinkConfiguration($typoLinkConfiguration, $arguments);
$typoLinkParameter = $typoLinkCodec->encode($mergedTypoLinkConfiguration);
// expose internal typoLink configuration to Fluid child context
$variableProvider = $renderingContext->getVariableProvider();
$variableProvider->add($partsAs, $typoLinkConfiguration);
// If no link has to be rendered, the inner content will be returned as such
$content = (string)$renderChildrenClosure();
// clean up exposed variables
$variableProvider->remove($partsAs);
if ($parameter) {
$content = static::invokeContentObjectRenderer($arguments, $typoLinkParameter, $content);
}
......
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:link.typolink parameter="{parameter}"
parts-as="typoLinkParts">Individual {typoLinkParts.target} {typoLinkParts.class} {typoLinkParts.title}</f:link.typolink>
</html>
......@@ -343,4 +343,33 @@ class TypolinkViewHelperTest extends FunctionalTestCase
],
];
}
public function typoLinkPartsAreRenderedDataProvider(): array
{
return [
[
'http://typo3.org/ "_self" "<CSS>" "<Title>"',
'<a href="http://typo3.org/" title="&lt;Title&gt;" target="_self" class="&lt;CSS&gt;">Individual _self &lt;CSS&gt; &lt;Title&gt;</a>',
],
[
'http://typo3.org/ "<Target>" "<CSS>" "<Title>"', // target does not point to "self", adds noreferrer relationship
'<a href="http://typo3.org/" title="&lt;Title&gt;" target="&lt;Target&gt;" class="&lt;CSS&gt;" rel="noreferrer">Individual &lt;Target&gt; &lt;CSS&gt; &lt;Title&gt;</a>',
],
];
}
/**
* @param string $parameter
* @param string $expectation
*
* @test
* @dataProvider typoLinkPartsAreRenderedDataProvider
*/
public function typoLinkPartsAreRendered(string $parameter, string $expectation): void
{
$view = new StandaloneView();
$view->setTemplatePathAndFilename('typo3/sysext/fluid/Tests/Functional/ViewHelpers/Fixtures/link_typolink_parts.html');
$view->assignMultiple(['parameter' => $parameter]);
self::assertSame($expectation, trim($view->render()));
}
}
......@@ -15,11 +15,13 @@ namespace TYPO3\CMS\Fluid\Tests\Unit\ViewHelpers\Link;
* The TYPO3 project - inspiring people to share!
*/
use PHPUnit\Framework\MockObject\MockObject;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\CMS\Fluid\ViewHelpers\Link\TypolinkViewHelper;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\TestingFramework\Fluid\Unit\ViewHelpers\ViewHelperBaseTestcase;
use TYPO3Fluid\Fluid\Core\Variables\VariableProviderInterface;
/**
* Class TypolinkViewHelperTest
......@@ -27,7 +29,7 @@ use TYPO3\TestingFramework\Fluid\Unit\ViewHelpers\ViewHelperBaseTestcase;
class TypolinkViewHelperTest extends ViewHelperBaseTestcase
{
/**
* @var TypolinkViewHelper|\PHPUnit\Framework\MockObject\MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
* @var TypolinkViewHelper|MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
*/
protected $subject;
......@@ -37,8 +39,11 @@ class TypolinkViewHelperTest extends ViewHelperBaseTestcase
protected function setUp(): void
{
$this->subject = $this->getAccessibleMock(TypolinkViewHelper::class, ['renderChildren']);
/** @var RenderingContext $renderingContext */
/** @var VariableProviderInterface|MockObject $variableProvider */
$variableProvider = $this->getMockBuilder(VariableProviderInterface::class)->getMock();
/** @var RenderingContext|MockObject $renderingContext */
$renderingContext = $this->getMockBuilder(RenderingContext::class)->disableOriginalConstructor()->getMock();
$renderingContext->expects(self::any())->method('getVariableProvider')->willReturn($variableProvider);
$this->subject->setRenderingContext($renderingContext);
}
......
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