Google Agenda et Outlook
Extension payante. Une réservation confirmée pose un rendez-vous dans Google Agenda ou Outlook ; son annulation l’en retire.
Ce module dépend de celui des créneaux : il n’écrit rien sans réservation, et le panneau n’apparaît que sur un formulaire qui en prend. C’est le seul de la série dans ce cas.
Un changement d’heure ne déplace pas un rendez-vous
C’est le premier test du plan, et la décision qui porte tout le reste.
Un rendez-vous peut se décrire de deux façons : « le 29 mars à 2 h 30, heure de Paris », ou « à tel instant précis ». Les deux se valent le reste de l’année ; elles divergent les deux nuits où l’heure change.
Le 29 mars 2026 à 2 h 30, heure de Paris, n’existe pas : cette heure-là est sautée. Et le 25 octobre à 2 h 30 existe deux fois. Une réservation prise en janvier pour une date d’été, décrite en heure locale, se décale d’une heure le jour venu — ou tombe dans un trou.
Le créneau part donc comme un instant absolu, en temps universel ; le fuseau n’accompagne que l’affichage. Le calendrier n’a plus rien à interpréter.
Le fuseau conservé est celui de la réservation, pas celui du site au moment de
la pose : un site qui change de fuseau entre les deux ne doit pas déplacer un
rendez-vous déjà annoncé à quelqu’un. Un fuseau que PHP ne connaît pas — un décalage
fixe comme UTC+2, qu’aucun des deux services n’accepte — retombe sur le temps
universel : le rendez-vous s’affichera à la mauvaise heure, mais il aura lieu au bon
moment, et c’est l’instant qui déclenche l’alarme.
Une date de créneau qu’on ne sait pas lire n’est pas approchée : rien n’est posé, et le motif le dit.
Les deux services ne décrivent pas une date de la même façon
Google accepte l’instant universel — un Z final — avec un fuseau d’affichage à
côté. Microsoft Graph refuse ce Z et veut une heure nue plus le nom de son fuseau ;
il reçoit donc l’heure universelle et le fuseau UTC.
C’est la divergence que CalendarProviderInterface ne cache pas. La lisser derrière
une seule forme aurait obligé à choisir laquelle est « la vraie » — et c’est
précisément la question où l’on se trompe d’une heure deux fois par an.
Seule une place confirmée entre dans un agenda
Une place en liste d’attente n’est pas un rendez-vous : y poser un événement bloquerait un créneau que personne n’a obtenu, et ferait refuser une vraie demande.
Trois moments, et pas un de plus : une place confirmée entre, une place promue depuis l’attente entre aussi — c’est devenu un vrai rendez-vous —, une place annulée en sort.
Le paiement est déjà réglé en amont
Le plan demande de ne créer l’événement qu’« après paiement confirmé lorsque requis ». Ce module n’a rien à contrôler pour cela : une soumission dont le règlement ne convient pas est refusée avant tout enregistrement, par le garde du module de paiement. Pas de soumission, donc pas de réservation, donc pas de rendez-vous.
Refaire ce contrôle ici aurait donné un second endroit où se tromper, et une fausse impression de garantie si les deux venaient à diverger.
Personne n’est invité sans qu’on l’ait demandé
Ajouter l’adresse du visiteur comme invité ne l’inscrit pas seulement à l’événement : Google et Microsoft lui envoient alors une invitation depuis le compte du client. C’est un second message, que personne n’a rédigé, qui arrive après celui que le site vient d’envoyer — et parfois dans une autre langue.
Le réglage est donc éteint par défaut, et l’écran dit ce qu’il déclenche avant qu’on
l’allume. Chez Google, sendUpdates=none est posé à chaque appel, y compris sans
invité : un défaut qui changerait chez eux ne doit pas se traduire par des courriels
partis d’un site qui ne l’a pas demandé.
Ce que l’agenda affiche
Un agenda se partage, parfois avec une équipe entière, et un rendez-vous y reste visible longtemps. C’est ce qui distingue cette sortie des autres.
La description ne reprend donc que les champs désignés un par un — pas « toutes les valeurs ». Les types sensibles sont écartés quoi qu’il arrive, et l’ensemble est borné : une description de dix mille caractères ne se lit pas dans une case d’agenda.
Le titre accepte deux marqueurs, {form} et {field:identifiant}, parce qu’un
agenda se lit en diagonale et que « Rendez-vous » sur trente lignes ne renseigne
personne. Un marqueur inconnu est retiré plutôt que laissé tel quel, et un
marqueur désignant un champ exclu ne rend rien.
Le calendrier n’est jamais deviné
Il aurait été commode de prendre le calendrier par défaut quand aucun n’est choisi. Ce serait mettre des rendez-vous dans l’agenda personnel de la personne qui a autorisé, alors qu’elle en visait peut-être un autre — et un agenda personnel se partage parfois avec une famille.
Tant qu’aucun calendrier n’est choisi, rien n’est posé, et l’écran le dit. Le choix se fait après l’autorisation, puisqu’on ne peut pas lister les agendas de quelqu’un avant. Seuls ceux où le compte peut écrire sont proposés ; un agenda partagé en lecture seule refuserait le premier rendez-vous. Et un identifiant tapé à la main est refusé : il désignerait au mieux rien, au pire l’agenda de quelqu’un d’autre.
L’annulation, et l’échec qui compte vraiment
Qu’un rendez-vous n’ait pas été posé se remarque : la personne appelle, et personne n’a rien dans son agenda.
Qu’un rendez-vous annulé n’ait pas été retiré ne se remarque pas du tout : quelqu’un garde une plage réservée pour un visiteur qui ne viendra jamais, et l’apprend le jour même. L’écran distingue donc les deux, et le second est écrit comme ce qu’il est — une chose à aller régler à la main dans l’agenda.
Un événement déjà absent est une réussite : Google répond 410, Microsoft 404,
et les deux veulent dire « il n’y est plus », ce qui était la demande. Traiter cela
comme un échec aurait fait échouer à jamais une seconde annulation sur ce que la
première avait réussi.
Il n’y a pas de bouton de renvoi, et c’est voulu
Rejouer une pose créerait un second rendez-vous si le premier avait en réalité abouti — et un doublon d’agenda bloque un créneau et fait refuser une vraie demande. Les reprises automatiques suffisent ; ce qu’elles n’obtiennent pas se règle dans l’agenda, où l’on voit ce qui s’y trouve réellement.
Effacer une soumission ne décommande personne
La ligne de suivi s’en va, l’événement reste.
Supprimer une soumission est un acte d’effacement de données ; décommander un rendez-vous est un acte de gestion, qui regarde la personne qui l’attend. Confondre les deux ferait disparaître d’un agenda un rendez-vous que quelqu’un comptait honorer, sans que personne l’ait décidé.
C’est l’annulation de la réservation qui retire l’événement, et elle seule.
Deux points d’extension ajoutés au module des créneaux
solis_forms_pro_booking_cancelled et solis_forms_pro_booking_promoted, émis
depuis le dépôt — là où l’état change réellement — et non chez leurs appelants, qui
sont déjà deux et seraient trois demain. Une garantie qui dépend de chaque appelant
pour s’en souvenir n’en est pas une : le premier qu’on oublierait laisserait un
rendez-vous annulé dans l’agenda de quelqu’un.
Ils rejoignent solis_forms_pro_booking_reserved, qui existait déjà.
Une connexion par fournisseur, et pas celle du stockage
Le module de stockage autorise déjà Google et Microsoft. Mais une autorisation porte des portées : celle du stockage ouvre des fichiers, celle-ci ouvre un agenda. Les fusionner aurait voulu dire demander les deux à tout le monde — et faire réautoriser le stockage de quelqu’un qui n’a jamais voulu de calendrier, en interrompant ses dépôts le temps qu’il s’en aperçoive.
Les portées demandées sont les plus étroites qui fonctionnent :
calendar.events chez Google — et non calendar, qui donnerait aussi le droit de
supprimer des agendas entiers — et Calendars.ReadWrite chez Microsoft.
Schéma
slf_calendar_events : une ligne par réservation portée à un agenda — et non
par soumission, car c’est la réservation qui a une vie dans un agenda. Avec le
fournisseur, le calendrier, l’identifiant distant, l’état, le motif du dernier
problème et le nombre de tentatives.
Cinq états au lieu de quatre : le cinquième, retiré, existe parce qu’un rendez-vous a une fin. Le confondre avec « échoué » aurait fait apparaître chaque annulation réussie dans la liste des problèmes.
L’identifiant distant n’est conservé que pour pouvoir annuler. Sans lui, une annulation ne saurait pas quoi retirer.
Les connexions vivent dans une option : l’identifiant client, le calendrier et le nom du compte en clair — ce ne sont pas des secrets, et le calendrier est la première chose à vérifier quand les rendez-vous arrivent au mauvais endroit —, les jetons et le secret client chiffrés.
Le journal des envois ne porte ni la requête ni la réponse — elles contiennent le titre et la description composés depuis la soumission — ni l’identifiant du calendrier, qui chez Google est le plus souvent l’adresse électronique du compte.
Ce que la V1 ne fait pas
Pas de lecture de disponibilité depuis les agendas, pas de déplacement bidirectionnel, pas d’événement récurrent, pas de réconciliation d’une modification faite à la main.
Ce dernier point mérite d’être dit franchement : si quelqu’un déplace le rendez-vous dans son agenda, SolisForms ne le saura pas, et la réservation gardera l’heure d’origine. Le site reste la source du créneau ; l’agenda en est le reflet.
