Skip to content

Instantly share code, notes, and snippets.

@sebkln
Created January 6, 2024 15:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebkln/bfc36c0a3fea5d13c3ae8ff710b4c136 to your computer and use it in GitHub Desktop.
Save sebkln/bfc36c0a3fea5d13c3ae8ff710b4c136 to your computer and use it in GitHub Desktop.
Middleware for web manifest in TYPO3 v12. Adjusted version of the solution provided by Kevin Appelt in TYPO3 Slack: https://typo3.slack.com/archives/C025BQLFA/p1680299950579649
# Addition in Site Configuration
webmanifest:
full_name: 'Full name of website'
short_name: 'Short name'
theme_color: '#000000'
favicon_path: 'EXT:sitepackage/Resources/Public/Images/Favicons/'
favicon_192: android-chrome-192x192.png
favicon_512: android-chrome-512x512.png
<?php
return [
'frontend' => [
'yourvendor/webmanifest' => [
'target' => \YourVendor\Sitepackage\Middleware\Webmanifest::class,
'before' => [
'typo3/cms-frontend/page-resolver',
],
'after' => [
'typo3/cms-frontend/site',
],
],
],
];
<?php
namespace YourVendor\Sitepackage\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Resource\Exception\InvalidFileException;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
class Webmanifest implements MiddlewareInterface
{
protected ServerRequestInterface $request;
final const MANIFEST_PATH = '/site.webmanifest';
final const MANIFEST_NAME = 'site.webmanifest';
/**
* @throws InvalidFileException
*/
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$this->request = $request;
if ($this->isWebmanifestRequest()) {
ob_clean();
return (new JsonResponse())->setPayload($this->generateWebmanifest());
}
$this->addWebmanifestToHead();
return $handler->handle($this->request);
}
protected function isWebmanifestRequest(): bool
{
return $this->request->getUri()->getPath() === self::MANIFEST_PATH;
}
protected function addWebmanifestToHead(): void
{
$siteUrl = $this->request->getAttribute('normalizedParams')->getSiteUrl();
$headerData = '<link rel="manifest" href="' . $siteUrl . self::MANIFEST_NAME . '">';
GeneralUtility::makeInstance(PageRenderer::class)->addHeaderData($headerData);
}
/**
* @return array{background_color: string, display: string, icons: never[]|array<int, array{src: mixed, type: string, sizes: string}>, name?: mixed, short_name?: string, theme_color?: mixed}
* @throws InvalidFileException
*/
protected function generateWebmanifest(): array
{
$siteConfig = $this->getSiteConfig();
$webmanifest = [
'background_color' => '#ffffff',
'display' => 'browser',
'icons' => [],
];
$name = $siteConfig['fullName'] ?? '';
if (!empty($name)) {
$webmanifest['name'] = $name;
}
$shortName = $siteConfig['shortName'] ?? '';
if (!empty($shortName)) {
$webmanifest['short_name'] = $shortName;
}
$themeColor = $siteConfig['themeColor'] ?? '';
if (!empty($themeColor)) {
$webmanifest['theme_color'] = $themeColor;
}
$faviconPath = $siteConfig['faviconPath'] ?? '';
$favicon192 = $siteConfig['favicon192'] ?? '';
$favicon512 = $siteConfig['favicon512'] ?? '';
if (!empty($faviconPath)) {
$icon192 = PathUtility::getPublicResourceWebPath($faviconPath . $favicon192);
if (!empty($icon192)) {
$webmanifest['icons'][] = ['src' => $icon192, 'type' => 'image/png', 'sizes' => '192x192'];
}
$icon512 = PathUtility::getPublicResourceWebPath($faviconPath . $favicon512);
if (!empty($icon512)) {
$webmanifest['icons'][] = ['src' => $icon512, 'type' => 'image/png', 'sizes' => '512x512'];
}
}
return $webmanifest;
}
/**
* @return array{fullName: ?string,shortName: ?string,themeColor: ?string,faviconPath: ?string,favicon192: ?string,favicon512: ?string}
*/
protected function getSiteConfig(): array
{
/** @var Site $site */
$site = $this->request->getAttribute('site');
$configuration = $site->getConfiguration();
return [
'fullName' => $configuration['webmanifest']['full_name'] ?? null,
'shortName' => $configuration['webmanifest']['short_name'] ?? null,
'themeColor' => $configuration['webmanifest']['theme_color'] ?? null,
'faviconPath' => $configuration['webmanifest']['favicon_path'] ?? null,
'favicon192' => $configuration['webmanifest']['favicon_192'] ?? null,
'favicon512' => $configuration['webmanifest']['favicon_512'] ?? null,
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment