diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..8bf4d45 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..b0e4773 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + mariadb + true + org.mariadb.jdbc.Driver + jdbc:mariadb://mariadb:3306/uslugi_db + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/maria_uslugi.iml b/.idea/maria_uslugi.iml new file mode 100644 index 0000000..0399c4b --- /dev/null +++ b/.idea/maria_uslugi.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4ecca67 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/about.php b/about.php index 814ebda..04ae3c3 100644 --- a/about.php +++ b/about.php @@ -1,74 +1,98 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + if (! empty($_SESSION['praticien_id'])) { + return true; + } - // 3) retirer le ~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - echo $buf; // garde
+ tes scripts inline utiles -} + return false; + } -function t(array $translations, string $key, string $fallback = ''): string { - $val = $translations[$key] ?? ''; - if ($val === '') return $fallback; - return (string)$val; -} + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; -// Lang HTML -$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (string)$lang : 'ru'; + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + function t(array $translations, string $key, string $fallback = ''): string + { + $val = $translations[$key] ?? ''; + if ($val === '') { + return $fallback; + } + + return (string) $val; + } + + // Lang HTML + $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru'; ?> - + - <?= htmlspecialchars($translations['seo_about_title'], ENT_QUOTES, 'UTF-8') ?> - - + <?php echo htmlspecialchars($translations['seo_about_title'], ENT_QUOTES, 'UTF-8') ?> + + - + - - - + + + - + @@ -61,15 +61,15 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
-

+

-
-

- +
+

+
@@ -77,9 +77,9 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
-
-

- +
+

+
@@ -89,7 +89,7 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
-

+

diff --git a/contact.php b/contact.php index ba945ef..c73c2ed 100644 --- a/contact.php +++ b/contact.php @@ -1,219 +1,263 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); - - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); - - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); - - // 3) retirer le ~i', '', $buf); - - echo $buf; // garde
+ tes scripts inline utiles -} - -/* ---------- Utils ---------- */ -function envget(string $k): string { - return trim((string)($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? '')); -} - -function t(array $translations, string $key, string $fallback = ''): string { - $val = $translations[$key] ?? ''; - if ($val === '') return $fallback; - return (string)$val; -} - -$LOG_DIR = __DIR__ . '/tmp'; -$LOG_FILE = $LOG_DIR . '/contact.log'; -if (!is_dir($LOG_DIR)) { @mkdir($LOG_DIR, 0770, true); } // dossier local, pas servi publiquement - -/* ---------- CSRF ---------- */ -if (empty($_SESSION['pub_csrf'])) { - $_SESSION['pub_csrf'] = bin2hex(random_bytes(32)); -} -$CSRF = $_SESSION['pub_csrf']; - -// --- reCAPTCHA v2 (lecture robuste) --- -$rcCfg = []; -$cfgPath = __DIR__ . '/includes/recaptcha.php'; -if (is_file($cfgPath)) { - $rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...'] -} - -$RECAPTCHA_SITE_KEY = trim((string)($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? '')); -$RECAPTCHA_SECRET_KEY = trim((string)($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? '')); - -// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs -$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20); -$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20); - -// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1 -if (($_GET['testcaptcha'] ?? '') === '1') $HAS_SITE = true; - -/* ---------- État page ---------- */ -$errors = []; -$sent = false; - -/* ---------- POST ---------- */ -if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { - - // CSRF - if (!hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) { - $errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.'); - } - - // Honeypot anti-bot - if (!empty($_POST['website'] ?? '')) { - $errors[] = t($translations, 'contact_err_spam', 'Spam suspected.'); - } - - // Données utilisateur - $prenom = trim($_POST['prenom'] ?? ''); - $nom = trim($_POST['nom'] ?? ''); - $email = trim($_POST['email'] ?? ''); - $sujet = trim($_POST['sujet'] ?? ''); - $message = trim($_POST['message'] ?? ''); - - // Validations - if (mb_strlen($prenom) < 2) $errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.'); - if (mb_strlen($nom) < 2) $errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.'); - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.'); - if (mb_strlen($sujet) < 3) $errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.'); - if (mb_strlen($message) < 10) $errors[] = t($translations, 'contact_err_message', 'Message is too short.'); - - // reCAPTCHA serveur - if ($HAS_SECRET) { - $token = $_POST['g-recaptcha-response'] ?? ''; - if ($token === '') { - $errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.'); - } else { - $resp = @file_get_contents( - 'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) . - '&response=' . urlencode($token) . - '&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '') - ); - $ver = $resp ? json_decode($resp, true) : ['success' => false]; - if (empty($ver['success'])) $errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.'); + // ===== Helpers header (identiques à index.php) ===== + function is_client_logged_in(): bool + { + $role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? ''); + if (! empty($_SESSION['user_id']) && $role === 'client') { + return true; } - } - // Envoi - if (!$errors) { - $to = 'contact@uslugi.fr'; + if (! empty($_SESSION['client_id'])) { + return true; + } - $subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — '); - $subject = $subjectPrefix . $sujet; + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - $mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr'); - $lblName = t($translations, 'contact_mail_label_name', 'Name'); - $lblEmail = t($translations, 'contact_mail_label_email', 'Email'); - $lblSubject = t($translations, 'contact_mail_label_subject', 'Subject'); - $lblMessage = t($translations, 'contact_mail_label_message', 'Message'); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - $html = ' -

