Files
maria_uslugi/result_search.php

741 lines
26 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare (strict_types = 1);
require_once __DIR__ . '/../includes/bootstrap_global.php';
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
require_once __DIR__ . '/includes/search_helpers.php';
$currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? '';
// Redirection de la recherche libre vers URL SEO
if (
($currentPath === '/recherche' || $currentPath === '/recherche/' || $currentPath === '/result_search.php')
&& empty($_GET['ajax'])
) {
$qsSpecialite = trim((string) ($_GET['specialite'] ?? ''));
$qsVille = trim((string) ($_GET['ville'] ?? ''));
if ($qsSpecialite !== '' || $qsVille !== '') {
$target = '/recherche';
$specSlug = '';
if ($qsSpecialite === '__OTHERS__') {
$specSlug = 'autres-specialistes';
} elseif ($qsSpecialite !== '') {
$specSlug = seo_spec_slug_from_input($qsSpecialite) ?? '';
}
$citySlug = '';
if ($qsVille !== '') {
$citySlug = seo_city_slug_from_input($qsVille);
}
if ($specSlug !== '') {
$target .= '/' . rawurlencode($specSlug);
}
if ($specSlug !== '') {
if ($citySlug !== '') {
$target .= '/' . rawurlencode($citySlug);
}
$target .= '/';
$extra = $_GET;
unset($extra['specialite'], $extra['ville'], $extra['slug']);
if (! empty($extra)) {
$target .= '?' . http_build_query($extra);
}
if (($_SERVER['REQUEST_URI'] ?? '') !== $target) {
header('Location: ' . $target, true, 301);
exit;
}
} elseif ($citySlug !== '') {
$target = '/recherche/ville/' . rawurlencode($citySlug) . '/';
$extra = $_GET;
unset($extra['specialite'], $extra['ville'], $extra['slug']);
if (! empty($extra)) {
$target .= '?' . http_build_query($extra);
}
if (($_SERVER['REQUEST_URI'] ?? '') !== $target) {
header('Location: ' . $target, true, 301);
exit;
}
}
}
}
$SPEC_CANON = require __DIR__ . '/includes/spec_map.php';
$canon = $SPEC_CANON[$lang] ?? [];
//Ajout 1 pourpraticien_traduction
$currentLang = $lang ?? 'ru';
if (! in_array($currentLang, ['ru', 'fr', 'en'], true)) {
$currentLang = 'ru';
}
// Lecture et normalisation des filtres
$specialiteParam = trim($_GET['specialite'] ?? '');
$ville = trim($_GET['ville'] ?? '');
// 🔑 On garde le slug SEO ici
$resolvedSeoSpecSlug = null;
// Remap de la spécialité URL/texte vers la valeur de recherche
if ($specialiteParam !== '' && $specialiteParam !== '__OTHERS__') {
$seoSpecSlug = seo_spec_slug_from_input($specialiteParam);
if ($seoSpecSlug !== null) {
$resolvedSeoSpecSlug = $seoSpecSlug; // ⭐ IMPORTANT
$searchSpec = seo_spec_search_value_from_slug($seoSpecSlug, $lang);
if ($searchSpec !== null) {
$specialiteParam = $searchSpec;
}
}
}
$H1_LABELS = [
'ru' => [
'avocats' => 'Адвокаты',
'consultants' => 'Консультанты',
'vrachi' => 'Врачи',
'psychologues' => 'Психологи',
'repetitori' => 'Преподаватели',
'finance' => 'Бухгалтеры',
'perevod' => 'Переводчики',
'notarius' => 'Нотариусы',
'gid' => 'Гиды',
'rieltori' => 'Риелторы',
'drugie' => 'Специалисты',
],
'fr' => [
'avocats' => 'Avocats',
'consultants' => 'Consultants',
'vrachi' => 'Médecins',
'psychologues' => 'Psychologues',
'repetitori' => 'Professeurs',
'finance' => 'Comptables',
'perevod' => 'Traducteurs',
'notarius' => 'Notaires',
'gid' => 'Guides',
'rieltori' => 'Agents immobiliers',
'drugie' => 'Spécialistes',
],
];
// Helper detection video
function video_thumb_info(?string $url): ?array
{
if (! $url || ! trim($url)) {
return null;
}
$u = trim($url);
if (preg_match('~(?:youtube\.com/(?:watch\?v=|embed/|shorts/)|youtu\.be/)([A-Za-z0-9_-]{6,})~i', $u, $m)) {
$id = $m[1];
return ['provider' => 'youtube', 'id' => $id, 'thumb' => "https://i.ytimg.com/vi/$id/hqdefault.jpg"];
}
if (preg_match('~dailymotion\.com/video/([A-Za-z0-9]+)|dai\.ly/([A-Za-z0-9]+)~i', $u, $m)) {
$id = $m[1] ?: $m[2];
return ['provider' => 'dailymotion', 'id' => $id, 'thumb' => "https://www.dailymotion.com/thumbnail/video/$id"];
}
$path = parse_url($u, PHP_URL_PATH) ?? '';
if (preg_match('~\.(mp4|webm|ogg)$~i', $path)) {
return ['provider' => 'file', 'id' => null, 'thumb' => null];
}
if (strpos(strtolower($u), 'vimeo.com') !== false) {
return ['provider' => 'vimeo', 'id' => null, 'thumb' => null];
}
return ['provider' => 'other', 'id' => null, 'thumb' => null];
}
// inverse map: canon_value -> key
$canonToKey = [];
foreach (($SPEC_CANON[$lang] ?? []) as $k => $v) {
$canonToKey[mb_strtolower($v, 'UTF-8')] = $k;
}
$inFrance = ($lang === 'fr') ? ' en France' : ' во Франции';
$h1Default = $translations['res_poisk'] ?? 'Результаты поиска';
$h1 = $h1Default;
// Normalisation affichage terme
$sp = trim(str_replace(["\xC2\xA0"], ' ', $specialiteParam));
$sp = preg_replace('/\s+/u', ' ', $sp);
$sp_l = mb_strtolower($sp, 'UTF-8');
if ($specialiteParam === '__OTHERS__') {
$label = $H1_LABELS[$lang]['drugie'] ?? $h1Default;
$h1 = $label . $inFrance;
} elseif (! empty($resolvedSeoSpecSlug)) {
$slugToKey = [
'avocat' => 'avocats',
'consultant' => 'consultants',
'medecin' => 'vrachi',
'psychologue' => 'psychologues',
'professeur' => 'repetitori',
'comptable' => 'finance',
'traducteur' => 'perevod',
'notaire' => 'notarius',
'guide' => 'gid',
'agent-immobilier' => 'rieltori',
'autres-specialistes' => 'drugie',
];
$h1Key = $slugToKey[$resolvedSeoSpecSlug] ?? null;
if ($h1Key !== null) {
$label = $H1_LABELS[$lang][$h1Key] ?? $h1Default;
$h1 = $label . $inFrance;
}
} elseif ($sp !== '' && isset($canonToKey[$sp_l])) {
$key = $canonToKey[$sp_l];
$label = $H1_LABELS[$lang][$key] ?? ($translations[$key] ?? $sp);
$h1 = $label . $inFrance;
}
// Cas spécial : autres spécialistes
$onlyOthers = false;
$specialite = $specialiteParam;
if ($specialiteParam === '__OTHERS__') {
$onlyOthers = true;
$specialite = '';
}
// Pagination
$perPage = 12;
$page = max(1, (int) ($_GET['page'] ?? 1));
$offset = ($page - 1) * $perPage;
// Construction SQL
$where = [];
$params = [];
/*========================== BLOCK WHERE AVEC ABONNEMENT VALIDE ==========================*/
$where[] = "(p.date_expiration IS NOT NULL AND p.date_expiration >= DATE_SUB(NOW(), INTERVAL 14 DAY))";
/*========================================================================================*/
// Le champ "specialite" peut contenir une spécialité OU un nom/prénom
$term = trim((string) $specialite);
$term_l = mb_strtolower($term, 'UTF-8');
// 1) Cas "Другие"
if ($onlyOthers) {
$mainSpecs = array_values($canon);
if ($mainSpecs) {
$ors = [];
foreach ($mainSpecs as $i => $spc) {
$key = ":cat{$i}";
$ors[] = "LOWER(p.specialite) LIKE $key";
$params[$key] = mb_strtolower($spc, 'UTF-8') . '%';
}
$where[] = '(p.specialite IS NULL OR p.specialite = "" OR NOT (' . implode(' OR ', $ors) . '))';
}
}
// 2) Cas normal
elseif ($term !== '') {
$where[] =
"("
. "LOWER(COALESCE(pt.specialite, p.specialite)) LIKE :sp_like "
. "OR LOWER(COALESCE(pt.nom_affiche, p.nom)) LIKE :nm_prefix1 "
. "OR LOWER(COALESCE(pt.prenom_affiche, p.prenom)) LIKE :nm_prefix2 "
. "OR LOWER(CONCAT(COALESCE(pt.prenom_affiche, p.prenom),' ',COALESCE(pt.nom_affiche, p.nom))) LIKE :nm_like_full1 "
. "OR LOWER(CONCAT(COALESCE(pt.nom_affiche, p.nom),' ',COALESCE(pt.prenom_affiche, p.prenom))) LIKE :nm_like_full2 "
. ")";
$params[':sp_like'] = '%' . $term_l . '%';
$params[':nm_prefix1'] = $term_l . '%';
$params[':nm_prefix2'] = $term_l . '%';
$params[':nm_like_full1'] = '%' . $term_l . '%';
$params[':nm_like_full2'] = '%' . $term_l . '%';
}
// Filtre ville — support latin + cyrillique
if ($ville !== '') {
$villeCands = city_query_candidates($ville);
$villeCands[] = mb_strtolower($ville, 'UTF-8');
$villeCands = array_values(array_unique($villeCands));
$villeOrs = [];
foreach ($villeCands as $i => $cand) {
$key = ":ville{$i}";
$params[$key] = $cand . '%';
$villeOrs[] = "LOWER(COALESCE(pt.ville_affichee, p.ville)) LIKE {$key}";
}
if ($villeOrs) {
$where[] = '(' . implode(' OR ', $villeOrs) . ')';
}
}
$whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';
// total
$sqlCount = "
SELECT COUNT(*)
FROM praticien p
LEFT JOIN praticien_traduction pt
ON pt.praticien_id = p.id
AND pt.langue = :lang
$whereSql
";
$stmt = $pdo->prepare($sqlCount);
$paramsCount = $params;
$paramsCount[':lang'] = $currentLang;
$stmt->execute($paramsCount);
$total = (int) $stmt->fetchColumn();
$pages = max(1, (int) ceil($total / $perPage));
// data
$sql = "
SELECT
p.id,
p.nom,
p.prenom,
p.ville,
p.photo,
p.video,
COALESCE(pt.nom_affiche, p.nom) AS nom_affiche,
COALESCE(pt.prenom_affiche, p.prenom) AS prenom_affiche,
COALESCE(pt.specialite, p.specialite) AS specialite_affichee,
COALESCE(pt.ville_affichee, p.ville) AS ville_affichee,
COALESCE(pt.presentation, p.presentation) AS presentation_affichee
FROM praticien p
LEFT JOIN praticien_traduction pt
ON pt.praticien_id = p.id
AND pt.langue = :lang
$whereSql
";
if ($term !== '') {
$sql .= " ORDER BY
(LOWER(CONCAT(COALESCE(pt.prenom_affiche, p.prenom),' ',COALESCE(pt.nom_affiche, p.nom))) = :nm_exact1
OR LOWER(CONCAT(COALESCE(pt.nom_affiche, p.nom),' ',COALESCE(pt.prenom_affiche, p.prenom))) = :nm_exact2) DESC,
(LOWER(COALESCE(pt.nom_affiche, p.nom)) = :nm_exact3 OR LOWER(COALESCE(pt.prenom_affiche, p.prenom)) = :nm_exact4) DESC,
(LOWER(COALESCE(pt.nom_affiche, p.nom)) LIKE :nm_prefix3 OR LOWER(COALESCE(pt.prenom_affiche, p.prenom)) LIKE :nm_prefix4) DESC,
(LOWER(COALESCE(pt.specialite, p.specialite)) LIKE :sp_prefix1) DESC,
COALESCE(pt.nom_affiche, p.nom) ASC,
COALESCE(pt.prenom_affiche, p.prenom) ASC";
$params[':nm_exact1'] = $term_l;
$params[':nm_exact2'] = $term_l;
$params[':nm_exact3'] = $term_l;
$params[':nm_exact4'] = $term_l;
$params[':nm_prefix3'] = $term_l . '%';
$params[':nm_prefix4'] = $term_l . '%';
$params[':sp_prefix1'] = $term_l . '%';
} else {
$sql .= " ORDER BY p.updated_at DESC, p.id DESC";
}
$sql .= " LIMIT :offset, :limit";
$stmt = $pdo->prepare($sql);
$params[':lang'] = $currentLang;
foreach ($params as $k => $v) {
$stmt->bindValue($k, $v, PDO::PARAM_STR);
}
$stmt->bindValue(':offset', (int) $offset, PDO::PARAM_INT);
$stmt->bindValue(':limit', (int) $perPage, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Si ce n'est pas une catégorie canonique et qu'on a des résultats
if (
$h1 === $h1Default
&& $specialiteParam !== '__OTHERS__'
&& $sp !== ''
&& empty($resolvedSeoSpecSlug)
&& ! isset($canonToKey[$sp_l])
) {
if (! empty($rows)) {
$h1 = '';
}
}
// util
function h($s): string
{
return htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8');
}
function excerpt($text, $len = 160): string
{
$t = trim(strip_tags((string) $text));
if (mb_strlen($t, 'UTF-8') <= $len) {
return $t;
}
return mb_substr($t, 0, $len, 'UTF-8') . '…';
}
// pour liens de pagination
$qParams = [];
if ($onlyOthers) {
$qParams['specialite'] = '__OTHERS__';
} elseif ($specialite !== '') {
$qParams['specialite'] = $specialite;
}
if ($ville !== '') {
$qParams['ville'] = $ville;
}
$baseQuery = http_build_query($qParams);
// =========================
// SEO dynamique
// =========================
$seoSpecialite = trim((string) $specialiteParam);
$seoVille = trim((string) $ville);
$isCanonCategory = ($seoSpecialite !== '' && isset($canonToKey[mb_strtolower($seoSpecialite, 'UTF-8')]));
$isOthersCategory = ($seoSpecialite === '__OTHERS__');
$seoDisplaySpecialite = $seoSpecialite;
if ($isOthersCategory) {
$seoDisplaySpecialite = $translations['drugie'] ?? 'Spécialistes';
}
if ($seoDisplaySpecialite === '') {
$seoTitle = $translations['boostseo_search_title_default'] ?? '';
$seoDesc = $translations['boostseo_search_desc_default'] ?? '';
$seoIntro = $translations['boostseo_search_intro_default'] ?? '';
} elseif ($seoVille !== '') {
$seoTitle = strtr(($translations['boostseo_search_title_spec_city'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
'%ville%' => $seoVille,
]);
$seoDesc = strtr(($translations['boostseo_search_desc_spec_city'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
'%ville%' => $seoVille,
]);
$seoIntro = strtr(($translations['boostseo_search_intro_spec_city'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
'%ville%' => $seoVille,
]);
} else {
$seoTitle = strtr(($translations['boostseo_search_title_spec'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
]);
$seoDesc = strtr(($translations['boostseo_search_desc_spec'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
]);
$seoIntro = strtr(($translations['boostseo_search_intro_spec'] ?? ''), [
'%specialite%' => $seoDisplaySpecialite,
]);
}
$canonicalUrl = 'https://uslugi.fr/recherche';
$canonicalSpecSlug = '';
if ($specialiteParam === '__OTHERS__') {
$canonicalSpecSlug = 'autres-specialistes';
} elseif ($specialiteParam !== '') {
foreach (seo_spec_map() as $slug => $cfg) {
if (($cfg['db'] ?? '') === $specialiteParam) {
$canonicalSpecSlug = $slug;
break;
}
}
}
$cityCanonicalSlug = '';
if ($ville !== '') {
$cityCanonicalSlug = seo_city_slug_from_input($ville);
}
if ($canonicalSpecSlug !== '') {
$canonicalUrl .= '/' . rawurlencode($canonicalSpecSlug);
if ($cityCanonicalSlug !== '') {
$canonicalUrl .= '/' . rawurlencode($cityCanonicalSlug);
}
} elseif ($cityCanonicalSlug !== '') {
$canonicalUrl .= '/ville/' . rawurlencode($cityCanonicalSlug);
}
$canonicalUrl .= '/';
if ($page > 1) {
$canonicalUrl .= '?page=' . $page;
}
?>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title><?php echo h($seoTitle) ?></title>
<meta name="description" content="<?php echo h($seoDesc) ?>">
<meta name="author" content="Uslugi.fr">
<meta name="robots" content="index, follow">
<link rel="canonical" href="<?php echo h($canonicalUrl) ?>">
<link rel="alternate" hreflang="ru" href="<?php echo h($canonicalUrl . (str_contains($canonicalUrl, '?') ? '&lang=ru' : '?lang=ru')) ?>">
<link rel="alternate" hreflang="fr" href="<?php echo h($canonicalUrl . (str_contains($canonicalUrl, '?') ? '&lang=fr' : '?lang=fr')) ?>">
<link rel="alternate" hreflang="x-default" href="<?php echo h($canonicalUrl) ?>">
<meta property="og:title" content="<?php echo h($seoTitle) ?>">
<meta property="og:description" content="<?php echo h($seoDesc) ?>">
<meta property="og:type" content="website">
<meta property="og:url" content="<?php echo h($canonicalUrl) ?>">
<meta property="og:image" content="https://uslugi.fr/public/uploads/img/logo.png">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
<?php
$trackingFile = __DIR__ . '/includes/tracking.php';
if (is_file($trackingFile)) {
include_once $trackingFile;
}
?>
</head>
<body class="layout">
<?php if (! empty($logged)):
include_header_clean(APP_HTDOCS . '/public/includes/header.php');
else: ?>
<header class="site-header">
<div class="container">
<div class="header-left">
<div class="brand">
<a href="/index.php"><img src="/public/uploads/img/logo_u.png" alt="uslugi.fr" class="logo-mobile"></a>
<a href="/index.php"><img src="/public/uploads/img/logo.png" alt="uslugi.fr" class="logo-desktop"></a>
</div>
<div class="lang-switch">
<?php require __DIR__ . '/includes/menu_langue.php'; ?>
</div>
</div>
<nav class="header-actions">
<a class="btn-login" href="/connexion.php">
<span class="d-sm-none"><?php echo h($translations['btn_se_connecter'] ?? '') ?></span>
<span class="d-none d-sm-inline"><?php echo h($translations['ja_spec'] ?? '') ?></span>
</a>
<div class="dropdown">
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
aria-expanded="false" aria-label="Помощь">?</button>
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
<li><a href="/how-it-work.php"><?php echo h($translations['kak_rabotaet'] ?? '') ?></a></li>
<li><a href="/about.php"><?php echo h($translations['pro_nas'] ?? '') ?></a></li>
<li><a href="/faq.php"><?php echo h($translations['faq'] ?? '') ?></a></li>
<li><a href="/contact.php"><?php echo h($translations['nam_pisat'] ?? '') ?></a></li>
</ul>
</div>
</nav>
</div>
</header>
<?php endif; ?>
<div class="main1">
<div class="content">
<div class="container">
<h1 class="results-title"><?php echo h($h1) ?></h1>
<p class="visually-hidden"><?php echo h($seoIntro) ?></p>
</div>
<section class="cards-section">
<div class="container pro-list">
<?php if ($rows): ?>
<?php foreach ($rows as $p):
$img = ! empty($p['photo'])
? "/public/uploads/" . ltrim((string) $p['photo'], '/')
: "/public/uploads/img/user_placeholder.png";
?>
<article class="pro-card">
<div class="pro-photo">
<a href="/detail_public.php?id=<?php echo (int) $p['id'] ?>">
<img src="<?php echo h($img ?: '/public/uploads/img/user_placeholder.png') ?>" alt="<?php echo h(trim(($p['prenom_affiche'] ?? '') . ' ' . ($p['nom_affiche'] ?? '') . ' — ' . ($p['specialite_affichee'] ?? '') . (! empty($p['ville_affichee']) ? ' — ' . $p['ville_affichee'] : ''))) ?>">
</a>
</div>
<div class="pro-info">
<h3 class="pro-name">
<a href="/detail_public.php?id=<?php echo (int) $p['id'] ?>">
<?php echo h(($p['prenom_affiche'] ?? '') . ' ' . ($p['nom_affiche'] ?? '')) ?>
</a>
</h3>
<?php if (! empty($p['specialite_affichee'])): ?>
<div class="pro-spec"><?php echo h($p['specialite_affichee']) ?></div>
<?php endif; ?>
<?php if (! empty($p['presentation_affichee'])): ?>
<p class="pro-desc"><?php echo h(excerpt($p['presentation_affichee'], 360)) ?></p>
<?php endif; ?>
<a href="/detail_public.php?id=<?php echo (int) $p['id'] ?>">
<?php echo h($translations['plus_details'] ?? 'Подробнее'); ?>
</a>
</div>
<?php if (! empty($p['video'])): ?>
<div class="pro-video-col">
<?php
$vinfo = video_thumb_info($p['video']);
$alt = htmlspecialchars($translations['video_alt'] ?? 'Vidéo', ENT_QUOTES, 'UTF-8');
$thumb = $vinfo['thumb'] ?? null;
$prov = $vinfo['provider'] ?? 'other';
$vid = $vinfo['id'] ?? null;
$raw = trim((string) ($p['video'] ?? ''));
?>
<?php if (in_array($prov, ['youtube', 'dailymotion'], true) && $vid): ?>
<a class="pro-video" href="#"
data-provider="<?php echo htmlspecialchars($prov, ENT_QUOTES, 'UTF-8') ?>"
data-id="<?php echo htmlspecialchars($vid, ENT_QUOTES, 'UTF-8') ?>"
aria-label="<?php echo $alt ?>">
<img src="<?php echo htmlspecialchars($thumb ?: '/public/uploads/img/video_placeholder.jpg', ENT_QUOTES, 'UTF-8') ?>"
alt="<?php echo $alt ?>">
</a>
<?php else: ?>
<a class="pro-video" href="<?php echo htmlspecialchars($raw, ENT_QUOTES, 'UTF-8') ?>" target="_blank" rel="noopener">
<img src="<?php echo htmlspecialchars($thumb ?: '/public/uploads/img/video_placeholder.jpg', ENT_QUOTES, 'UTF-8') ?>"
alt="<?php echo $alt ?>">
</a>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="pro-cta-col">
<a class="pro-cta"
href="/public/client/reserver_rdv.php?praticien_id=<?php echo (int) $p['id'] ?>">
<?php echo h($translations['den'] ?? 'Выберите день') ?>
</a>
</div>
</article>
<?php endforeach; ?>
<?php else: ?>
<div class="no-results"><?php echo h($translations['probuite'] ?? 'Нет результатов') ?></div>
<?php endif; ?>
</div>
<?php if ($pages > 1): ?>
<?php
$qBase = $baseQuery ? ($baseQuery . '&') : '';
$prevPage = max(1, $page - 1);
$nextPage = min($pages, $page + 1);
?>
<nav class="pager" aria-label="Pagination">
<a class="pager-arrow <?php echo $page <= 1 ? 'is-disabled' : '' ?>"
href="<?php echo h('/result_search.php?' . $qBase . 'page=' . $prevPage) ?>"
aria-label="Page précédente">&laquo;&laquo;</a>
<?php
$start = max(1, $page - 2);
$end = min($pages, $page + 2);
for ($i = $start; $i <= $end; $i++):
$href = '/result_search.php?' . $qBase . 'page=' . $i;
?>
<a class="pager-page <?php echo $i === $page ? 'is-active' : '' ?>"
href="<?php echo h($href) ?>"><?php echo (int) $i ?></a>
<?php endfor; ?>
<a class="pager-arrow <?php echo $page >= $pages ? 'is-disabled' : '' ?>"
href="<?php echo h('/result_search.php?' . $qBase . 'page=' . $nextPage) ?>"
aria-label="Page suivante">&raquo;&raquo;</a>
</nav>
<?php endif; ?>
</section>
</div>
</div>
<!-- Modal vidéo -->
<div id="lightboxVideo" class="vmodal" aria-hidden="true">
<div class="vmodal__backdrop" data-close></div>
<div class="vmodal__dialog" role="dialog" aria-modal="true" aria-label="Vidéo">
<div class="vmodal__header">
<h5 class="vmodal__title">Vidéo</h5>
<button class="vmodal__close" type="button" title="Fermer" aria-label="Fermer" data-close>×</button>
</div>
<div class="vmodal__body">
<div class="vmodal__ratio">
<iframe id="vPlayer" src="" title="Video player"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
referrerpolicy="strict-origin-when-cross-origin"></iframe>
</div>
</div>
<div class="vmodal__footer">
<button class="btn btn-secondary-like" type="button" data-close>Fermer</button>
</div>
</div>
</div>
<footer class="site-footer">
<div class="container">
<p><?php echo $translations['copyr'] ?></p>
</div>
</footer>
<script>
(function(){
const modal = document.getElementById('lightboxVideo');
const frame = document.getElementById('vPlayer');
function buildSrc(provider, id){
if (!provider || !id) return '';
if (provider === 'youtube') return 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0&modestbranding=1';
if (provider === 'dailymotion') return 'https://www.dailymotion.com/embed/video/' + id + '?autoplay=1&ui-start-screen-info=false';
return '';
}
function openModal(src){
if (!src) return;
frame.src = src;
modal.setAttribute('aria-hidden','false');
document.body.style.overflow = 'hidden';
}
function closeModal(){
frame.src = '';
modal.setAttribute('aria-hidden','true');
document.body.style.overflow = '';
}
document.addEventListener('click', function(e){
const a = e.target.closest('a.pro-video');
if (!a) return;
const provider = a.getAttribute('data-provider');
const id = a.getAttribute('data-id');
if (provider && id){
e.preventDefault();
const src = buildSrc(provider, id);
openModal(src);
}
});
modal.addEventListener('click', (e)=>{ if (e.target.hasAttribute('data-close')) closeModal(); });
window.addEventListener('keydown', (e)=>{ if (e.key === 'Escape' && modal.getAttribute('aria-hidden') === 'false') closeModal(); });
})();
</script>
<script src="/js/bootstrap.bundle.min.js"></script>
</body>
</html>