Hooks synchronisation, webhooks et contrôle d’accès

Disponible dans :Pro

Ces hooks de HappenBoard Pro interviennent là où votre site échange avec d’autres systèmes, et à l’entrée de l’événement. Ils couvrent les webhooks sortants et Slack, la synchronisation des agendas Google et Outlook, le scanner de check-in et l’impression des badges.

La configuration des webhooks est décrite dans Les webhooks sortants. Celle du scanner est dans Le check-in par QR code. Si les hooks sont nouveaux pour vous, commencez par Étendre HappenBoard avec les hooks.

Vérifier la signature d’un webhook

Chaque envoi de webhook est un POST dont le corps JSON contient event, delivered_at, delivery_id et data. Il porte ces en-têtes :

  • X-HappenBoard-Event : la clé de l’événement, par exemple rsvp.created.
  • X-HappenBoard-Delivery : un identifiant qui reste le même à chaque nouvelle tentative d’un même envoi.
  • X-HappenBoard-Timestamp : l’heure Unix de cette tentative.
  • X-HappenBoard-Signature-V1 : t=<timestamp>,v1=<hex>, un HMAC-SHA256 de l’horodatage, d’un point et du corps brut, calculé avec le secret de signature du webhook.
  • X-HappenBoard-Signature : sha256=<hex>, un HMAC du corps seul. Il reste envoyé pour les anciens destinataires, mais ne protège pas contre le rejeu.

Comparez la signature v1 en temps constant et refusez un horodatage éloigné de plus de cinq minutes de votre horloge. Modifier t casse la signature : une requête interceptée ne peut donc pas être rejouée plus tard.

Code
// $secret est le secret de signature du webhook.
parse_str( str_replace( ',', '&', $_SERVER['HTTP_X_HAPPENBOARD_SIGNATURE_V1'] ?? '' ), $sig );
$t  = (string) ( $sig['t'] ?? '' );
$ok = ctype_digit( $t )
    && abs( time() - (int) $t ) <= 300
    && hash_equals( hash_hmac( 'sha256', $t . '.' . file_get_contents( 'php://input' ), $secret ), (string) ( $sig['v1'] ?? '' ) );

Calculez le HMAC sur le corps tel qu’il est arrivé, avant de décoder le JSON. Servez-vous ensuite de X-HappenBoard-Delivery pour ignorer un envoi déjà traité : chaque nouvelle tentative garde l’identifiant mais reçoit un nouvel horodatage.

Le secret de signature ne s’affiche qu’une fois : à la création du webhook, puis chaque fois que quelqu’un clique sur Generate a new secret dans son éditeur. Ensuite, la liste des webhooks n’en montre que les quatre derniers caractères. Côté REST, POST /happenboard/v1/pro/webhooks renvoie le nouveau secret une seule fois, et POST /happenboard/v1/pro/webhooks/{id}/secret le remplace.

Nouvelles tentatives et mise en pause

Les envois partent dans une tâche de fond, jamais dans la requête qui les a déclenchés. Un échec qui semble passager (aucune réponse, délai dépassé, HTTP 408, 429 ou 5xx) est retenté 1, 4, 16, 64 puis 256 minutes plus tard : six tentatives sur environ six heures. Les nouvelles tentatives passent par Action Scheduler s’il est installé, par WP-Cron sinon. Toute autre réponse est définitive, et les redirections ne sont jamais suivies.

Chaque tentative ratée ajoute un au compteur d’échecs consécutifs du webhook, et une réponse 2xx le remet à zéro. À 50, Pro désactive le webhook, ses tentatives en attente s’arrêtent, la liste l’affiche comme Paused et l’administrateur du site reçoit un e-mail. Un webhook qui avait déjà dépassé la limite est désactivé dès que la carte Webhooks en affiche la liste. Le réactiver remet le compteur à zéro.

Le bouton Test envoie tout de suite un événement webhook.test. Il déclenche les hooks d’envoi comme une vraie tentative, mais n’est jamais retenté ni compté.

Le check-in à l’entrée

  • Chaque scan appelle POST /happenboard/v1/pro/checkin/mark avec le code du billet, et l’événement choisi dans Event at this door s’il y en a un.
  • Un code de billet qui échoue à la vérification reçoit une erreur HTTP 400 et compte pour le blocage (happenboard_pro_checkin_lockout).
  • Un billet authentique est refusé avec une erreur HTTP 409 s’il est pour un autre événement, si sa réservation ne détient aucune place, ou s’il est pour une autre date d’un événement récurrent. Cela déclenche happenboard_pro_attendee_checkin_refused.
  • Un scan accepté déclenche happenboard_pro_attendee_checked_in, documenté avec les hooks participants.
  • Le bouton Undo du scanner supprime ce check-in et déclenche happenboard_pro_attendee_checkin_undone.

Les filtres qui façonnent l’événement envoyé à Google et Outlook sont documentés avec les hooks événements.

happenboard_pro_webhook_delivered

Action Pro src/Service/Webhooks/Sender.php

Se déclenche après chaque tentative d’envoi de webhook qui reçoit une réponse HTTP, quel que soit son code. Testez $status pour distinguer un succès d’un refus.

Signature

do_action( 'happenboard_pro_webhook_delivered', array $webhook, string $event, array $data, int $status, string $body )

Paramètres

$webhook array<string,mixed>
Le webhook : id, label, url, secret, events, active, createdUtc, updatedUtc et lastResult (utc, status, error et failures de la tentative précédente). Il contient le secret de signature : ne l’écrivez jamais en entier dans un journal.
$event string
La clé de l’événement, aussi envoyée dans X-HappenBoard-Event : rsvp.created, rsvp.cancelled, attendee.status_changed, attendee.checked_in, attendee.checkin_undone, attendee.deleted, ou webhook.test pour le test.
$data array<string,mixed>
Les données envoyées dans la clé data du corps. Le nom et l’e-mail du participant sont relus dans sa fiche à chaque tentative : une personne effacée entre-temps est envoyée telle que l’effacement l’a laissée.
$status int
Code HTTP de la réponse. Seuls 200 à 299 comptent comme un envoi réussi.
$body string
Le corps brut de la réponse.

Exemple

add_action(
    'happenboard_pro_webhook_delivered',
    function ( $webhook, $event, $data, $status, $body ) {
        if ( $status >= 200 && $status < 300 ) {
            return; // Envoi réussi.
        }
        // Ce hook se déclenche aussi pour les réponses 3xx, 4xx et 5xx.
        error_log( sprintf(
            'Webhook %s to %s answered HTTP %d: %s',
            $event,
            (string) ( $webhook['url'] ?? '' ),
            $status,
            substr( $body, 0, 200 )
        ) );
    },
    10,
    5
);

Remarques

  • Cinq arguments sont passés : enregistrez le hook avec 10, 5.
  • Malgré son nom, il se déclenche pour toute réponse HTTP, codes d’erreur compris, et à chaque tentative : un destinataire qui répond 500 peut le déclencher six fois pour un même envoi.
  • Une tentative arrêtée avant l’envoi ne déclenche rien : une URL qui ne pointe pas vers une adresse publique, ou un port autre que 80, 443 et 8080. Le filtre WordPress http_allowed_safe_ports peut élargir cette liste de ports.
  • Pro ne garde que le dernier résultat sur le webhook, celui qu’affiche la liste d’administration. Pour un historique des envois, enregistrez-les ici.

happenboard_pro_webhook_failed

Action Pro src/Service/Webhooks/Sender.php

Se déclenche quand une tentative d’envoi de webhook ne reçoit aucune réponse HTTP : échec DNS, connexion refusée, erreur TLS ou délai de 5 secondes dépassé. Il transmet le message d’erreur.

Signature

do_action( 'happenboard_pro_webhook_failed', array $webhook, string $event, array $data, string $error )

Paramètres

$webhook array<string,mixed>
Le webhook, avec les mêmes clés que dans happenboard_pro_webhook_delivered, secret de signature compris.
$event string
La clé de l’événement, par exemple attendee.checked_in, ou webhook.test pour le test.
$data array<string,mixed>
Les données qui devaient partir dans la clé data du corps.
$error string
Le message du WP_Error renvoyé par le client HTTP, par exemple un délai cURL dépassé.

Exemple

add_action(
    'happenboard_pro_webhook_failed',
    function ( $webhook, $event, $data, $error ) {
        // Pro retente seul : une seule alerte, au troisième échec d'affilée.
        $failures = (int) ( $webhook['lastResult']['failures'] ?? 0 ) + 1;
        if ( 3 !== $failures ) {
            return;
        }
        wp_mail(
            get_option( 'admin_email' ),
            'Webhook unreachable',
            sprintf( '%s (%s): %s', (string) ( $webhook['url'] ?? '' ), $event, $error )
        );
    },
    10,
    4
);

Remarques

  • Quatre arguments sont passés : enregistrez le hook avec 10, 4.
  • Pro retente déjà ces échecs et déclenche le hook à chaque tentative. Servez-vous-en pour alerter ou journaliser, pas pour renvoyer, sinon le destinataire reçoit des doublons.
  • Un destinataire qui répond avec un code d’erreur, 500 par exemple, déclenche happenboard_pro_webhook_delivered à la place. Écoutez les deux pour voir chaque tentative.
  • Pour une adresse qui reste injoignable, happenboard_pro_webhook_auto_paused vous donne une seule alerte, au moment où Pro abandonne.

happenboard_pro_webhook_auto_pause_after

Filtre Pro src/Service/Webhooks/Repository.php

Filtre le nombre de tentatives ratées d’affilée après lequel un webhook est désactivé. Renvoyez 0 pour ne jamais en désactiver.

Signature

apply_filters( 'happenboard_pro_webhook_auto_pause_after', int $attempts )

Paramètres

$attempts int
Par défaut 50, soit un peu plus de huit événements à raison de six tentatives chacun.

Valeur de retour

int Nombre de tentatives ratées d’affilée avant la désactivation. Une valeur négative compte comme 0.

Exemple

add_filter(
    'happenboard_pro_webhook_auto_pause_after',
    function ( $attempts ) {
        // Notre CRM a de longues maintenances : laissons-lui plus de marge.
        return 200;
    }
);

Remarques

  • Toute tentative ratée compte, nouvelles tentatives comprises : pas de réponse, une réponse autre que 2xx, ou une URL refusée avant l’envoi. Une réponse 2xx remet le compteur à zéro. Les tests ne comptent pas.
  • La limite est vérifiée quand un échec est enregistré, et quand la carte Webhooks affiche la liste des webhooks. Un webhook déjà au-delà, ou au-delà d’une valeur plus basse que vous venez de fixer, est désactivé à la prochaine ouverture de la carte ou au prochain échec.
  • La liste des webhooks le lit aussi, pour distinguer un webhook désactivé pour échecs (autoPaused, affiché Paused) d’un webhook désactivé à la main.
  • Réactiver le webhook, dans le panneau ou avec PATCH /happenboard/v1/pro/webhooks/{id}, remet le compteur à zéro.

happenboard_pro_webhook_auto_paused

Action Pro src/Service/Webhooks/Repository.php

Se déclenche une fois quand un webhook est désactivé après trop d’échecs d’envoi d’affilée. Pro s’en sert déjà pour envoyer un e-mail à l’adresse d’administration du site. Servez-vous-en pour prévenir quelqu’un d’autre : ce destinataire ne reçoit plus rien tant que le webhook n’est pas réactivé.

Signature

do_action( 'happenboard_pro_webhook_auto_paused', int $webhook_id, int $failures )

Paramètres