'.htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8').'

-

'.htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8').': '.htmlspecialchars($prenom).' '.htmlspecialchars($nom).'

-

'.htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8').': '.htmlspecialchars($email).'

-

'.htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8').': '.htmlspecialchars($sujet).'

-

'.htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8').':
'.nl2br(htmlspecialchars($message)).'

+ if (! empty($_SESSION['praticien_id'])) { + return true; + } + + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } + + return false; + } + + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; + + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + /* ---------- Utils ---------- */ + function envget(string $k): string + { + return trim((string) ($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? '')); + } + + function t(array $translations, string $key, string $fallback = ''): string + { + $val = $translations[$key] ?? ''; + if ($val === '') { + return $fallback; + } + + return (string) $val; + } + + $LOG_DIR = __DIR__ . '/tmp'; + $LOG_FILE = $LOG_DIR . '/contact.log'; + if (! is_dir($LOG_DIR)) {@mkdir($LOG_DIR, 0770, true);} // dossier local, pas servi publiquement + + /* ---------- CSRF ---------- */ + if (empty($_SESSION['pub_csrf'])) { + $_SESSION['pub_csrf'] = bin2hex(random_bytes(32)); + } + $CSRF = $_SESSION['pub_csrf']; + + // --- reCAPTCHA v2 (lecture robuste) --- + $rcCfg = []; + $cfgPath = __DIR__ . '/includes/recaptcha.php'; + if (is_file($cfgPath)) { + $rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...'] + } + + $RECAPTCHA_SITE_KEY = trim((string) ($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? '')); + $RECAPTCHA_SECRET_KEY = trim((string) ($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? '')); + + // Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs + $HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20); + $HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20); + + // (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1 + if (($_GET['testcaptcha'] ?? '') === '1') { + $HAS_SITE = true; + } + + /* ---------- État page ---------- */ + $errors = []; + $sent = false; + + /* ---------- POST ---------- */ + if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { + + // CSRF + if (! hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) { + $errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.'); + } + + // Honeypot anti-bot + if (! empty($_POST['website'] ?? '')) { + $errors[] = t($translations, 'contact_err_spam', 'Spam suspected.'); + } + + // Données utilisateur + $prenom = trim($_POST['prenom'] ?? ''); + $nom = trim($_POST['nom'] ?? ''); + $email = trim($_POST['email'] ?? ''); + $sujet = trim($_POST['sujet'] ?? ''); + $message = trim($_POST['message'] ?? ''); + + // Validations + if (mb_strlen($prenom) < 2) { + $errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.'); + } + + if (mb_strlen($nom) < 2) { + $errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.'); + } + + if (! filter_var($email, FILTER_VALIDATE_EMAIL)) { + $errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.'); + } + + if (mb_strlen($sujet) < 3) { + $errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.'); + } + + if (mb_strlen($message) < 10) { + $errors[] = t($translations, 'contact_err_message', 'Message is too short.'); + } + + // reCAPTCHA serveur + if ($HAS_SECRET) { + $token = $_POST['g-recaptcha-response'] ?? ''; + if ($token === '') { + $errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.'); + } else { + $resp = @file_get_contents( + 'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) . + '&response=' . urlencode($token) . + '&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '') + ); + $ver = $resp ? json_decode($resp, true) : ['success' => false]; + if (empty($ver['success'])) { + $errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.'); + } + + } + } + + // Envoi + if (! $errors) { + $to = 'contact@uslugi.fr'; + + $subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — '); + $subject = $subjectPrefix . $sujet; + + $mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr'); + $lblName = t($translations, 'contact_mail_label_name', 'Name'); + $lblEmail = t($translations, 'contact_mail_label_email', 'Email'); + $lblSubject = t($translations, 'contact_mail_label_subject', 'Subject'); + $lblMessage = t($translations, 'contact_mail_label_message', 'Message'); + + $html = ' +

' . htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8') . '

+

' . htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8') . ': ' . htmlspecialchars($prenom) . ' ' . htmlspecialchars($nom) . '

+

' . htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8') . ': ' . htmlspecialchars($email) . '

+

' . htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8') . ': ' . htmlspecialchars($sujet) . '

+

' . htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8') . ':
' . nl2br(htmlspecialchars($message)) . '

'; - $text = $mailH3 . "\n" - . $lblName . ": $prenom $nom\n" - . $lblEmail . ": $email\n" - . $lblSubject . ": $sujet\n\n" - . $lblMessage . ":\n$message\n"; + $text = $mailH3 . "\n" + . $lblName . ": $prenom $nom\n" + . $lblEmail . ": $email\n" + . $lblSubject . ": $sujet\n\n" + . $lblMessage . ":\n$message\n"; - try { - // From et Reply-To (tableaux) comme attendus par ton wrapper - $fromEmail = 'no-reply@uslugi.fr'; - $fromName = 'USLUGI.FR'; + try { + // From et Reply-To (tableaux) comme attendus par ton wrapper + $fromEmail = 'no-reply@uslugi.fr'; + $fromName = 'USLUGI.FR'; - $replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr'; - $replyName = trim($prenom.' '.$nom) ?: 'USLUGI.FR'; + $replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr'; + $replyName = trim($prenom . ' ' . $nom) ?: 'USLUGI.FR'; - // Appel wrapper: retourne [bool $ok, ?string $err] - [$ok, $err] = uslugi_mail( - $to, - $subject, - $html, - $text, - [ - 'from' => [$fromEmail, $fromName], - 'reply_to' => [$replyEmail, $replyName], - // 'bcc' => ['tonmail@gmail.com'], - ] - ); + // Appel wrapper: retourne [bool $ok, ?string $err] + [$ok, $err] = uslugi_mail( + $to, + $subject, + $html, + $text, + [ + 'from' => [$fromEmail, $fromName], + 'reply_to' => [$replyEmail, $replyName], + // 'bcc' => ['tonmail@gmail.com'], + ] + ); - if ($ok !== true) { - throw new RuntimeException('Wrapper mail send failed.'); - } + if ($ok !== true) { + throw new RuntimeException('Wrapper mail send failed.'); + } - // OK - $sent = true; - $_POST = []; - @file_put_contents($LOG_FILE, sprintf( - "[%s] OK to=%s subj=%s reply=%s ip=%s\n", - date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-' - ), FILE_APPEND); + // OK + $sent = true; + $_POST = []; + @file_put_contents($LOG_FILE, sprintf( + "[%s] OK to=%s subj=%s reply=%s ip=%s\n", + date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-' + ), FILE_APPEND); - } catch (Throwable $e) { - error_log('MAIL ERROR: ' . $e->getMessage()); - @file_put_contents($LOG_FILE, sprintf( - "[%s] ERR to=%s subj=%s\n", - date('c'), $to, $sujet - ), FILE_APPEND); + } catch (Throwable $e) { + error_log('MAIL ERROR: ' . $e->getMessage()); + @file_put_contents($LOG_FILE, sprintf( + "[%s] ERR to=%s subj=%s\n", + date('c'), $to, $sujet + ), FILE_APPEND); - // Message utilisateur générique (jamais d’info sensible à l’écran) - $errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.'); + // Message utilisateur générique (jamais d’info sensible à l’écran) + $errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.'); + } + } } - } -} -// Lang HTML -$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (string)$lang : 'ru'; + // Lang HTML + $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru'; ?> - + - <?= htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?> - - + <?php echo htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?> + + - + - - - - + + + + + + + + + + + + +
+
+ +
+ + + +

+ +

+

+ +

+
+ +
+
+ + $name ?? '', 'profession' => $profession ?? '', + 'city' => $city ?? '', 'country' => $country ?? '', + 'phone' => $phone ?? '', 'email' => $email ?? '', + 'site' => $site ?? '', 'reason' => $reason ?? '', + ]; + } + + if ($form_index_status === 'success'): ?> +
+
✓
+

+

+
+ +
+ + + + + +
+ + + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+
+ + + +

+ +

+
+
+ +
+
+
+ + diff --git a/how-it-work.php b/how-it-work.php index 8d94175..5a4304f 100644 --- a/how-it-work.php +++ b/how-it-work.php @@ -5,87 +5,87 @@ // ===== Helpers header (identiques à index.php) ===== function is_client_logged_in(): bool { - $role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? ''); - if (! empty($_SESSION['user_id']) && $role === 'client') { - return true; - } + $role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? ''); + if (! empty($_SESSION['user_id']) && $role === 'client') { + return true; + } - if (! empty($_SESSION['client_id'])) { - return true; - } + if (! empty($_SESSION['client_id'])) { + return true; + } - if (! empty($_SESSION['reference_id']) && $role === 'client') { - return true; - } + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - if (! empty($_SESSION['user_id']) && $role === 'praticien') { - return true; - } + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - if (! empty($_SESSION['praticien_id'])) { - return true; - } + if (! empty($_SESSION['praticien_id'])) { + return true; + } - if (! empty($_SESSION['reference_id']) && $role === 'praticien') { - return true; - } + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - return false; + return false; } function include_header_clean(string $absPath): void { - global $translations, $lang; - ob_start(); - include $absPath; // /public/includes/header.php - $buf = ob_get_clean() ?: ''; + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; - // 0) DOCTYPE + … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); - // 3) retirer le ~i', '', $buf); + // 3) retirer le ~i', '', $buf); - echo $buf; // garde
+ tes scripts inline utiles + echo $buf; // garde
+ tes scripts inline utiles } function t(array $translations, string $key, string $fallback = ''): string { - $val = $translations[$key] ?? ''; - if ($val === '') { - return $fallback; - } + $val = $translations[$key] ?? ''; + if ($val === '') { + return $fallback; + } - return (string) $val; + return (string) $val; } // Lang HTML $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru'; ?> - + - <?php echo htmlspecialchars($translations['seo_how_it_work_title'], ENT_QUOTES, 'UTF-8')?> - - + <?php echo htmlspecialchars($translations['seo_how_it_work_title'], ENT_QUOTES, 'UTF-8') ?> + + - + - - - + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + +
+

+ + + + +

+

+ +

+
+
+ ' . h($label) . ''; + } + }; + ?> + +

+ +

+
+
+
+ +
+

+ +

+
+query(" + SELECT id + FROM praticien + WHERE photo IS NOT NULL + AND photo <> '' + AND date_expiration >= NOW() + ORDER BY id DESC + LIMIT 100 +")->fetchAll(PDO::FETCH_COLUMN); + + if (! $ids) { + throw new Exception('Aucun praticien'); + } + + /* ====================================================== + 2️⃣ On mélange et on prend 4 +====================================================== */ + shuffle($ids); + $ids = array_slice($ids, 0, 4); + + /* ====================================================== + 3️⃣ On récupère les 4 profils +====================================================== */ + $placeholders = implode(',', array_fill(0, count($ids), '?')); + + $stmt = $pdo->prepare(" + SELECT + p.id, + COALESCE(NULLIF(pt.nom_affiche, ''), p.nom) AS nom, + COALESCE(NULLIF(pt.prenom_affiche, ''), p.prenom) AS prenom, + COALESCE(NULLIF(pt.specialite, ''), p.specialite) AS specialite, + p.photo + FROM praticien p + LEFT JOIN praticien_traduction pt + ON pt.praticien_id = p.id + AND pt.langue = ? + WHERE p.id IN ($placeholders) +"); + + $stmt->execute(array_merge([$lang], $ids)); + $randomPros = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (! $randomPros) { + throw new Exception('Aucun praticien'); + } + /* ====================================================== + 3️⃣ Notes + ====================================================== */ + function percent_from_5($note) + { + $n = max(0, min(5, (float) $note)); + return (int) round($n / 5 * 100); + } + + $ratingsById = []; + + $stRatings = $pdo->prepare(" + SELECT praticien_id, ROUND(AVG(note),1) AS m, COUNT(*) AS c + FROM avis_praticien + WHERE statut='publie' AND praticien_id IN ($placeholders) + GROUP BY praticien_id + "); + $stRatings->execute($ids); + + foreach ($stRatings->fetchAll(PDO::FETCH_ASSOC) as $r) { + $ratingsById[(int) $r['praticien_id']] = [ + 'm' => (float) $r['m'], + 'c' => (int) $r['c'], + ]; + } + + /* ====================================================== + 4️⃣ Affichage + ====================================================== */ + foreach ($randomPros as $rp): + + $pid = (int) $rp['id']; + + $photoName = ltrim((string) $rp['photo'], '/'); + $rpImg = "/public/uploads/" . $photoName; + $abs = APP_HTDOCS . "/public/uploads/" . $photoName; + + if (! $photoName || ! is_file($abs)) { + $rpImg = "/public/uploads/img/user_placeholder.png"; + } + + $fullName = trim(($rp['prenom'] ?? '') . ' ' . ($rp['nom'] ?? '')); + $spec = trim((string) ($rp['specialite'] ?? '')); + $detailUrl = "/detail_public.php?id=" . $pid; + + $hour = random_int(9, 18); + $availability = ($translations['home_online_at'] ?? 'Онлайн:') . ' ' . sprintf('%02d:00', $hour); + + $stats = $ratingsById[$pid] ?? ['m' => 0, 'c' => 0]; + $note = (float) $stats['m']; + $count = (int) $stats['c']; + $w = percent_from_5($note); + + ?> +
+ +
+ + <?php echo h($fullName) ?> + + +
+ +

