Commit b72d3fd5 authored by Benni Mack's avatar Benni Mack
Browse files

[BUGFIX] TypoLink is executed fully without href attribute

In #87992 an early return was added to have <a> tags
with just an "id" or "name" attribute. This is all nice,
but when used further typolink settings (such as userFunc
or custom "title"), these options were never run.

This change now uses typolink() natively again and
removes the introduced "resolveAnchorLinK" workaround.

Added tests show that additional attributes are executed
and links without href are actually created (was previously
untested).

Resolves: #96464
Related: #87992
Releases: main, 11.5
Change-Id: I67d4090228684fc89f72bc3d6367109437040ccf
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72894

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 1c589463
......@@ -4583,17 +4583,27 @@ class ContentObjectRenderer implements LoggerAwareInterface
$target = $resolvedLinkParameters['target'];
$title = $resolvedLinkParameters['title'];
$linkDetails = [];
if (!$linkParameter) {
return $this->resolveAnchorLink($linkText, $conf ?? []);
}
// Detecting kind of link and resolve all necessary parameters
$linkService = GeneralUtility::makeInstance(LinkService::class);
try {
$linkDetails = $linkService->resolve($linkParameter);
} catch (UnknownLinkHandlerException | InvalidPathException $exception) {
$this->logger->warning('The link could not be generated', ['exception' => $exception]);
return $linkText;
// Support anchors without href value if id or name attribute is present.
$aTagParams = (string)$this->stdWrapValue('ATagParams', $conf ?? []);
$aTagParams = GeneralUtility::get_tag_attributes($aTagParams);
// If it looks like an anchor tag, render it anyway
if (isset($aTagParams['id']) || isset($aTagParams['name'])) {
$linkDetails = [
'type' => 'inpage',
'url' => '',
];
}
} else {
// Detecting kind of link and resolve all necessary parameters
$linkService = GeneralUtility::makeInstance(LinkService::class);
try {
$linkDetails = $linkService->resolve($linkParameter);
} catch (UnknownLinkHandlerException | InvalidPathException $exception) {
$this->logger->warning('The link could not be generated', ['exception' => $exception]);
return $linkText;
}
}
$linkDetails['typoLinkParameter'] = $linkParameter;
......@@ -6466,27 +6476,6 @@ class ContentObjectRenderer implements LoggerAwareInterface
return $this->typoScriptFrontendController ?: $GLOBALS['TSFE'] ?? null;
}
/**
* Support anchors without href value
* Changes ContentObjectRenderer::typolink to render a tag without href,
* if id or name attribute is present.
*
* @param string $linkText
* @param array $conf Typolink configuration decoded as array
* @return string Full a-Tag or just the linktext if id or name are not set.
*/
protected function resolveAnchorLink(string $linkText, array $conf): string
{
$anchorTag = '<a ' . $this->getATagParams($conf) . '>';
$aTagParams = GeneralUtility::get_tag_attributes($anchorTag);
// If it looks like a anchor tag, render it anyway
if (isset($aTagParams['id']) || isset($aTagParams['name'])) {
return $anchorTag . $linkText . '</a>';
}
// Otherwise just return the link text
return $linkText;
}
/**
* Get content length of the current tag that could also contain nested tag contents
*
......
......@@ -627,6 +627,62 @@ class TypoLinkGeneratorTest extends AbstractTestCase
self::assertSame($expectation, (string)$response->getBody());
}
public function linkWithoutAnchorIsGeneratedDataProvider(): array
{
return [
'empty parameter does not create a link' => [
[
'parameter' => '',
],
'no link',
'no link',
],
'empty parameter with additional ATagParams does not create a link' => [
[
'parameter' => '',
'ATagParams' => 'data-any="where"',
],
'no link',
'no link',
],
'empty parameter with additional ATagParams with id creates a link' => [
[
'parameter' => '',
'ATagParams' => 'id="c13" data-any="where"',
],
'a link',
'<a id="c13" data-any="where">a link</a>',
],
'empty parameter with additional ATagParams with id creates a link and adds title' => [
[
'parameter' => '',
'ATagParams' => 'id="c13" data-any="where"',
'title' => 'custom title',
],
'a link',
'<a title="custom title" id="c13" data-any="where">a link</a>',
],
];
}
/**
* @test
* @dataProvider linkWithoutAnchorIsGeneratedDataProvider
*/
public function linkWithoutAnchorIsGenerated(array $instructions, string $linkText, string $expectation): void
{
$sourcePageId = 1100;
$request = (new InternalRequest('https://acme.us/'))
->withPageId($sourcePageId)
->withInstructions(
[
$this->createTypoLinkInstruction($instructions, $linkText),
]
);
$response = $this->executeFrontendSubRequest($request);
self::assertSame($expectation, (string)$response->getBody());
}
/**
* @param string $parameter
* @param AbstractInstruction ...$instructions
......
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