$webhook_id int
Identifiant du webhook désactivé.
$failures int
Échecs d’envoi d’affilée au moment de la désactivation : la limite (happenboard_pro_webhook_auto_pause_after, 50 par défaut), ou davantage pour un webhook qui l’avait déjà dépassée.

Exemple

add_action(
    'happenboard_pro_webhook_auto_paused',
    function ( $webhook_id, $failures ) {
        // Pro prévient déjà l’administrateur du site : prévenez aussi le développeur.
        wp_mail(
            '[email protected]',
            'Webhook désactivé',
            sprintf(
                'Le webhook #%d a échoué %d fois de suite et a été désactivé. Réparez le destinataire, puis réactivez-le dans HappenBoard > Integrations > Webhooks (Pro).',
                $webhook_id,
                $failures
            )
        );
    },
    10,
    2
);

Remarques

  • Deux arguments sont passés : enregistrez le hook avec 10, 2.
  • Il s’exécute en général dans la tâche d’envoi en arrière-plan, sans utilisateur connecté, juste après le hook d’envoi de la tentative qui a atteint la limite. Pour un webhook qui avait déjà dépassé la limite, il se déclenche dans la requête d’administration qui affiche la liste de la carte Webhooks.
  • Le webhook est désactivé par une seule mise à jour conditionnelle en base : deux envois qui échouent au même moment ne le déclenchent qu’une fois. Les nouvelles tentatives en attente pour ce webhook s’arrêtent.
  • Il ne se déclenche jamais quand quelqu’un désactive un webhook à la main, ni quand le filtre de limite renvoie 0.

happenboard_pro_slack_webhook_url_valid

Filtre Pro src/Settings/Repository.php