+
+
+ +
+
+ +
+ 0): ?> +
+
★★★★★
+
★★★★★
+
+ +
+ /5 + () +
+ +
+
+ +
+
+ 📅 + +
+ + + + +
+ +
+ +
+

+
+
+

+

+ + + +
+
+ +
+ + + + + +
+
+
+
+ + +
+

+

+
+
+
+

+
+
+ + + + + + + + + + diff --git a/inscription_praticien.php b/inscription_praticien.php index 39c2506..ed9b8b2 100644 --- a/inscription_praticien.php +++ b/inscription_praticien.php @@ -1,5 +1,5 @@ - @@ -7,15 +7,15 @@ require_once __DIR__ . '/../includes/bootstrap_global.php'; - <?= $translations['insc_praticien_title'] ?> + <?php echo $translations['insc_praticien_title'] ?> - - - - + + + + - + @@ -89,22 +109,22 @@ function include_header_clean(string $absPath): void {
@@ -116,39 +136,39 @@ function include_header_clean(string $absPath): void {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- - + +
- +
@@ -157,7 +177,7 @@ function include_header_clean(string $absPath): void {
-

+

diff --git a/topics/family.php b/topics/family.php index 97fdd82..4652e69 100644 --- a/topics/family.php +++ b/topics/family.php @@ -1,51 +1,71 @@ ]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); - $buf = preg_replace('~]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - echo $buf; -} + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } + + if (! empty($_SESSION['praticien_id'])) { + return true; + } + + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } + + return false; + } + + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; + $buf = ob_get_clean() ?: ''; + + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + $buf = preg_replace('~]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*~i', '', $buf); + + echo $buf; + } ?> - + - <?= htmlspecialchars($translations['seo_topic_family_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?> - - + <?php echo htmlspecialchars($translations['seo_topic_family_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?> + + - + - - - - + + + + - + @@ -89,22 +109,22 @@ function include_header_clean(string $absPath): void {
@@ -116,39 +136,39 @@ function include_header_clean(string $absPath): void {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- - + +
- +
@@ -157,7 +177,7 @@ function include_header_clean(string $absPath): void {
-

+

diff --git a/topics/health.php b/topics/health.php index cad9a56..0703a21 100644 --- a/topics/health.php +++ b/topics/health.php @@ -1,63 +1,83 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + if (! empty($_SESSION['praticien_id'])) { + return true; + } - // 3) retirer le ~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - echo $buf; // garde
+ tes scripts inline utiles -} + return false; + } -// helpers safe (optionnel mais propre) -function t(string $key, string $fallback = ''): string { - global $translations; - return (string)($translations[$key] ?? $fallback); -} + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; + + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + // helpers safe (optionnel mais propre) + function t(string $key, string $fallback = ''): string + { + global $translations; + return (string) ($translations[$key] ?? $fallback); + } ?> - + - <?= htmlspecialchars(t('seo_medecine_title'), ENT_QUOTES) ?> - - + <?php echo htmlspecialchars(t('seo_medecine_title'), ENT_QUOTES) ?> + + - + - - - - + + + + - + @@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string { @@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- +
- +
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
-

+

diff --git a/topics/immigration.php b/topics/immigration.php index 2a4e353..fd523f7 100644 --- a/topics/immigration.php +++ b/topics/immigration.php @@ -1,63 +1,83 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + if (! empty($_SESSION['praticien_id'])) { + return true; + } - // 3) retirer le ~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - echo $buf; // garde
+ tes scripts inline utiles -} + return false; + } -// helper simple -function t(string $key, string $fallback = ''): string { - global $translations; - return (string)($translations[$key] ?? $fallback); -} + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; + + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + // helper simple + function t(string $key, string $fallback = ''): string + { + global $translations; + return (string) ($translations[$key] ?? $fallback); + } ?> - + - <?= htmlspecialchars(t('seo_immigration_title'), ENT_QUOTES) ?> - - + <?php echo htmlspecialchars(t('seo_immigration_title'), ENT_QUOTES) ?> + + - + - - - - + + + + - + @@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string { @@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- +
- +
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
-

+

diff --git a/topics/jobs.php b/topics/jobs.php index 85be2a0..13fb0e2 100644 --- a/topics/jobs.php +++ b/topics/jobs.php @@ -1,63 +1,83 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + if (! empty($_SESSION['praticien_id'])) { + return true; + } - // 3) retirer le ~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - echo $buf; // garde
+ tes scripts inline utiles -} + return false; + } -// helper simple -function t(string $key, string $fallback = ''): string { - global $translations; - return (string)($translations[$key] ?? $fallback); -} + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; + + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + // helper simple + function t(string $key, string $fallback = ''): string + { + global $translations; + return (string) ($translations[$key] ?? $fallback); + } ?> - + - <?= htmlspecialchars(t('seo_travail_title'), ENT_QUOTES) ?> - - + <?php echo htmlspecialchars(t('seo_travail_title'), ENT_QUOTES) ?> + + - + - - - - + + + + - + @@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string { @@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- +
- +
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
-

