Skip to content

Commit b6938f0

Browse files
committed
[FEATURE] Add support for config.htmlTag & page.bodyTagAdd
- By default generate language attributes for html tag based on current language page, so nuxt does not have done it manually - support custom attributes like `config.htmlTag.attributes.class = no-js` with option to override default attributes - Add support for setting body tag attributes via `page.bodyTagAdd` Typoscript directive, so frontend app can automatically apply it via nuxt feature
1 parent eaf2010 commit b6938f0

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

Classes/Seo/MetaHandler.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
use Psr\EventDispatcher\EventDispatcherInterface;
1616
use Psr\Http\Message\ServerRequestInterface;
1717
use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
18+
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
1819
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
1920
use TYPO3\CMS\Core\Utility\GeneralUtility;
2021
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
2122
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
2223
use TYPO3\CMS\Frontend\Event\ModifyHrefLangTagsEvent;
2324

25+
use function htmlspecialchars;
26+
2427
class MetaHandler
2528
{
2629
public function __construct(
@@ -69,6 +72,26 @@ public function process(ServerRequestInterface $request, TypoScriptFrontendContr
6972
$content['seo']['link'] = $seoLinks;
7073
}
7174

75+
/**
76+
* @var SiteLanguage $language
77+
*/
78+
$language = $request->getAttribute('language');
79+
80+
$rawHtmlTagAttrs = $controller->config['config']['htmlTag.']['attributes.'] ?? [];
81+
$htmlTagAttrs = $this->normalizeAttr($rawHtmlTagAttrs);
82+
83+
$rawBodyTagAttrs = GeneralUtility::get_tag_attributes(trim($request->getAttribute('frontend.typoscript')->getSetupArray()['page.']['bodyTagAdd'] ?? ''));
84+
$bodyTagAttrs = $this->normalizeAttr($rawBodyTagAttrs);
85+
86+
$content['seo']['htmlAttrs'] = array_merge([
87+
'lang' => $language->getLocale()->getLanguageCode(),
88+
'dir' => $language->getLocale()->isRightToLeftLanguageDirection() ? 'rtl' : null,
89+
], $htmlTagAttrs);
90+
91+
if ($bodyTagAttrs !== []) {
92+
$content['seo']['bodyAttrs'] = $bodyTagAttrs;
93+
}
94+
7295
return $content;
7396
}
7497

@@ -130,4 +153,17 @@ private function setMetaTag(string $type, string $name, string $content, array $
130153
$manager = $this->metaTagRegistry->getManagerForProperty($name);
131154
$manager->addProperty($name, $content, $subProperties, $replace, $type);
132155
}
156+
157+
/**
158+
* @codeCoverageIgnore
159+
*/
160+
private function normalizeAttr(array $rawHtmlAttrs): array
161+
{
162+
$htmlAttrs = [];
163+
164+
foreach ($rawHtmlAttrs as $attr => $value) {
165+
$htmlAttrs[htmlspecialchars((string)$attr)] = htmlspecialchars((string)$value);
166+
}
167+
return $htmlAttrs;
168+
}
133169
}

Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
2626
use TYPO3\CMS\Core\EventDispatcher\ListenerProvider;
2727
use TYPO3\CMS\Core\Http\ServerRequest;
28+
use TYPO3\CMS\Core\Http\Uri;
2829
use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
30+
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
31+
use TYPO3\CMS\Core\TypoScript\AST\Node\RootNode;
32+
use TYPO3\CMS\Core\TypoScript\FrontendTypoScript;
2933
use TYPO3\CMS\Core\Utility\GeneralUtility;
3034
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
3135
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
@@ -128,6 +132,19 @@ public function testModifiedPageTitle(): void
128132

129133
$request = $this->prophesize(ServerRequestInterface::class);
130134
$request->getAttribute(Argument::is('headless'))->willReturn(new Headless(HeadlessMode::FULL));
135+
$request->getAttribute(Argument::is('language'))->willReturn(new SiteLanguage(
136+
0,
137+
'en',
138+
new Uri('/en'),
139+
[]
140+
));
141+
142+
$frontendTyposcript = new FrontendTypoScript(new RootNode(), [], [], []);
143+
$frontendTyposcript->setSetupTree(new RootNode());
144+
$frontendTyposcript->setSetupArray([]);
145+
146+
$request->getAttribute(Argument::is('frontend.typoscript'))->willReturn($frontendTyposcript);
147+
131148
$controller = $this->prophesize(TypoScriptFrontendController::class);
132149
$controller->content = json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'test before event']]);
133150
$controller->cObj = $this->prophesize(ContentObjectRenderer::class)->reveal();
@@ -137,7 +154,7 @@ public function testModifiedPageTitle(): void
137154

138155
$listener($event);
139156

140-
self::assertSame(json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'Modified title via PageTitleProviderManager', 'meta' => []]]), $event->getController()->content);
157+
self::assertSame(json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'Modified title via PageTitleProviderManager', 'meta' => [], 'htmlAttrs' => ['lang' => 'en', 'dir' => null]]]), $event->getController()->content);
141158
}
142159

143160
public function testHreflangs(): void
@@ -158,6 +175,19 @@ public function testHreflangs(): void
158175

159176
$request = $this->prophesize(ServerRequestInterface::class);
160177
$request->getAttribute(Argument::is('headless'))->willReturn(new Headless(HeadlessMode::FULL));
178+
$request->getAttribute(Argument::is('language'))->willReturn(new SiteLanguage(
179+
0,
180+
'en',
181+
new Uri('/en'),
182+
[]
183+
));
184+
185+
$frontendTyposcript = new FrontendTypoScript(new RootNode(), [], [], []);
186+
$frontendTyposcript->setSetupTree(new RootNode());
187+
$frontendTyposcript->setSetupArray([]);
188+
189+
$request->getAttribute(Argument::is('frontend.typoscript'))->willReturn($frontendTyposcript);
190+
161191
$GLOBALS['TYPO3_REQUEST'] = $request->reveal();
162192
$controller = $this->prophesize(TypoScriptFrontendController::class);
163193
$controller->content = json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'test before event']]);
@@ -184,6 +214,6 @@ public function handle(): void {}
184214
['rel' => 'alternate', 'hreflang' => 'pl-PL', 'href' => 'https://example.com/pl'],
185215
['rel' => 'alternate', 'hreflang' => 'en-US', 'href' => 'https://example.com/us'],
186216
['rel' => 'alternate', 'hreflang' => 'en-UK', 'href' => 'https://example.com/uk'],
187-
]]]), $event->getController()->content);
217+
], 'htmlAttrs' => ['lang' => 'en', 'dir' => null]]]), $event->getController()->content);
188218
}
189219
}

0 commit comments

Comments
 (0)