feat(ViteAssetExtension): Ajoute la gestion des favicons et améliore la gestion des scripts.

⚙️ chore(pwa): Met à jour le nom et l'URL de démarrage du PWA.
```
This commit is contained in:
Serreau Jovann
2026-01-22 22:21:13 +01:00
parent ccf1c3c042
commit ed924a3b04
2 changed files with 35 additions and 56 deletions

View File

@@ -30,9 +30,9 @@ pwa:
max_age: 3600
manifest:
enabled: true
name: "Intranet Lukikevent"
short_name: "Intranet"
start_url: "app_home"
name: "Réservation Lukikevent"
short_name: "Réservation Lukikevent"
start_url: "reservation"
display: "standalone"
background_color: "#ffffff"
theme_color: "#f4c842"

View File

@@ -1,20 +1,16 @@
<?php
declare(strict_types=1);
namespace App\Twig;
use Detection\MobileDetect;
use Jaybizzle\CrawlerDetect\CrawlerDetect;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Nelmio\SecurityBundle\EventListener\ContentSecurityPolicyListener;
class ViteAssetExtension extends AbstractExtension
{
private const CACHE_KEY = 'vite_manifest';
const CACHE_KEY = 'vite_manifest';
private ?array $manifestData = null;
private readonly bool $isDev;
@@ -22,9 +18,8 @@ class ViteAssetExtension extends AbstractExtension
private readonly string $manifest,
private readonly CacheItemPoolInterface $cache,
private readonly ContentSecurityPolicyListener $cspListener,
private readonly RequestStack $requestStack,
) {
$this->isDev = ($_ENV['VITE_LOAD'] ?? "1") === "0";
$this->isDev = $_ENV['VITE_LOAD'] === "0";
}
public function getFunctions(): array
@@ -32,29 +27,25 @@ class ViteAssetExtension extends AbstractExtension
return [
new TwigFunction('vite_asset', $this->asset(...), ['is_safe' => ['html']]),
new TwigFunction('isMobile', $this->isMobile(...), ['is_safe' => ['html']]),
new TwigFunction('vite_favicons', $this->favicons(...), ['is_safe' => ['html']])
];
}
/**
* Récupère le nonce pour les scripts via le Listener de Nelmio
*/
private function getNonce(): string
{
// Dans la v3.8, on utilise getNonce('script') sur le listener
return $this->cspListener->getNonce('script');
}
public function isMobile(): bool
{
$detect = new MobileDetect();
return $detect->isMobile() || $detect->isTablet();
}
private function isBot(): bool
{
$request = $this->requestStack->getCurrentRequest();
if (!$request) return false;
$crawlerDetect = new CrawlerDetect($request->headers->all());
return $crawlerDetect->isCrawler();
}
private function getNonce(): string
{
return $this->cspListener->getNonce('script');
}
private function loadManifest(): void
{
if ($this->manifestData === null) {
@@ -91,47 +82,35 @@ HTML;
{
$this->loadManifest();
$nonce = $this->getNonce();
$isBot = $this->isBot();
$entryData = $this->manifestData[$entry] ?? null;
if (!$entryData) return '';
$file = $this->manifestData[$entry]['file'] ?? '';
$css = $this->manifestData[$entry]['css'] ?? [];
$file = $entryData['file'];
$css = $entryData['css'] ?? [];
$imports = $entryData['imports'] ?? []; // Les fichiers JS secondaires (chunks)
$html = '';
// 1. On charge le fichier JS principal (ex: reserve.js)
$html .= <<<HTML
$html = <<<HTML
<script type="module" src="/build/{$file}" crossorigin="anonymous" nonce="{$nonce}" defer></script>
HTML;
// 2. On traite les imports (chunks comme Sentry BrowserTracing)
foreach ($imports as $importKey) {
$importData = $this->manifestData[$importKey] ?? null;
if (!$importData) continue;
$importFile = $importData['file'];
// LOGIQUE DE FILTRAGE :
// Si c'est un bot ET que le fichier contient "browserTracing" dans son nom d'origine
if ($isBot && str_contains($importKey, 'browserTracingIntegration')) {
$html .= "";
continue;
}
// Sinon on l'ajoute normalement
$html .= <<<HTML
<link rel="modulepreload" href="/build/{$importFile}" nonce="{$nonce}">
HTML;
}
// 3. On ajoute le CSS
foreach ($css as $cssFile) {
$html .= '<link rel="stylesheet" href="/build/'.$cssFile.'" crossorigin="anonymous"/>';
}
return $html;
}
public function favicons(): string
{
return $this->isDev ? '<link rel="icon" href="/favicon.ico">' : $this->faviconsProd();
}
private function faviconsProd(): string
{
$this->loadManifest();
$faviconHtml = "";
foreach ($this->manifestData as $key => $favicon) {
if(!str_contains($key, ".js") && isset($favicon['file'])) {
$faviconHtml .= '<link rel="icon" href="/build/'.$favicon['file'].'" type="image/x-icon">';
}
}
return $faviconHtml;
}
}