263 lines
10 KiB
PHP
263 lines
10 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
@date_default_timezone_set('Europe/Paris');
|
||
|
||
function site_asset_version(): string
|
||
{
|
||
static $version = null;
|
||
if ($version !== null) {
|
||
return $version;
|
||
}
|
||
|
||
$paths = [
|
||
__DIR__ . '/assets/css/custom.css',
|
||
__DIR__ . '/assets/js/main.js',
|
||
];
|
||
|
||
$mtime = 0;
|
||
foreach ($paths as $path) {
|
||
if (is_file($path)) {
|
||
$mtime = max($mtime, (int) filemtime($path));
|
||
}
|
||
}
|
||
|
||
$version = (string) ($mtime ?: time());
|
||
return $version;
|
||
}
|
||
|
||
function site_settings(): array
|
||
{
|
||
static $settings = null;
|
||
if ($settings !== null) {
|
||
return $settings;
|
||
}
|
||
|
||
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||
$host = $_SERVER['HTTP_HOST'] ?? 'programmetelecesoir.fr';
|
||
|
||
$settings = [
|
||
'domain' => 'programmetelecesoir.fr',
|
||
'project_name' => $_SERVER['PROJECT_NAME'] ?? 'programmetelecesoir.fr',
|
||
'project_description' => $_SERVER['PROJECT_DESCRIPTION'] ?? '',
|
||
'project_image_url' => $_SERVER['PROJECT_IMAGE_URL'] ?? '',
|
||
'base_url' => $scheme . '://' . $host,
|
||
'asset_version' => site_asset_version(),
|
||
'owner_name' => 'M LORENTE CHRISTOPHE',
|
||
'dpo_name' => 'M LORENTE CHRISTOPHE',
|
||
'dpo_address' => '7 rue Lucien Deneau – 28300 Mainvilliers',
|
||
'dpo_phone' => '06 58 22 59 16',
|
||
'host_name' => 'FLATLOGIC.COM',
|
||
];
|
||
|
||
return $settings;
|
||
}
|
||
|
||
function e(mixed $value): string
|
||
{
|
||
return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||
}
|
||
|
||
function site_current_path(): string
|
||
{
|
||
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
|
||
$path = strtok($requestUri, '?');
|
||
return $path !== false && $path !== '' ? $path : '/';
|
||
}
|
||
|
||
function site_asset_url(string $relativePath): string
|
||
{
|
||
return $relativePath . '?v=' . rawurlencode(site_asset_version());
|
||
}
|
||
|
||
function render_site_head(string $pageTitle, string $fallbackDescription, string $keywords = '', bool $noindex = false): void
|
||
{
|
||
$site = site_settings();
|
||
$projectDescription = $site['project_description'];
|
||
$projectImageUrl = $site['project_image_url'];
|
||
$canonical = $site['base_url'] . site_current_path();
|
||
?>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title><?= e($pageTitle) ?></title>
|
||
<?php if ($projectDescription): ?>
|
||
<meta name="description" content="<?= e($projectDescription) ?>" />
|
||
<meta property="og:description" content="<?= e($projectDescription) ?>" />
|
||
<meta property="twitter:description" content="<?= e($projectDescription) ?>" />
|
||
<?php else: ?>
|
||
<meta name="description" content="<?= e($fallbackDescription) ?>" />
|
||
<meta property="og:description" content="<?= e($fallbackDescription) ?>" />
|
||
<meta property="twitter:description" content="<?= e($fallbackDescription) ?>" />
|
||
<?php endif; ?>
|
||
<?php if ($projectImageUrl): ?>
|
||
<meta property="og:image" content="<?= e($projectImageUrl) ?>" />
|
||
<meta property="twitter:image" content="<?= e($projectImageUrl) ?>" />
|
||
<?php endif; ?>
|
||
<?php if ($keywords !== ''): ?>
|
||
<meta name="keywords" content="<?= e($keywords) ?>" />
|
||
<?php endif; ?>
|
||
<meta name="author" content="<?= e($site['owner_name']) ?>" />
|
||
<meta name="theme-color" content="#111827" />
|
||
<meta property="og:title" content="<?= e($pageTitle) ?>" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="<?= e($canonical) ?>" />
|
||
<meta property="twitter:card" content="summary_large_image" />
|
||
<link rel="canonical" href="<?= e($canonical) ?>" />
|
||
<?php if ($noindex): ?>
|
||
<meta name="robots" content="noindex, nofollow" />
|
||
<?php else: ?>
|
||
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
|
||
<?php endif; ?>
|
||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
||
<link rel="stylesheet" href="<?= e(site_asset_url('assets/css/custom.css')) ?>">
|
||
<?php
|
||
}
|
||
|
||
function nav_link(string $label, string $href, bool $active = false, bool $sectionLink = false): string
|
||
{
|
||
$className = 'nav-link';
|
||
if ($active) {
|
||
$className .= ' active';
|
||
}
|
||
|
||
$dataAttr = $sectionLink ? ' data-section-link="1"' : '';
|
||
$current = $active ? ' aria-current="page"' : '';
|
||
return '<a class="' . e($className) . '" href="' . e($href) . '"' . $current . $dataAttr . '>' . e($label) . '</a>';
|
||
}
|
||
|
||
function render_site_nav(string $current = 'home'): void
|
||
{
|
||
?>
|
||
<header class="site-header">
|
||
<nav class="navbar navbar-expand-lg navbar-light">
|
||
<div class="container">
|
||
<a class="navbar-brand" href="/">programmetelecesoir.fr</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNavbar" aria-controls="mainNavbar" aria-expanded="false" aria-label="Afficher la navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="mainNavbar">
|
||
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-1">
|
||
<li class="nav-item"><?= nav_link('En ce moment', '/#widget-section', $current === 'home', true) ?></li>
|
||
<li class="nav-item"><?= nav_link('Guide TV', '/#guide', false, true) ?></li>
|
||
<li class="nav-item"><?= nav_link('Chaînes', '/#chaines', false, true) ?></li>
|
||
<li class="nav-item"><?= nav_link('FAQ', '/#faq', false, true) ?></li>
|
||
<li class="nav-item"><?= nav_link('Cookies', '/politique-cookies.php', $current === 'cookies') ?></li>
|
||
<li class="nav-item"><?= nav_link('Confidentialité', '/politique-confidentialite.php', $current === 'privacy') ?></li>
|
||
<li class="nav-item"><?= nav_link('Règlement', '/reglement.php', $current === 'rules') ?></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
<?php
|
||
}
|
||
|
||
function render_site_footer(): void
|
||
{
|
||
$site = site_settings();
|
||
?>
|
||
<footer class="site-footer">
|
||
<div class="container">
|
||
<div class="footer-grid">
|
||
<div>
|
||
<div class="footer-brand">programmetelecesoir.fr</div>
|
||
<p class="footer-copy">Guide éditorial et page d'accès rapide au programme TV ce soir, au direct en ce moment et aux principales chaînes TNT.</p>
|
||
</div>
|
||
<div>
|
||
<div class="footer-title">Documents</div>
|
||
<ul class="footer-links list-unstyled mb-0">
|
||
<li><a href="/politique-cookies.php">Politique de cookies</a></li>
|
||
<li><a href="/politique-confidentialite.php">Politique de confidentialité</a></li>
|
||
<li><a href="/reglement.php">Règlement d'utilisation</a></li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<div class="footer-title">DPO & contact</div>
|
||
<address class="footer-copy mb-0">
|
||
<?= e($site['dpo_name']) ?><br>
|
||
<?= e($site['dpo_address']) ?><br>
|
||
Tél. <?= e($site['dpo_phone']) ?>
|
||
</address>
|
||
</div>
|
||
<div>
|
||
<div class="footer-title">Hébergement</div>
|
||
<p class="footer-copy mb-0">Hébergeur déclaré : <?= e($site['host_name']) ?>.</p>
|
||
<button type="button" class="link-button mt-2" id="footer-cookie-settings">Revoir mon choix cookies</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<?php
|
||
}
|
||
|
||
function render_cookie_controls(): void
|
||
{
|
||
?>
|
||
<div class="cookie-floating">
|
||
<button type="button" class="cookie-reopen" id="cookie-reopen" aria-controls="cookie-banner" aria-expanded="false">
|
||
<span class="cookie-reopen__dot" aria-hidden="true"></span>
|
||
<span id="cookie-reopen-label">Cookies : essentiels</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="cookie-banner" id="cookie-banner" hidden>
|
||
<div class="cookie-banner__top">
|
||
<div>
|
||
<p class="cookie-banner__eyebrow mb-2">Préférences cookies</p>
|
||
<h2 class="cookie-banner__title">Gérez votre confidentialité</h2>
|
||
</div>
|
||
</div>
|
||
<p class="cookie-banner__intro">Le widget TV nécessaire au service reste actif pour afficher le programme en temps réel. Les traceurs optionnels sont désactivés par défaut tant que vous n'avez pas choisi.</p>
|
||
<div class="cookie-banner__toggles">
|
||
<div class="cookie-switch-row">
|
||
<div>
|
||
<strong>Essentiels</strong>
|
||
<p>Conservent votre choix de consentement et la sécurité minimale du site.</p>
|
||
</div>
|
||
<div class="form-check form-switch m-0">
|
||
<input class="form-check-input" type="checkbox" role="switch" id="cookie-essential" checked disabled>
|
||
</div>
|
||
</div>
|
||
<div class="cookie-switch-row">
|
||
<div>
|
||
<label class="cookie-switch-label" for="cookie-personalization">Personnalisation</label>
|
||
<p>Mémorise vos préférences d'interface sur cet appareil, comme le rappel de lecture mobile.</p>
|
||
</div>
|
||
<div class="form-check form-switch m-0">
|
||
<input class="form-check-input" type="checkbox" role="switch" id="cookie-personalization" data-consent-control="personalization">
|
||
</div>
|
||
</div>
|
||
<div class="cookie-switch-row">
|
||
<div>
|
||
<label class="cookie-switch-label" for="cookie-audience">Mesure locale d'audience</label>
|
||
<p>Active un simple compteur local dans votre navigateur, sans service tiers ni publicité.</p>
|
||
</div>
|
||
<div class="form-check form-switch m-0">
|
||
<input class="form-check-input" type="checkbox" role="switch" id="cookie-audience" data-consent-control="audience">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cookie-banner__actions">
|
||
<button type="button" class="btn btn-light btn-refined" data-cookie-action="reject">Continuer sans accepter</button>
|
||
<button type="button" class="btn btn-outline-dark btn-refined" data-cookie-action="save">Enregistrer mes choix</button>
|
||
<button type="button" class="btn btn-dark btn-refined" data-cookie-action="accept">Tout accepter</button>
|
||
</div>
|
||
<div class="cookie-banner__links">
|
||
<a href="/politique-cookies.php">Voir la politique de cookies</a>
|
||
<span aria-hidden="true">•</span>
|
||
<a href="/politique-confidentialite.php">Confidentialité</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast-stack" id="toast-stack" aria-live="polite" aria-atomic="true"></div>
|
||
<?php
|
||
}
|
||
|
||
function render_site_scripts(): void
|
||
{
|
||
?>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" defer></script>
|
||
<script src="<?= e(site_asset_url('assets/js/main.js')) ?>" defer></script>
|
||
<?php
|
||
}
|