Filtre si une URL peut être enregistrée comme webhook Slack. Par défaut, seules les URL Incoming Webhook de Slack (https://hooks.slack.com/services/…) passent ; renvoyez true pour autoriser un service compatible Slack, comme Mattermost ou Rocket.Chat.

Signature

apply_filters( 'happenboard_pro_slack_webhook_url_valid', bool $valid, string $url )

Paramètres

$valid bool
Indique si l’URL correspond au format des Incoming Webhooks de Slack.
$url string
L’URL telle que saisie, sans les espaces autour.

Valeur de retour

bool true pour accepter l’URL.

Exemple

add_filter(
    'happenboard_pro_slack_webhook_url_valid',
    function ( $valid, $url ) {
        // Accepter aussi nos webhooks entrants Mattermost.
        return $valid || str_starts_with( $url, 'https://chat.example.org/hooks/' );
    },
    10,
    2
);

Remarques

  • Deux arguments sont passés : enregistrez le hook avec 10, 2.
  • L’URL doit toujours commencer par https://. Renvoyer true pour une URL en http:// ne la fait pas enregistrer.
  • Il s’exécute à l’enregistrement des réglages de Pro, depuis la carte Slack ou POST /happenboard/v1/pro/settings. Une URL refusée renvoie une erreur HTTP 400 happenboard_slack_url_invalid. Chaque message vérifie encore, à l’envoi, que l’hôte est public.
  • Le destinataire reçoit le format de message de Slack (text et des blocks Block Kit), sans signature : l’URL elle-même tient lieu de secret.

happenboard_pro_attendee_checkin_refused

Action Pro src/REST/Checkin.php

Se déclenche quand le scanner refuse un billet authentique : il est pour un autre événement, sa réservation ne détient aucune place, ou il est pour une autre date d’un événement récurrent. Aucun check-in n’est enregistré.

Signature

do_action( 'happenboard_pro_attendee_checkin_refused', int $attendee_id, int $event_id, string $status, int $seat_index, string $source, string $reason, int $scanned_for )

Paramètres

$attendee_id int
Participant dont le billet a été scanné.
$event_id int
L’événement du billet.
$status string
Le statut du participant au moment du scan, par exemple going, cancelled, waitlist ou declined. Seul going donne accès.
$seat_index int
Place concernée, comptée à partir de 0 (0 aussi pour un QR code unique qui couvre toute la réservation).
$source string
Source du scan envoyée par le scanner, qr par défaut.
$reason string
wrong_event (billet d’un autre événement), status (la réservation ne détient aucune place), wrong_date (autre date de la série) ou date_gone (sa date a été annulée ou retirée).
$scanned_for int
L’événement choisi dans Event at this door, ou 0 quand le scanner accepte tous les événements.

Exemple

add_action(
    'happenboard_pro_attendee_checkin_refused',
    function ( $attendee_id, $event_id, $status, $seat_index, $source, $reason, $scanned_for ) {
        if ( 'wrong_event' !== $reason ) {
            return;
        }
        error_log( sprintf(
            'Ticket of attendee %d (event %d) was scanned at the door of event %d.',
            $attendee_id,
            $event_id,
            $scanned_for
        ) );
    },
    10,
    7
);

Remarques

  • Sept arguments sont passés. Enregistrez le hook avec 10, 7 pour recevoir $reason et $scanned_for.
  • L’événement est vérifié en premier : avec wrong_event, le statut peut être n’importe lequel. Un billet réservé sur une traduction de l’événement (WPML ou Polylang) compte comme le même événement.
  • Il ne se déclenche que depuis POST /happenboard/v1/pro/checkin/mark. La route verify et l’ability check-in-attendee peuvent aussi refuser un billet, mais sans le déclencher.
  • Le scan répond HTTP 409 avec happenboard_pro_attendee_not_admissible et la raison dans les données de l’erreur. Le journal d’activité de Pro l’enregistre comme attendee.checkin_refused, en priorité 10.

happenboard_pro_attendee_checkin_undone

Action Pro src/REST/Checkin.php

Se déclenche après l’annulation d’un check-in fait par erreur, quand le personnel clique sur Undo dans le scanner. La ligne du check-in est déjà supprimée.

Signature

do_action( 'happenboard_pro_attendee_checkin_undone', int $checkin_id, int $attendee_id, int $event_id, int $seat_index )

Paramètres

$checkin_id int
Identifiant du check-in annulé, celui que happenboard_pro_attendee_checked_in avait transmis pour ce scan.
$attendee_id int
Participant concerné par le check-in.
$event_id int
Événement enregistré sur le check-in.
$seat_index int
Place concernée, comptée à partir de 0.

Exemple

add_action(
    'happenboard_pro_attendee_checkin_undone',
    function ( $checkin_id, $attendee_id, $event_id, $seat_index ) {
        // Retirer l'entrée que notre compteur de porte avait ajoutée au check-in.
        $count = (int) get_post_meta( $event_id, 'my_door_count', true );
        update_post_meta( $event_id, 'my_door_count', max( 0, $count - 1 ) );
    },
    10,
    4
);

Remarques

  • Quatre arguments sont passés : enregistrez le hook avec 10, 4.
  • Il se déclenche depuis POST /happenboard/v1/pro/checkin/undo (corps { checkin_id }), ouvert aux utilisateurs qui peuvent faire le check-in. Un check-in inexistant, ou déjà annulé, répond HTTP 404 et ne déclenche rien.
  • Pro l’écoute trois fois : le journal d’activité ajoute une ligne attendee.checkin_undone (priorité 10), les webhooks abonnés reçoivent l’événement attendee.checkin_undone (20), et Slack publie un message quand Check-in undone est coché (30).
  • Les données du webhook sont checkin_id, attendee_id, event_id, seat_index et undone_utc. Le destinataire rapproche checkin_id de l’envoi attendee.checked_in précédent.

happenboard_pro_checkin_lockout

Action Pro src/Service/Checkin/VerifyThrottle.php

Se déclenche quand un utilisateur est bloqué au check-in après trop de codes de billet invalides. Un blocage signale quelqu’un qui cherche des codes valides, ou un scanner qui lit mal.

Signature

do_action( 'happenboard_pro_checkin_lockout', int $actor_id, int $count )

Paramètres

$actor_id int
Identifiant de l’utilisateur bloqué, 0 pour une requête sans utilisateur connecté.
$count int
Nombre de codes différents refusés qui ont provoqué le blocage : 10.

Exemple

add_action(
    'happenboard_pro_checkin_lockout',
    function ( $actor_id, $count ) {
        $user = get_userdata( (int) $actor_id );
        wp_mail(
            get_option( 'admin_email' ),
            'Scanner de check-in bloqué',
            sprintf(
                '%s est bloqué au check-in pendant 5 minutes après %d codes invalides.',
                $user ? $user->display_name : 'Un utilisateur inconnu',
                $count
            )
        );
    },
    10,
    2
);

Remarques

  • Deux arguments sont passés : enregistrez le hook avec 10, 2.
  • Dix codes différents qui ressemblent à des billets HappenBoard mais échouent à la vérification, en 60 secondes, bloquent cet utilisateur pendant 300 secondes. Un texte qui n’est pas un billet, un code déjà compté et un billet authentique refusé ne comptent pas.
  • Pendant le blocage, la vérification répond HTTP 429 avec happenboard_pro_checkin_locked, et le hook ne se redéclenche pas avant la fin du blocage.
  • Les échecs sont comptés par utilisateur sur les routes du scanner et sur les abilities verify-ticket et check-in-attendee. Pour lever un blocage plus tôt, supprimez le transient happenboard_pro_vt_lock_{user_id}.

happenboard_badges_per_sheet

Filtre Pro src/Service/Badges/BadgeBuilder.php

Filtre le nombre de badges contenus dans un PDF de planche. Une sélection plus grande est répartie sur plusieurs planches, chacune téléchargée par sa propre requête.

Signature

apply_filters( 'happenboard_badges_per_sheet', int $per_sheet )

Paramètres

$per_sheet int
Par défaut 150.

Valeur de retour

int Badges par planche. La valeur est ramenée entre 1 et 1000.

Exemple

add_filter(
    'happenboard_badges_per_sheet',
    function ( $per_sheet ) {
        // Serveur généreux : moins de fichiers PDF, plus gros.
        return 300;
    }
);

Remarques

  • Seul HappenBoard Pro le déclenche, même si son nom ne contient pas _pro_.
  • Les badges sont disposés à 8 par page A4 (2 sur 4), un par place de chaque réservation que le contrôle d’accès admettrait.
  • Chaque badge coûte de la mémoire et du temps : 150 badges prennent environ 4 secondes et 85 Mo, 400 environ 11 secondes et 280 Mo. Une planche trop lourde pour le serveur échoue sans fichier : n’augmentez la valeur qu’avec de la marge.
  • Seule la route de téléchargement des badges, GET /happenboard/v1/pro/attendees/badges, le lit. L’ability export-badges a sa propre limite de 500.

happenboard_pro_calendar_event_pushed

Action Pro src/Service/Calendar/Push/GooglePusher.php

Se déclenche après l’écriture d’un événement HappenBoard dans un agenda Google ou Outlook connecté, à la première création puis à chaque mise à jour. Servez-vous-en pour lire la réponse du fournisseur, comme l’identifiant distant ou le lien web de l’événement.

Signature

do_action( 'happenboard_pro_calendar_event_pushed', int $post_id, string $provider, array $response )

Paramètres

$post_id int
L’événement HappenBoard envoyé.
$provider string
google ou outlook. Un seul hook sert les deux fournisseurs : testez toujours cette valeur.
$response array<string,mixed>
La réponse décodée. Google renvoie une ressource Event (id, etag, htmlLink), Microsoft Graph un event (id, @odata.etag, webLink).

Exemple

add_action(
    'happenboard_pro_calendar_event_pushed',
    function ( $post_id, $provider, $response ) {
        if ( 'google' !== $provider ) {
            return; // Se déclenche aussi avec 'outlook'.
        }
        update_post_meta(
            (int) $post_id,
            'my_gcal_html_link',
            (string) ( $response['htmlLink'] ?? '' )
        );
    },
    10,
    3
);

Remarques

  • Trois arguments sont passés : enregistrez le hook avec 10, 3.
  • Enregistrer un événement ne fait que mettre l’envoi en file d’attente : le hook se déclenche en général plus tard, dans une tâche de fond (Action Scheduler ou WP-Cron). Une resynchronisation manuelle le déclenche tout de suite. L’annulation envoyée quand un événement part à la corbeille, et la suppression, ne le déclenchent pas.
  • Il ne se déclenche qu’en cas de succès. Un envoi qui échoue pour une raison passagère est retenté 5, 15, 60 puis 240 minutes plus tard. Passagère veut dire sans réponse, avec un statut 5xx, ou 401, 403, 408, 409, 412, 423 ou 429 ; les autres échecs ne sont pas retentés. Aucun hook ne signale l’échec.
  • Seuls les événements publiés sont envoyés, et seulement si la synchro est activée, le compte connecté et un agenda cible choisi. Un événement dont la synchro est coupée individuellement est ignoré.

happenboard_pro_gcal_exdates

Filtre Pro src/Service/Calendar/Push/EventMapper.php

Filtre les dates à exclure d’un événement récurrent envoyé vers Google Agenda. Elles deviennent une ligne EXDATE à côté de la RRULE.

Signature

apply_filters( 'happenboard_pro_gcal_exdates', array $exdates, int $event_id )

Paramètres

$exdates array<int,string>
Les dates retirées de la série dans HappenBoard, chacune sous la forme de son début en ISO 8601 UTC. Vide quand aucune date n’est retirée.
$event_id int
L’événement HappenBoard en cours de préparation pour l’envoi.

Valeur de retour

array<int,string> Des dates-heures ISO 8601 en UTC, une par date à exclure. Tout ce qui n’est pas un tableau compte comme une liste vide.

Exemple

add_filter(
    'happenboard_pro_gcal_exdates',
    function ( $exdates, $event_id ) {
        // Les dates retirées sont déjà dans la liste. Gardez aussi nos dates réservées
        // aux membres hors de Google, enregistrées en débuts UTC comme 2026-11-02T18:00:00Z.
        $private = get_post_meta( $event_id, 'my_private_dates', true );
        if ( is_array( $private ) ) {
            $exdates = array_merge( $exdates, $private );
        }
        return $exdates;
    },
    10,
    2
);

Remarques

  • Deux arguments sont passés : enregistrez le hook avec 10, 2.
  • La liste contient déjà les dates retirées dans HappenBoard : elles disparaissent aussi de la copie Google. Google uniquement : l’envoi vers Outlook ne lit jamais ce filtre.
  • Renvoyez des valeurs en UTC. Une valeur illisible est ignorée, et une valeur avec un autre décalage n’est pas convertie : son heure est lue comme de l’UTC.
  • Il s’exécute pour chaque événement envoyé, mais un événement sans règle de répétition ne reçoit jamais de ligne EXDATE, quoi que vous renvoyiez : Google la refuse sans RRULE.

happenboard_pro_calendar_local_wins

Action Pro src/Service/Calendar/Pull/GooglePuller.php

Se déclenche quand la récupération Google trouve un événement modifié des deux côtés depuis la dernière synchro et garde la copie WordPress, plus récente. Servez-vous-en pour garder une trace de la modification Google écartée.

Signature

do_action( 'happenboard_pro_calendar_local_wins', int $post_id )

Paramètres

$post_id int
L’événement HappenBoard dont la copie WordPress a été gardée.

Exemple

add_action(
    'happenboard_pro_calendar_local_wins',
    function ( $post_id ) {
        // Trace seulement : Pro renvoie déjà cet événement vers Google.
        error_log( sprintf(
            'Google conflict on event %d, WordPress copy kept.',
            (int) $post_id
        ) );
    }
);

Remarques

  • Un seul argument : un add_action() simple suffit.
  • Quand l’envoi vers Google est actif, Pro écoute déjà en priorité 10 et renvoie aussitôt la version WordPress vers Google. Ne la renvoyez pas vous-même.
  • Il ne se déclenche que si la copie WordPress est strictement plus récente. En cas d’égalité, la version Google l’emporte et le hook ne se déclenche pas.
  • La récupération tourne toutes les 15 minutes via WP-Cron, et quand quelqu’un lance une récupération manuelle depuis les réglages de synchro. La modification Google écartée ne vous est pas transmise.

happenboard_pro_calendar_local_wins_outlook

Action Pro src/Service/Calendar/Pull/OutlookPuller.php

La version Outlook de happenboard_pro_calendar_local_wins. Se déclenche quand la récupération Outlook trouve un événement modifié des deux côtés et garde la copie WordPress, plus récente.

Signature

do_action( 'happenboard_pro_calendar_local_wins_outlook', int $post_id )

Paramètres

$post_id int
L’événement HappenBoard dont la copie WordPress a été gardée.

Exemple

add_action(
    'happenboard_pro_calendar_local_wins_outlook',
    function ( $post_id ) {
        // Trace seulement : Pro renvoie déjà cet événement vers Outlook.
        error_log( sprintf(
            'Outlook conflict on event %d, WordPress copy kept.',
            (int) $post_id
        ) );
    }
);

Remarques

  • Un seul argument : un add_action() simple suffit.
  • Seul le nom du hook indique le fournisseur : il n’y a pas d’argument $provider. Écoutez les deux hooks pour couvrir les deux agendas.
  • Quand l’envoi vers Outlook est actif, Pro écoute déjà en priorité 10 et renvoie la version WordPress. Ne la renvoyez pas vous-même.
  • Même règle que pour Google : il ne se déclenche que si la copie WordPress est strictement plus récente.

happenboard_pro_host_busy_unknown_blocks

Filtre Pro src/Service/Calendar/Busy/SlotBusyFilter.php

Filtre si un hôte dont l’agenda connecté n’a pas pu être lu est retiré des créneaux proposés. Par défaut, ne pas savoir quand un hôte est occupé revient à ne pas savoir s’il est libre.

Signature

apply_filters( 'happenboard_pro_host_busy_unknown_blocks', bool $blocks, array $hosts )

Paramètres

$blocks bool
Par défaut true.
$hosts array<int,int>
Identifiants des hôtes dont l’agenda Google ou Outlook n’a pas pu être lu pour cette période.

Valeur de retour

bool true pour retirer ces hôtes des créneaux, false pour les proposer sur leurs seules disponibilités HappenBoard.

Exemple

add_filter(
    'happenboard_pro_host_busy_unknown_blocks',
    function ( $blocks, $hosts ) {
        // Toujours proposer le compte de l'accueil (utilisateur 12), même si
        // son agenda est illisible ; les autres hôtes restent bloqués.
        return array( 12 ) === array_values( $hosts ) ? false : $blocks;
    },
    10,
    2
);

Remarques

  • Deux arguments sont passés : enregistrez le hook avec 10, 2.
  • Pro retire les hôtes occupés de la liste hosts de chaque créneau, sur le filtre happenboard_booking_slots de l’extension gratuite, en priorité 20. Un créneau ne disparaît que s’il ne reste aucun hôte.
  • Il n’est appelé que si la lecture d’un agenda a échoué. Une lecture ratée est gardée en cache 60 secondes et une lecture réussie 300 : une panne coûte à un hôte une minute de créneaux à la fois.
  • Votre réponse vaut pour tous les hôtes de $hosts, et la même liste revérifie un créneau à l’enregistrement d’une réservation. Renvoyer false peut laisser passer une réservation sur un rendez-vous que vous ne pouviez pas voir. Il s’exécute sur les pages de réservation publiques : gardez-le rapide.

Pour aller plus loin