+

diff --git a/topics/taxes.php b/topics/taxes.php index 50f2b06..d931ffa 100644 --- a/topics/taxes.php +++ b/topics/taxes.php @@ -1,63 +1,83 @@ … - $buf = preg_replace('~]*>~i', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'client') { + return true; + } - // 1) retirer … et ouverts/fermés - $buf = preg_replace('~]*>.*?~is', '', $buf); - $buf = preg_replace('~]*>~i', '', $buf); + if (! empty($_SESSION['user_id']) && $role === 'praticien') { + return true; + } - // 2) retirer les CSS “globaux” pour éviter d’écraser la home - $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + if (! empty($_SESSION['praticien_id'])) { + return true; + } - // 3) retirer le ~i', '', $buf); + if (! empty($_SESSION['reference_id']) && $role === 'praticien') { + return true; + } - echo $buf; // garde
+ tes scripts inline utiles -} + return false; + } -// helper simple -function t(string $key, string $fallback = ''): string { - global $translations; - return (string)($translations[$key] ?? $fallback); -} + function include_header_clean(string $absPath): void + { + global $translations, $lang; + ob_start(); + include $absPath; // /public/includes/header.php + $buf = ob_get_clean() ?: ''; + + // 0) DOCTYPE + … + $buf = preg_replace('~]*>~i', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 1) retirer … et ouverts/fermés + $buf = preg_replace('~]*>.*?~is', '', $buf); + $buf = preg_replace('~]*>~i', '', $buf); + + // 2) retirer les CSS “globaux” pour éviter d’écraser la home + $buf = preg_replace('~]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf); + + // 3) retirer le ~i', '', $buf); + + echo $buf; // garde
+ tes scripts inline utiles + } + + // helper simple + function t(string $key, string $fallback = ''): string + { + global $translations; + return (string) ($translations[$key] ?? $fallback); + } ?> - + - <?= htmlspecialchars(t('seo_taxes_title'), ENT_QUOTES) ?> - - + <?php echo htmlspecialchars(t('seo_taxes_title'), ENT_QUOTES) ?> + + - + - - - - + + + + - + @@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string { @@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
-

-

+

+

- - - - - + + + + +
-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

-

-

+

+

- +
- +
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {