This commit introduces the `fxLegalLabelIsDraft` function, which checks if a given label is a draft based on its content. The function trims the label and evaluates conditions such as emptiness and the presence of underscores, enhancing the clarity and maintainability of the cookie consent management system. This addition supports better label handling in the context of legal page requirements.
678 lines
28 KiB
PHP
678 lines
28 KiB
PHP
<?php
|
|
|
|
function fxCookiesPreferences(): array
|
|
{
|
|
$defaults = ['analytics' => false, 'marketing' => false, 'set' => false];
|
|
|
|
if (!empty($_COOKIE['cookiesPreferences'])) {
|
|
$prefs = json_decode(stripslashes((string) $_COOKIE['cookiesPreferences']), true);
|
|
|
|
if (is_array($prefs)) {
|
|
return [
|
|
'analytics' => !empty($prefs['analytics']),
|
|
'marketing' => !empty($prefs['marketing']),
|
|
'set' => true,
|
|
];
|
|
}
|
|
}
|
|
|
|
if (isset($_COOKIE['cookiesAccepted']) && $_COOKIE['cookiesAccepted'] === 'true') {
|
|
return ['analytics' => true, 'marketing' => true, 'set' => true];
|
|
}
|
|
|
|
if (isset($_COOKIE['cookiesRejected']) && $_COOKIE['cookiesRejected'] === 'true') {
|
|
return ['analytics' => false, 'marketing' => false, 'set' => true];
|
|
}
|
|
|
|
return $defaults;
|
|
}
|
|
|
|
function fxCookiesConsentAccepted(): bool
|
|
{
|
|
$prefs = fxCookiesPreferences();
|
|
|
|
return $prefs['set'] && ($prefs['analytics'] || $prefs['marketing']);
|
|
}
|
|
|
|
function fxCookiesConsentRejected(): bool
|
|
{
|
|
$prefs = fxCookiesPreferences();
|
|
|
|
return $prefs['set'] && !$prefs['analytics'] && !$prefs['marketing'];
|
|
}
|
|
|
|
function fxCookiesConsentPending(): bool
|
|
{
|
|
return !fxCookiesPreferences()['set'];
|
|
}
|
|
|
|
function fxCookiesAllowAnalytics(): bool
|
|
{
|
|
return fxCookiesPreferences()['analytics'];
|
|
}
|
|
|
|
function fxCookiesAllowMarketing(): bool
|
|
{
|
|
return fxCookiesPreferences()['marketing'];
|
|
}
|
|
|
|
function fxCookiesConsentResetIfRequested(): void
|
|
{
|
|
if (!isset($_GET['cookies'])) {
|
|
return;
|
|
}
|
|
|
|
$past = time() - 3600;
|
|
$names = ['cookiesAccepted', 'cookiesRejected', 'cookiesPreferences'];
|
|
|
|
foreach ($names as $name) {
|
|
setcookie($name, '', $past, '/');
|
|
unset($_COOKIE[$name]);
|
|
}
|
|
|
|
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '/';
|
|
$query = [];
|
|
|
|
if (!empty($_SERVER['QUERY_STRING'])) {
|
|
parse_str($_SERVER['QUERY_STRING'], $query);
|
|
}
|
|
|
|
unset($query['cookies']);
|
|
$location = $path;
|
|
|
|
if ($query) {
|
|
$location .= '?' . http_build_query($query);
|
|
}
|
|
|
|
header('Location: ' . $location);
|
|
exit;
|
|
}
|
|
|
|
function fxPageNeedsPaypal(): bool
|
|
{
|
|
global $strPage;
|
|
|
|
if (empty($strPage)) {
|
|
return false;
|
|
}
|
|
|
|
static $paypalPages = [
|
|
'panier.php',
|
|
'dons.php',
|
|
'paiement_redirect.php',
|
|
'panier',
|
|
'cart',
|
|
'don',
|
|
'donate',
|
|
];
|
|
|
|
return in_array($strPage, $paypalPages, true);
|
|
}
|
|
|
|
function fxCookieConsentDefaults(): array
|
|
{
|
|
return [
|
|
'experience_cookies' => [
|
|
'fr' => 'Nous utilisons des témoins (cookies) pour assurer le bon fonctionnement du site, sécuriser vos inscriptions et mémoriser votre panier. Avec votre consentement, nous utilisons aussi des outils de mesure d\'audience et de marketing. Vous pouvez accepter, refuser ou personnaliser vos choix à tout moment. Votre décision n\'empêche pas de vous inscrire.',
|
|
'en' => 'We use cookies to ensure the site works properly, secure your registration and remember your cart. With your consent, we also use analytics and marketing tools. You may accept, refuse or customize your choices at any time. Your decision does not prevent you from registering.',
|
|
],
|
|
'bouton_acceper_cookies' => [
|
|
'fr' => 'Tout accepter',
|
|
'en' => 'Accept all',
|
|
],
|
|
'bouton_refuser_cookies' => [
|
|
'fr' => 'Tout refuser',
|
|
'en' => 'Refuse all',
|
|
],
|
|
'bouton_personnaliser_cookies' => [
|
|
'fr' => 'Personnaliser',
|
|
'en' => 'Customize',
|
|
],
|
|
'bouton_enregistrer_cookies' => [
|
|
'fr' => 'Enregistrer mes choix',
|
|
'en' => 'Save my choices',
|
|
],
|
|
'cookie_pref_titre' => [
|
|
'fr' => 'Gérer mes préférences de témoins',
|
|
'en' => 'Manage my cookie preferences',
|
|
],
|
|
'cookie_pref_essentiels' => [
|
|
'fr' => 'Témoins essentiels — nécessaires au panier, à la session, à la connexion et à la sécurité du site. Toujours actifs.',
|
|
'en' => 'Essential cookies — required for cart, session, login and site security. Always active.',
|
|
],
|
|
'cookie_pref_analytique' => [
|
|
'fr' => 'Mesure d\'audience — statistiques de fréquentation du site via Google Analytics.',
|
|
'en' => 'Analytics — site traffic statistics via Google Analytics.',
|
|
],
|
|
'cookie_pref_marketing' => [
|
|
'fr' => 'Marketing — mesure des conversions et publicité via Meta (Facebook) et scripts ajoutés par l\'organisateur.',
|
|
'en' => 'Marketing — conversion tracking and advertising via Meta (Facebook) and scripts added by the organizer.',
|
|
],
|
|
'politique_cookie' => [
|
|
'fr' => 'Politique de témoins',
|
|
'en' => 'Cookie policy',
|
|
],
|
|
'politique_confidentialite' => [
|
|
'fr' => 'Politique de confidentialité',
|
|
'en' => 'Privacy policy',
|
|
],
|
|
];
|
|
}
|
|
|
|
function fxCookieConsentTextIsDraft(string $clef, string $text): bool
|
|
{
|
|
$text = trim($text);
|
|
|
|
if ($text === '' || $text === $clef || $text === '*' . $clef . '*') {
|
|
return true;
|
|
}
|
|
|
|
if (stripos($text, $clef) === 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function fxEnsureCookieConsentTexts(): void
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!isset($objDatabase)) {
|
|
return;
|
|
}
|
|
|
|
static $done = false;
|
|
|
|
if ($done) {
|
|
return;
|
|
}
|
|
|
|
$done = true;
|
|
|
|
foreach (fxCookieConsentDefaults() as $clef => $texts) {
|
|
foreach (['fr', 'en'] as $lang) {
|
|
if (!isset($texts[$lang])) {
|
|
continue;
|
|
}
|
|
|
|
$sql = "SELECT pk_info, info_texte FROM info
|
|
WHERE info_clef = '" . $objDatabase->fxEscape($clef) . "'
|
|
AND info_langue = '" . $objDatabase->fxEscape($lang) . "'
|
|
AND info_prg = 'global'
|
|
LIMIT 1";
|
|
$row = $objDatabase->fxGetRow($sql);
|
|
|
|
if (!$row) {
|
|
if (function_exists('fxSetInfo')) {
|
|
fxSetInfo('add', [
|
|
'info_clef' => $clef,
|
|
'info_langue' => $lang,
|
|
'info_texte' => $texts[$lang],
|
|
'info_aide' => '',
|
|
'info_prg' => 'global',
|
|
'info_actif' => 1,
|
|
], $lang);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!fxCookieConsentTextIsDraft($clef, (string) $row['info_texte'])) {
|
|
continue;
|
|
}
|
|
|
|
$targetText = fxCookieConsentDefaults()[$clef][$lang] ?? $texts[$lang];
|
|
|
|
$objDatabase->fxQuery(
|
|
"UPDATE info SET info_texte = '" . $objDatabase->fxEscape($targetText) . "', info_maj = NOW()
|
|
WHERE pk_info = " . intval($row['pk_info'])
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function fxCookieConsentText(string $clef, string $strLangue): string
|
|
{
|
|
$defaults = fxCookieConsentDefaults();
|
|
$lang = ($strLangue === 'en') ? 'en' : 'fr';
|
|
|
|
return $defaults[$clef][$lang] ?? $clef;
|
|
}
|
|
|
|
function fxCookieLegalPlaceholders(string $html): string
|
|
{
|
|
global $vClient, $vDomaine;
|
|
|
|
$org = htmlspecialchars((string) $vClient, ENT_QUOTES, 'UTF-8');
|
|
$domain = htmlspecialchars((string) $vDomaine, ENT_QUOTES, 'UTF-8');
|
|
$email = 'confidentialite@' . preg_replace('/^https?:\/\//', '', (string) parse_url($vDomaine, PHP_URL_HOST));
|
|
$date = date('Y-m-d');
|
|
|
|
$replacements = [
|
|
'[ORGANISATION]' => $org,
|
|
'[ORGANIZATION]' => $org,
|
|
'[SITE]' => $domain,
|
|
'[DATE]' => $date,
|
|
'[COURRIEL]' => $email,
|
|
'[EMAIL]' => $email,
|
|
];
|
|
|
|
return str_replace(array_keys($replacements), array_values($replacements), $html);
|
|
}
|
|
|
|
function fxCookiePolicyHtml(string $strLangue): string
|
|
{
|
|
if ($strLangue === 'en') {
|
|
return fxCookieLegalPlaceholders(<<<'HTML'
|
|
<p><em>Last updated: [DATE]</em></p>
|
|
|
|
<p>This cookie policy explains how <strong>[ORGANIZATION]</strong> uses cookies and similar technologies on the registration website <strong>[SITE]</strong>, operated on the MS1 Inscription platform (Progiweb inc.).</p>
|
|
|
|
<h3>What is a cookie?</h3>
|
|
<p>A cookie is a small file stored on your device when you visit a website. It helps the site remember information such as your language, session or cart contents.</p>
|
|
|
|
<h3>How to manage your choices</h3>
|
|
<p>When you first visit the site, a banner lets you <strong>accept all</strong>, <strong>refuse all</strong> or <strong>customize</strong> optional cookies. You can change your choices at any time by clicking the cookie icon in the footer.</p>
|
|
|
|
<h3>1. Essential cookies (always active)</h3>
|
|
<p>These cookies are necessary for the site to function. They do not require your consent.</p>
|
|
<ul>
|
|
<li><strong>Session cookie (PHPSESSID)</strong> — keeps you logged in, maintains your cart and forms. Duration: session, approximately 3 hours of inactivity.</li>
|
|
<li><strong>no_panier</strong> — identifies your registration cart. Duration: 10 hours.</li>
|
|
<li><strong>cookiesPreferences</strong> — remembers your cookie choices. Duration: 12 months.</li>
|
|
<li><strong>reCAPTCHA (Google)</strong> — protects forms against spam and abuse.</li>
|
|
</ul>
|
|
|
|
<h3>2. Analytics cookies (optional)</h3>
|
|
<p>Active only if you enable <em>Analytics</em> in the banner.</p>
|
|
<ul>
|
|
<li><strong>Google Analytics</strong> (_ga, _ga_*, _gid) — helps us understand how the site is used. Provider: Google LLC. Duration: up to 13 months.</li>
|
|
</ul>
|
|
|
|
<h3>3. Marketing cookies (optional)</h3>
|
|
<p>Active only if you enable <em>Marketing</em> in the banner and if enabled for the event.</p>
|
|
<ul>
|
|
<li><strong>Meta Pixel</strong> (_fbp, _fbc) — measures advertising effectiveness and conversions. Provider: Meta Platforms Inc. Duration: up to 90 days.</li>
|
|
<li><strong>Custom scripts</strong> — the event organizer may add additional tools for a specific event.</li>
|
|
</ul>
|
|
|
|
<h3>4. Payment cookies</h3>
|
|
<p>When you proceed to payment, <strong>PayPal</strong> may place cookies required to process your transaction securely. These cookies are used only during checkout.</p>
|
|
|
|
<h3>5. Similar technologies</h3>
|
|
<p>We may use local storage on your device to control how often certain informational messages are displayed. This data remains on your device.</p>
|
|
|
|
<h3>6. Cross-border transfers</h3>
|
|
<p>Some providers (Google, Meta, PayPal) may process data outside Quebec, including in the United States. Contractual and technical safeguards are in place.</p>
|
|
|
|
<h3>7. Your rights</h3>
|
|
<p>Under Quebec Law 25, you may withdraw your consent for optional cookies at any time. For any questions: <a href="mailto:[EMAIL]">[EMAIL]</a>.</p>
|
|
<p>See also our <a href="[SITE]/page/confidentialite/en">privacy policy</a>.</p>
|
|
HTML
|
|
);
|
|
}
|
|
|
|
return fxCookieLegalPlaceholders(<<<'HTML'
|
|
<p><em>Dernière mise à jour : [DATE]</em></p>
|
|
|
|
<p>La présente politique explique comment <strong>[ORGANISATION]</strong> utilise des témoins (cookies) et technologies similaires sur le site d'inscription <strong>[SITE]</strong>, exploité via la plateforme MS1 Inscription (Progiweb inc.).</p>
|
|
|
|
<h3>Qu'est-ce qu'un témoin?</h3>
|
|
<p>Un témoin est un petit fichier déposé sur votre appareil lors d'une visite. Il permet au site de mémoriser certaines informations, comme votre langue, votre session ou le contenu de votre panier.</p>
|
|
|
|
<h3>Comment gérer vos choix</h3>
|
|
<p>Lors de votre première visite, un bandeau vous permet d'<strong>accepter tout</strong>, de <strong>tout refuser</strong> ou de <strong>personnaliser</strong> les témoins optionnels. Vous pouvez modifier vos choix en tout temps en cliquant sur l'icône témoins dans le pied de page.</p>
|
|
|
|
<h3>1. Témoins essentiels (toujours actifs)</h3>
|
|
<p>Ces témoins sont nécessaires au fonctionnement du site. Ils ne requièrent pas votre consentement.</p>
|
|
<ul>
|
|
<li><strong>Témoin de session (PHPSESSID)</strong> — maintient votre connexion, votre panier et vos formulaires. Durée : session, environ 3 heures d'inactivité.</li>
|
|
<li><strong>no_panier</strong> — identifie votre panier d'inscription. Durée : 10 heures.</li>
|
|
<li><strong>cookiesPreferences</strong> — mémorise vos choix de témoins. Durée : 12 mois.</li>
|
|
<li><strong>reCAPTCHA (Google)</strong> — protège les formulaires contre le pourriel et les abus.</li>
|
|
</ul>
|
|
|
|
<h3>2. Témoins analytiques (optionnels)</h3>
|
|
<p>Actifs seulement si vous activez la <em>mesure d'audience</em> dans le bandeau.</p>
|
|
<ul>
|
|
<li><strong>Google Analytics</strong> (_ga, _ga_*, _gid) — nous aide à comprendre l'utilisation du site. Fournisseur : Google LLC. Durée : jusqu'à 13 mois.</li>
|
|
</ul>
|
|
|
|
<h3>3. Témoins marketing (optionnels)</h3>
|
|
<p>Actifs seulement si vous activez le <em>marketing</em> dans le bandeau et si l'organisateur les a activés pour l'événement.</p>
|
|
<ul>
|
|
<li><strong>Pixel Meta</strong> (_fbp, _fbc) — mesure l'efficacité publicitaire et les conversions. Fournisseur : Meta Platforms inc. Durée : jusqu'à 90 jours.</li>
|
|
<li><strong>Scripts personnalisés</strong> — l'organisateur de l'événement peut ajouter d'autres outils pour un événement précis.</li>
|
|
</ul>
|
|
|
|
<h3>4. Témoins de paiement</h3>
|
|
<p>Lors du paiement, <strong>PayPal</strong> peut déposer des témoins nécessaires au traitement sécurisé de la transaction. Ces témoins sont utilisés uniquement lors du passage à la caisse.</p>
|
|
|
|
<h3>5. Technologies similaires</h3>
|
|
<p>Nous pouvons utiliser le stockage local de votre navigateur pour contrôler la fréquence d'affichage de certains messages informatifs. Ces données restent sur votre appareil.</p>
|
|
|
|
<h3>6. Transferts hors Québec</h3>
|
|
<p>Certains fournisseurs (Google, Meta, PayPal) peuvent traiter des données à l'extérieur du Québec, notamment aux États-Unis. Des mesures contractuelles et techniques sont en place.</p>
|
|
|
|
<h3>7. Vos droits</h3>
|
|
<p>Conformément à la Loi 25, vous pouvez retirer votre consentement pour les témoins optionnels en tout temps. Pour toute question : <a href="mailto:[COURRIEL]">[COURRIEL]</a>.</p>
|
|
<p>Consultez aussi notre <a href="[SITE]/page/confidentialite/fr">politique de confidentialité</a>.</p>
|
|
HTML
|
|
);
|
|
}
|
|
|
|
function fxPrivacyPolicyHtml(string $strLangue): string
|
|
{
|
|
if ($strLangue === 'en') {
|
|
return fxCookieLegalPlaceholders(<<<'HTML'
|
|
<p><em>Last updated: [DATE]</em></p>
|
|
|
|
<p><strong>[ORGANIZATION]</strong> (the "Organizer") respects your privacy. This policy describes how we collect, use and protect personal information when you use our registration website <strong>[SITE]</strong>, in accordance with Quebec's Act respecting the protection of personal information in the private sector (Law 25).</p>
|
|
|
|
<p>The site is operated on the MS1 Inscription platform by Progiweb inc., which acts as a technical service provider for the Organizer.</p>
|
|
|
|
<h3>1. Person responsible for the protection of personal information</h3>
|
|
<p>For any privacy-related request:</p>
|
|
<p><strong>Email:</strong> <a href="mailto:[EMAIL]">[EMAIL]</a></p>
|
|
|
|
<h3>2. Personal information we collect</h3>
|
|
<p>Depending on your registration, we may collect:</p>
|
|
<ul>
|
|
<li><strong>Identity and contact:</strong> name, address, city, province, postal code, email, phone, date of birth, sex;</li>
|
|
<li><strong>Registration:</strong> category, race, team, bib number, answers to organizer questions;</li>
|
|
<li><strong>Account:</strong> login credentials if you create an account;</li>
|
|
<li><strong>Payment:</strong> amount, payment method, transaction ID (card numbers are processed by PayPal — we do not store them);</li>
|
|
<li><strong>Technical data:</strong> IP address, browser type, pages visited, cookies (see our <a href="[SITE]/page/cookie/en">cookie policy</a>).</li>
|
|
</ul>
|
|
|
|
<h3>3. Purposes of collection</h3>
|
|
<ul>
|
|
<li>Process and confirm your event registration;</li>
|
|
<li>Manage payments, refunds and order-related communications;</li>
|
|
<li>Send confirmations, reminders and practical event information;</li>
|
|
<li>Ensure site security and prevent fraud;</li>
|
|
<li>Produce visit statistics and measure advertising campaigns, <strong>only with your cookie consent</strong>.</li>
|
|
</ul>
|
|
|
|
<h3>4. Legal basis</h3>
|
|
<ul>
|
|
<li><strong>Contract:</strong> registration and payment processing;</li>
|
|
<li><strong>Legal obligation:</strong> retention of certain accounting records;</li>
|
|
<li><strong>Legitimate interest:</strong> site security and fraud prevention;</li>
|
|
<li><strong>Consent:</strong> non-essential cookies and marketing communications, where applicable.</li>
|
|
</ul>
|
|
|
|
<h3>5. Third parties and service providers</h3>
|
|
<p>Your information may be shared with:</p>
|
|
<ul>
|
|
<li><strong>Progiweb inc. (MS1 Inscription)</strong> — hosting and platform operation;</li>
|
|
<li><strong>PayPal</strong> — payment processing;</li>
|
|
<li><strong>Google</strong> — reCAPTCHA (security); Google Analytics (if consented);</li>
|
|
<li><strong>Meta (Facebook)</strong> — advertising pixel (if consented);</li>
|
|
<li><strong>Event organizer and partners</strong> — race management, timing, bib pickup.</li>
|
|
</ul>
|
|
<p>We do not sell your personal information.</p>
|
|
|
|
<h3>6. Cross-border transfers</h3>
|
|
<p>Some service providers may process data outside Quebec. We require appropriate contractual and security measures in such cases.</p>
|
|
|
|
<h3>7. Retention period</h3>
|
|
<ul>
|
|
<li>Confirmed registration data: retained for the period required by the Organizer and applicable laws;</li>
|
|
<li>Uncompleted cart: up to 10 hours;</li>
|
|
<li>Session: approximately 3 hours of inactivity;</li>
|
|
<li>Accounting and transaction records: minimum 6 years where required by law.</li>
|
|
</ul>
|
|
|
|
<h3>8. Security</h3>
|
|
<p>We apply reasonable measures including HTTPS encryption, access controls and backups. No method is completely risk-free.</p>
|
|
|
|
<h3>9. Your rights</h3>
|
|
<p>You may request access to, correction or deletion of your personal information, or withdraw your consent where applicable. Contact: <a href="mailto:[EMAIL]">[EMAIL]</a>. We will respond within a reasonable time, generally within 30 days.</p>
|
|
<p>You may also file a complaint with the Commission d'accès à l'information du Québec (CAI): <a href="https://www.cai.gouv.qc.ca" target="_blank" rel="noopener">www.cai.gouv.qc.ca</a>.</p>
|
|
|
|
<h3>10. Minors</h3>
|
|
<p>Some events involve minor participants. We collect only information necessary for registration and event safety. Parental consent may be required depending on the event.</p>
|
|
|
|
<h3>11. Privacy incidents</h3>
|
|
<p>In the event of an incident presenting a risk of serious harm, we will notify the CAI and affected individuals as required by law.</p>
|
|
|
|
<h3>12. Changes</h3>
|
|
<p>We may update this policy. The date above indicates the latest revision. Material changes may be communicated by email or site notice.</p>
|
|
HTML
|
|
);
|
|
}
|
|
|
|
return fxCookieLegalPlaceholders(<<<'HTML'
|
|
<p><em>Dernière mise à jour : [DATE]</em></p>
|
|
|
|
<p><strong>[ORGANISATION]</strong> (l'« Organisateur ») respecte votre vie privée. La présente politique décrit comment nous collectons, utilisons et protégeons vos renseignements personnels lorsque vous utilisez notre site d'inscription <strong>[SITE]</strong>, conformément à la <em>Loi sur la protection des renseignements personnels dans le secteur privé</em> (Loi 25).</p>
|
|
|
|
<p>Le site est exploité sur la plateforme MS1 Inscription par Progiweb inc., qui agit à titre de mandataire technique pour l'Organisateur.</p>
|
|
|
|
<h3>1. Responsable de la protection des renseignements personnels</h3>
|
|
<p>Pour toute demande relative à la confidentialité :</p>
|
|
<p><strong>Courriel :</strong> <a href="mailto:[COURRIEL]">[COURRIEL]</a></p>
|
|
|
|
<h3>2. Renseignements personnels collectés</h3>
|
|
<p>Selon votre inscription, nous pouvons collecter :</p>
|
|
<ul>
|
|
<li><strong>Identité et coordonnées :</strong> nom, adresse, ville, province, code postal, courriel, téléphone, date de naissance, sexe;</li>
|
|
<li><strong>Inscription :</strong> catégorie, épreuve, équipe, numéro de dossard, réponses aux questions de l'organisateur;</li>
|
|
<li><strong>Compte :</strong> identifiants de connexion si vous créez un compte;</li>
|
|
<li><strong>Paiement :</strong> montant, mode de paiement, identifiant de transaction (les numéros de carte sont traités par PayPal — nous ne les conservons pas);</li>
|
|
<li><strong>Données techniques :</strong> adresse IP, type de navigateur, pages visitées, témoins (voir notre <a href="[SITE]/page/cookie/fr">politique de témoins</a>).</li>
|
|
</ul>
|
|
|
|
<h3>3. Finalités de la collecte</h3>
|
|
<ul>
|
|
<li>Traiter et confirmer votre inscription à l'événement;</li>
|
|
<li>Gérer les paiements, remboursements et communications liées à votre commande;</li>
|
|
<li>Envoyer confirmations, rappels et informations pratiques sur l'événement;</li>
|
|
<li>Assurer la sécurité du site et prévenir la fraude;</li>
|
|
<li>Produire des statistiques de visite et mesurer des campagnes publicitaires, <strong>seulement avec votre consentement aux témoins</strong>.</li>
|
|
</ul>
|
|
|
|
<h3>4. Fondements</h3>
|
|
<ul>
|
|
<li><strong>Exécution du contrat :</strong> inscription et traitement du paiement;</li>
|
|
<li><strong>Obligation légale :</strong> conservation de certains documents comptables;</li>
|
|
<li><strong>Intérêt légitime :</strong> sécurité du site et prévention de la fraude;</li>
|
|
<li><strong>Consentement :</strong> témoins non essentiels et communications marketing, le cas échéant.</li>
|
|
</ul>
|
|
|
|
<h3>5. Tiers et fournisseurs de services</h3>
|
|
<p>Vos renseignements peuvent être communiqués à :</p>
|
|
<ul>
|
|
<li><strong>Progiweb inc. (MS1 Inscription)</strong> — hébergement et exploitation de la plateforme;</li>
|
|
<li><strong>PayPal</strong> — traitement des paiements;</li>
|
|
<li><strong>Google</strong> — reCAPTCHA (sécurité); Google Analytics (si consenti);</li>
|
|
<li><strong>Meta (Facebook)</strong> — pixel publicitaire (si consenti);</li>
|
|
<li><strong>Organisateur et partenaires de l'événement</strong> — gestion de la course, chronométrage, remise des dossards.</li>
|
|
</ul>
|
|
<p>Nous ne vendons pas vos renseignements personnels.</p>
|
|
|
|
<h3>6. Transferts hors Québec</h3>
|
|
<p>Certains mandataires peuvent traiter des renseignements à l'extérieur du Québec. Nous exigeons des mesures contractuelles et de sécurité appropriées.</p>
|
|
|
|
<h3>7. Durée de conservation</h3>
|
|
<ul>
|
|
<li>Données d'inscription confirmée : conservées pour la période requise par l'Organisateur et les lois applicables;</li>
|
|
<li>Panier non finalisé : jusqu'à 10 heures;</li>
|
|
<li>Session : environ 3 heures d'inactivité;</li>
|
|
<li>Documents comptables et transactions : minimum 6 ans lorsque exigé par la loi.</li>
|
|
</ul>
|
|
|
|
<h3>8. Sécurité</h3>
|
|
<p>Nous appliquons des mesures raisonnables incluant le chiffrement HTTPS, des contrôles d'accès et des sauvegardes. Aucune méthode n'est toutefois sans risque.</p>
|
|
|
|
<h3>9. Vos droits</h3>
|
|
<p>Vous pouvez demander l'accès à vos renseignements, leur rectification ou leur suppression, ou retirer votre consentement lorsque applicable. Contact : <a href="mailto:[COURRIEL]">[COURRIEL]</a>. Nous répondrons dans un délai raisonnable, généralement sous 30 jours.</p>
|
|
<p>Vous pouvez aussi déposer une plainte auprès de la Commission d'accès à l'information du Québec (CAI) : <a href="https://www.cai.gouv.qc.ca" target="_blank" rel="noopener">www.cai.gouv.qc.ca</a>.</p>
|
|
|
|
<h3>10. Mineurs</h3>
|
|
<p>Certains événements concernent des participants mineurs. Nous collectons seulement les renseignements nécessaires à l'inscription et à la sécurité. Un consentement parental peut être requis selon l'événement.</p>
|
|
|
|
<h3>11. Incidents de confidentialité</h3>
|
|
<p>En cas d'incident présentant un risque de préjudice grave, nous aviserons la CAI et les personnes concernées conformément à la loi.</p>
|
|
|
|
<h3>12. Modifications</h3>
|
|
<p>Nous pouvons mettre à jour cette politique. La date ci-dessus indique la dernière révision. Les changements importants pourront être communiqués par courriel ou avis sur le site.</p>
|
|
HTML
|
|
);
|
|
}
|
|
|
|
function fxLegalPageNeedsSeed(array $row): bool
|
|
{
|
|
if (trim((string) ($row['pag_texte_fr'] ?? '')) === '' || trim((string) ($row['pag_texte_en'] ?? '')) === '') {
|
|
return true;
|
|
}
|
|
|
|
$plainFr = trim(strip_tags((string) $row['pag_texte_fr']));
|
|
|
|
return strlen($plainFr) < 500;
|
|
}
|
|
|
|
function fxLegalLabelIsDraft(string $label): bool
|
|
{
|
|
$label = trim($label);
|
|
|
|
if ($label === '') {
|
|
return true;
|
|
}
|
|
|
|
// Un libellé qui contient un underscore ressemble à une clé technique
|
|
// (ex. "politique_cookie") plutôt qu'à un vrai libellé.
|
|
if (strpos($label, '_') !== false) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function fxEnsureLegalPage(string $code, string $labelFr, string $labelEn, string $titleFr, string $titleEn, callable $bodyFr, callable $bodyEn, int $sort = 90): void
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!isset($objDatabase)) {
|
|
return;
|
|
}
|
|
|
|
$sql = "SELECT * FROM inscriptions_pages WHERE pag_code = '" . $objDatabase->fxEscape($code) . "' LIMIT 1";
|
|
$row = $objDatabase->fxGetRow($sql);
|
|
|
|
$textFr = $bodyFr();
|
|
$textEn = $bodyEn();
|
|
|
|
if (!$row) {
|
|
$sqlInsert = "INSERT INTO inscriptions_pages
|
|
(pag_code, pag_label_fr, pag_label_en, pag_titre_fr, pag_titre_en, pag_texte_fr, pag_texte_en, pag_tri, pag_maj, pag_menu, pag_actif)
|
|
VALUES (
|
|
'" . $objDatabase->fxEscape($code) . "',
|
|
'" . $objDatabase->fxEscape($labelFr) . "',
|
|
'" . $objDatabase->fxEscape($labelEn) . "',
|
|
'" . $objDatabase->fxEscape($titleFr) . "',
|
|
'" . $objDatabase->fxEscape($titleEn) . "',
|
|
'" . $objDatabase->fxEscape($textFr) . "',
|
|
'" . $objDatabase->fxEscape($textEn) . "',
|
|
" . intval($sort) . ",
|
|
NOW(),
|
|
1,
|
|
1
|
|
)";
|
|
$objDatabase->fxQuery($sqlInsert);
|
|
|
|
return;
|
|
}
|
|
|
|
$updates = [];
|
|
|
|
if (fxLegalPageNeedsSeed($row)) {
|
|
$updates[] = "pag_texte_fr = '" . $objDatabase->fxEscape($textFr) . "'";
|
|
$updates[] = "pag_texte_en = '" . $objDatabase->fxEscape($textEn) . "'";
|
|
}
|
|
|
|
if (fxLegalLabelIsDraft((string) $row['pag_label_fr'])) {
|
|
$updates[] = "pag_label_fr = '" . $objDatabase->fxEscape($labelFr) . "'";
|
|
}
|
|
|
|
if (fxLegalLabelIsDraft((string) $row['pag_label_en'])) {
|
|
$updates[] = "pag_label_en = '" . $objDatabase->fxEscape($labelEn) . "'";
|
|
}
|
|
|
|
if (fxLegalLabelIsDraft((string) $row['pag_titre_fr'])) {
|
|
$updates[] = "pag_titre_fr = '" . $objDatabase->fxEscape($titleFr) . "'";
|
|
}
|
|
|
|
if (fxLegalLabelIsDraft((string) $row['pag_titre_en'])) {
|
|
$updates[] = "pag_titre_en = '" . $objDatabase->fxEscape($titleEn) . "'";
|
|
}
|
|
|
|
if ((int) $row['pag_menu'] !== 1) {
|
|
$updates[] = 'pag_menu = 1';
|
|
}
|
|
|
|
if ((int) $row['pag_actif'] !== 1) {
|
|
$updates[] = 'pag_actif = 1';
|
|
}
|
|
|
|
if ($updates) {
|
|
$updates[] = 'pag_maj = NOW()';
|
|
$objDatabase->fxQuery('UPDATE inscriptions_pages SET ' . implode(', ', $updates) . " WHERE pag_id = " . intval($row['pag_id']));
|
|
}
|
|
}
|
|
|
|
function fxEnsureLegalPages(): void
|
|
{
|
|
static $done = false;
|
|
|
|
if ($done) {
|
|
return;
|
|
}
|
|
|
|
$done = true;
|
|
|
|
fxEnsureCookieConsentTexts();
|
|
|
|
fxEnsureLegalPage(
|
|
'cookie',
|
|
'Témoins',
|
|
'Cookies',
|
|
'Politique de témoins',
|
|
'Cookie policy',
|
|
static function () {
|
|
return fxCookiePolicyHtml('fr');
|
|
},
|
|
static function () {
|
|
return fxCookiePolicyHtml('en');
|
|
},
|
|
98
|
|
);
|
|
|
|
fxEnsureLegalPage(
|
|
'confidentialite',
|
|
'Confidentialité',
|
|
'Privacy',
|
|
'Politique de confidentialité',
|
|
'Privacy policy',
|
|
static function () {
|
|
return fxPrivacyPolicyHtml('fr');
|
|
},
|
|
static function () {
|
|
return fxPrivacyPolicyHtml('en');
|
|
},
|
|
99
|
|
);
|
|
}
|
|
|
|
function fxCookiePolicyPageContent(string $strLangue): string
|
|
{
|
|
return fxCookiePolicyHtml($strLangue);
|
|
}
|
|
|
|
function fxPrivacyPolicyPageContent(string $strLangue): string
|
|
{
|
|
return fxPrivacyPolicyHtml($strLangue);
|
|
}
|