Created
January 6, 2024 15:48
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
return [ | |
'frontend' => [ | |
'yourvendor/webmanifest' => [ | |
'target' => \YourVendor\Sitepackage\Middleware\Webmanifest::class, | |
'before' => [ | |
'typo3/cms-frontend/page-resolver', | |
], | |
'after' => [ | |
'typo3/cms-frontend/site', | |
], | |
], | |
], | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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