Live · stato OK
Documentazione · OW Agenda v1.3.1

OW Agenda
Documentazione

La prenotazione appuntamenti WordPress che non lascia occupare i tuoi slot a vuoto.

v1.3.1GPL-2.0-or-laterDocumentazione

OW Agenda — Documentazione

La prenotazione online degli appuntamenti e l'agenda di tutti i giorni, dentro WordPress, senza abbonamento. Autore: OptionWeb — Julien Daniel Pagina del plugin: https://optionweb.dev/it/addons/ow-agenda/ Licenza: GPL-2.0-or-later Versione coperta da questo documento: 1.3.1


Indice

  1. Panoramica
  2. Installazione
  3. Avvio rapido
  4. Il percorso di prenotazione
  5. La doppia verifica via email
  6. La conferma delle richieste
  7. La pagina Agenda
  8. La rubrica clienti
  9. Gli inviti per le sedute
  10. Email e file calendario (ICS)
  11. Promemoria e attività pianificata
  12. Anti-spam e limiti di frequenza
  13. GDPR
  14. Shortcode
  15. REST API
  16. Riferimento impostazioni
  17. Dati memorizzati
  18. Internazionalizzazione
  19. Disinstallazione
  20. Risoluzione problemi
  21. FAQ
  22. Changelog

Panoramica

OW Agenda aggiunge a WordPress un sistema completo di appuntamenti: una pagina pubblica in cui il visitatore sceglie prima il giorno e poi l'ora, e una pagina «Agenda» protetta da login, pensata per essere usata dal telefono, in cui Lei gestisce la giornata.

Tutto resta dentro il sito. Nessun servizio esterno, nessuna API di terze parti, nessun abbonamento: gli slot vengono calcolati dal suo server, gli appuntamenti vivono nelle sue tabelle MySQL, le email partono con wp_mail().

Cosa viene consegnato (tutto gratuito, GPL-2):

  • Prenotazione online: scelta del giorno, scelta dello slot, form breve, casella di consenso GDPR
  • Doppio opt-in via email: una richiesta diventa reale solo dopo il clic su un link di verifica — i bot non arrivano mai all'agenda
  • Conferma manuale (consigliata) o conferma automatica, con i pulsanti Conferma / Rifiuta direttamente nell'email di notifica (link firmati HMAC, senza login)
  • Pagina «Agenda» mobile-first: vista del giorno, richieste in attesa, appuntamenti telefonici inseriti a mano, blocco degli slot, spostamento, stati fatto / assente
  • Rubrica clienti: ricerca, creazione, modifica, eliminazione; alimentata automaticamente dagli appuntamenti confermati
  • Inviti per le sedute: un link privato permette a un cliente esistente di scegliere la data della sua seduta, su un servizio e una durata che stabilisce Lei
  • Email HTML curate con allegato ICS (aggiunta al calendario del telefono con un solo gesto), promemoria automatico il giorno prima, annullamento online da parte del cliente
  • Anonimizzazione automatica degli appuntamenti passati, eliminazione delle richieste mai verificate
  • REST API completa sotto il namespace owag/v1

Cosa non fa, deliberatamente:

  • Nessun pagamento online: OW Agenda prende l'appuntamento, non incassa un acconto (usi WooCommerce se è questa la sua esigenza)
  • Una sola agenda: nessuna gestione multi-professionista né multi-risorsa; il plugin descrive un calendario, quello del sito
  • Nessuna sincronizzazione bidirezionale con Google Calendar o Outlook: il calendario del cliente viene aggiornato tramite file ICS (solo andata), le sue indisponibilità personali si inseriscono come blocchi
  • Nessun catalogo di servizi lato visitatore: la prenotazione pubblica riguarda una prestazione unica (etichetta e durata configurabili); le altre prestazioni passano dagli inviti per le sedute
  • Nessun appuntamento ricorrente, nessuna videoconferenza, nessuna sala d'attesa

Questo elenco è una scelta di architettura, non una roadmap nascosta: un'agenda semplice che non sbaglia mai uno slot vale più di una cattedrale che nessuno osa toccare.


Installazione

Dallo .zip

  1. Scarichi ow-agenda-1.3.1.zip da https://optionweb.dev/it/addons/ow-agenda/
  2. Plugin → Aggiungi nuovo → Carica plugin
  3. Scelga il file, clicchi su Installa, poi su Attiva

Via FTP

Decomprima l'archivio e copi la cartella ow-agenda in /wp-content/plugins/, poi attivi il plugin da Plugin.

Requisiti

  • WordPress 6.3 o successivo
  • PHP 7.4 o successivo (8.1+ consigliato)
  • MySQL 5.7+ / MariaDB 10.2+ — le funzioni GET_LOCK() / RELEASE_LOCK() vengono usate per serializzare le prenotazioni simultanee
  • Un invio di email funzionante. È l'unica vera dipendenza del plugin: tutto il percorso (verifica, conferma, promemoria, annullamento) passa dall'email. Su un hosting condiviso, installi un plugin SMTP prima di mettere online l'agenda.

Cosa viene installato

All'attivazione, OW Agenda crea tre tabelle:

TabellaContenuto
{prefix}_owag_appointmentsTutti gli eventi dell'agenda: consulenze web, sedute nate da un invito, appuntamenti inseriti a mano, blocchi di slot
{prefix}_owag_invitesI link privati «scelga la data della sua seduta»
{prefix}_owag_customersLa rubrica clienti

…e, solo la prima volta, due pagine pubblicate:

  • «Prenota un appuntamento» — contiene lo shortcode [ow_agenda]
  • «Agenda» — contiene lo shortcode [ow_agenda_admin]

I loro identificativi vengono memorizzati nelle opzioni owag_page_booking e owag_page_admin; il flag owag_pages_created garantisce che una disattivazione seguita da una riattivazione non ricrei dei duplicati. Può rinominare queste pagine, spostarle in un menu, cambiarne il permalink: il plugin le segue tramite il loro ID.

L'attivazione aggiunge anche:

  • la capability owag_manage al ruolo amministratore — è questa, e non manage_options, ad aprire l'agenda e le route REST di amministrazione;
  • le impostazioni predefinite nell'opzione owag_settings;
  • l'attività pianificata oraria owag_hourly_event (prima esecuzione 5 minuti dopo l'attivazione).

Un segreto HMAC (owag_admin_secret, 64 caratteri, non caricato automaticamente) viene generato alla prima notifica admin: è lui a firmare i pulsanti Conferma / Rifiuta delle email.

Dare l'accesso a qualcun altro

La pagina Agenda è visibile a qualsiasi utente loggato che disponga di owag_manage. Per aprire l'agenda a un'assistente senza consegnarle le chiavi del sito:

// À exécuter une fois (mu-plugin, ou plugin de gestion des rôles).
$role = get_role( 'editor' );
if ( $role ) { $role->add_cap( 'owag_manage' ); }

Avvio rapido

Dopo l'attivazione, si rechi in OW Agenda (menu principale dell'amministrazione). La schermata delle impostazioni sta in una pagina sola; cinque minuti bastano.

1. Gli orari di apertura

Per ogni giorno della settimana, inserisca una fascia (09:00 → 18:00) e, se chiude a mezzogiorno, una seconda fascia (14:00 → 18:30). Un giorno lasciato vuoto è un giorno chiuso. Di default: dal lunedì al venerdì, 09:00–18:00; sabato e domenica chiusi.

Gli orari vengono interpretati nel fuso del sito (Impostazioni → Generali → Fuso orario). Lo verifichi prima di aprire le prenotazioni: tutte le date sono memorizzate in ora locale.

2. La prestazione prenotabile online

  • Etichetta della consulenza — ciò che il visitatore vede come titolo del widget («Consulenza», «Primo appuntamento», «Valutazione»…)
  • Durata della consulenza — 60 minuti di default. È questa durata a essere bloccata in agenda.
  • Granularità degli slot — la distanza tra due orari proposti (30 minuti di default). Con una durata di 60 e una granularità di 30, propone le 9:00, 9:30, 10:00… e il primo appuntamento preso alle 9:30 elimina le 9:00 e le 10:00 dall'elenco.
  • Margine tra due appuntamenti — minuti di respiro aggiunti prima e dopo ogni slot candidato (0 di default).

3. I termini

  • Preavviso minimo di prenotazione — 24 h di default: un visitatore non può prenotare per tra un'ora.
  • Orizzonte di prenotazione — 60 giorni di default: oltre, non viene più proposto nulla.
  • Annullamento online da parte del cliente — fino a 24 h prima dell'appuntamento; passato questo termine, la pagina di annullamento invita a telefonare.

4. La conferma e le email

  • Conferma delle richieste: conferma manuale (consigliata) o conferma automatica.
  • Doppia verifica email: la lasci attiva. È la migliore protezione anti-bot del plugin.
  • Notifiche admin inviate a: il suo indirizzo. Di default, l'email di amministrazione del sito.

Salvi, poi apra la pagina «Prenota un appuntamento»: il widget mostra i 14 giorni successivi e i suoi slot liberi. È online.

5. L'agenda sul telefono

Apra la pagina «Agenda» sul suo telefono, effettui il login, poi usi «Aggiungi alla schermata Home». Il plugin pubblica un manifest applicativo: la pagina si apre allora a schermo intero, senza barra del browser, come un'app.


Il percorso di prenotazione

Lato visitatore, la pagina di prenotazione è un componente autonomo (JavaScript senza framework, meno di 10 KB) che dialoga con gli endpoint pubblici owag/v1/public/*.

Passo 1 — il giorno

Al caricamento, il widget chiede le disponibilità su 14 giorni a partire da oggi e mostra una striscia di giorni cliccabili. Un giorno senza slot liberi è in grigio e non cliccabile. Il pulsante «Vedi le date successive» carica i 14 giorni seguenti, tutte le volte che serve fino all'orizzonte configurato.

Le date del widget sono costruite in ora locale del browser, mai in UTC. È una correzione della 1.3.0: in precedenza, un visitatore situato a est di UTC che apriva la pagina poco dopo la mezzanotte vedeva l'elenco iniziare dal giorno prima e perdeva una giornata di disponibilità.

Passo 2 — l'ora

Il clic su un giorno chiama /public/slots e mostra gli orari di inizio liberi. Uno slot viene proposto quando tutte queste condizioni sono soddisfatte:

  1. cade in una fascia di apertura del giorno in questione;
  2. l'appuntamento intero (inizio + durata) rientra prima della chiusura;
  3. inizia dopo adesso + preavviso minimo;
  4. il giorno rientra nell'orizzonte di prenotazione;
  5. non si sovrappone ad alcun evento attivo, margine compreso — e per «evento attivo» si intendono gli appuntamenti confermati, le richieste in attesa, i blocchi, gli appuntamenti telefonici inseriti a mano e le richieste non ancora verificate che trattengono ancora il loro slot.

È questo il punto importante: tutto ciò che occupa l'agenda chiude lo slot online. Un appuntamento preso al telefono e annotato in agenda sparisce immediatamente dagli slot proposti sul sito.

Passo 3 — il form

Quattro campi, di cui tre obbligatori: nome (minimo 2 caratteri), telefono (minimo 8 cifre), email (validata), messaggio libero. Una casella di consenso GDPR, non selezionata di default, è obbligatoria.

Il form incorpora inoltre due campi invisibili per il visitatore — una trappola per bot e un timestamp di apertura della pagina — descritti nella sezione Anti-spam.

Passo 4 — la risposta

A seconda della sua configurazione, tre esiti:

ConfigurazioneStato creatoMessaggio mostrato
Doppia verifica email attiva (default)unverified«Un ultimo passaggio: le è appena stata inviata un'email…»
Verifica disattivata + conferma manualepending«La sua richiesta è stata ricevuta!»
Verifica disattivata + conferma automaticaconfirmed«Il suo appuntamento è confermato!»

Se lo slot è stato preso tra la visualizzazione dell'elenco e l'invio del form, il visitatore riceve un messaggio esplicito (owag_slot_taken, HTTP 409) e l'elenco dei giorni si ricarica automaticamente. Due visitatori non possono ottenere lo stesso slot: la sezione critica è serializzata da un lock MySQL con nome, specifico del suo database e del suo prefisso di tabelle, il che regge anche su un hosting condiviso.


La doppia verifica via email

È la funzionalità che distingue OW Agenda da un form di contatto travestito.

Quando la doppia verifica email è attiva (impostazione email_verify, attiva di default):

  1. La richiesta viene registrata con lo stato unverified. L'amministratore non riceve notifica. L'appuntamento non compare come richiesta da gestire.
  2. Il visitatore riceve un'email «Un ultimo passaggio…» contenente un pulsante di verifica.
  3. Lo slot viene trattenuto per 45 minuti. Passato questo termine senza verifica, torna disponibile per tutti — un bot non può quindi congelarle la giornata.
  4. Il clic sul pulsante apre una pagina autonoma (?owag_verify=<uid>) che mostra il riepilogo dell'appuntamento e un pulsante «Confermo la mia richiesta». La verifica parte solo al clic: gli antivirus e gli scanner di link che visitano gli URL delle email non confermano nulla.
  5. La richiesta diventa allora pending (conferma manuale) o confirmed (conferma automatica), il cliente riceve l'email corrispondente ed è solo a quel punto che parte la notifica admin.
  6. Le richieste mai verificate vengono eliminate dopo 48 h dall'attività oraria. Non lasciano alcuna traccia né alcun dato personale.

Se, tra l'invio e il clic, lo slot è stato preso da qualcun altro (la finestra di 45 minuti è scaduta), la verifica restituisce un errore chiaro e la richiesta viene annullata — mai un appuntamento fantasma su uno slot già occupato.

Conseguenza pratica: un indirizzo email non valido non produce alcun appuntamento. Non perde più tempo a richiamare numeri inventati. Il prezzo da pagare è un clic in più per il cliente; l'esperienza mostra che il tasso di abbandono è molto inferiore al tasso di falsi appuntamenti che evita.

Le prenotazioni nate da un invito per una seduta saltano questo passaggio: il cliente ha già dimostrato di leggere la propria casella di posta cliccando sul link privato che ha ricevuto.


La conferma delle richieste

Conferma manuale (consigliata)

Impostazione predefinita: auto_confirm = 0. Una richiesta verificata arriva con lo stato pending. Al cliente non viene promesso nulla finché Lei non fa nulla — ma lo slot è già bloccato, nessuno può soffiarglielo.

Riceve un'email «Da confermare: » contenente il riepilogo completo (servizio, data, nome, telefono, email, messaggio del cliente) e due pulsanti:

  • Conferma l'appuntamento — ciano
  • Rifiuta — bordo rosso

I pulsanti dell'email: link firmati HMAC

Questi pulsanti non richiedono alcun login. Puntano al suo sito con tre parametri: owag_admin_action (confirm o refuse), uid (l'identificativo casuale dell'appuntamento) e sig, una firma HMAC-SHA256 di uid|action calcolata con il segreto privato del sito (owag_admin_secret).

  • La firma viene verificata prima che venga mostrato il minimo dettaglio: un link manomesso non mostra nient'altro che «Link non valido».
  • Il confronto usa hash_equals() — nessuna fuga di informazioni dal tempo di risposta.
  • La pagina mostra un riepilogo e un pulsante; l'azione viene eseguita solo al clic. Uno scanner di link non conferma quindi nulla al posto suo.
  • Una richiesta già gestita restituisce «Già gestita (stato: …)» invece di un errore.

Confermare invia automaticamente l'email di conferma al cliente, con il file calendario. Rifiutare invia l'email di annullamento. In entrambi i casi, l'agenda è aggiornata prima che Lei abbia rimesso in tasca il telefono.

Questi link restano validi finché l'appuntamento è in attesa. Se elimina l'opzione owag_admin_secret (ripristino parziale del database, pulizia manuale), tutti i link già inviati smettono di funzionare: viene generato un nuovo segreto e le vecchie firme non corrispondono più. In tal caso proceda dalla pagina Agenda.

Conferma automatica

Impostazione auto_confirm = 1. Uno slot libero viene confermato immediatamente: il cliente riceve la sua conferma con il file calendario, Lei riceve una notifica «Nuovo appuntamento». Da riservare alle attività in cui ogni slot aperto è uno slot accettabile.

Le due impostazioni si combinano con la doppia verifica: anche in conferma automatica, la richiesta passa prima da unverified se email_verify è attiva.


La pagina Agenda

La pagina «Agenda» ([ow_agenda_admin]) è lo strumento di tutti i giorni. È pensata prima di tutto per il telefono: pulsanti larghi, una sola colonna, nessuna tabella da far scorrere in orizzontale, e funziona ovviamente altrettanto bene su uno schermo di computer.

È protetta: un visitatore non loggato vede un link di accesso, un utente loggato senza la capability owag_manage vede «L'accesso è riservato al team». La pagina è in noindex,nofollow: non finirà mai su Google.

Scheda Agenda — la vista del giorno

La giornata in corso, evento per evento, con l'ora, la durata, l'etichetta, lo stato e l'origine (sito, invito, inserimento manuale). Navigazione da un giorno all'altro, pulsante Oggi. Su ogni appuntamento:

  • Dettagli — recapiti del cliente, messaggio lasciato al momento della prenotazione e un blocco di note interne (mai visibili al cliente) salvate senza inviare la minima email
  • Conferma ✓ — per una richiesta ancora in attesa; parte l'email di conferma
  • Fatto / Assente (no-show) — stati di fine appuntamento
  • Sposta — nuova data, nuova ora, durata eventualmente modificata. Il plugin le chiede se il cliente vada avvisato per email; in caso affermativo, quest'ultimo riceve una conferma aggiornata e un file calendario che corregge l'evento già presente sul suo telefono
  • Annulla l'appuntamento — anche qui con la scelta se avvisare o meno il cliente
  • Elimina il blocco — per uno slot bloccato

Quando un'azione crea una sovrapposizione (spostamento su uno slot occupato), il plugin avvisa e chiede conferma: può forzare. È il suo calendario, sa quello che fa — la protezione è vincolante solo per i visitatori.

Aggiungere un appuntamento o un blocco

Il pulsante «Aggiungi un appuntamento» apre una scheda unica che serve a due scopi:

  • Appuntamento — il cliente l'ha chiamata. Nome, telefono, email (facoltativa), servizio, data, ora, durata, note interne. Se indica un indirizzo email e seleziona l'opzione, il cliente riceve la conferma con il suo file calendario, come se avesse prenotato online. L'appuntamento alimenta anche la rubrica clienti.
  • Blocco (ferie, pausa…) — un motivo, una data, un'ora, una durata. Nessuna email, nessuna scheda cliente, ma lo slot sparisce immediatamente dalla prenotazione online. È così che si mette una settimana di ferie, un corso di formazione o la pausa pranzo che non si vuole veder prenotata.

Scheda In attesa

L'elenco delle richieste verificate che attendono la sua decisione, senza distinzione di giorno (gli appuntamenti già passati sono esclusi). Due pulsanti per riga: Conferma e Rifiuta. È la prima schermata da aprire al mattino.

Suggerimento: l'agenda come app

Sulla pagina Agenda, il plugin dichiara un manifest di applicazione web (?owag_manifest=1) con il nome del sito, l'icona del sito e il colore del tema. Su Android come su iOS, il menu del browser propone allora «Aggiungi alla schermata Home»: ottiene un'icona, un avvio a schermo intero e mai più l'URL da ridigitare.


La rubrica clienti

La terza scheda della pagina Agenda è una rubrica leggera, volutamente minimale: nome, telefono, email, note libere.

  • Si riempie da sola. Non appena un appuntamento viene confermato (prenotazione online verificata, seduta su invito, inserimento manuale), il cliente viene associato a una scheda esistente tramite la sua email, poi tramite il suo telefono. Se non esiste, la scheda viene creata; se esiste, vengono completati solo i campi vuoti — il plugin non sovrascrive mai ciò che ha inserito Lei a mano.
  • Ricerca su nome, telefono o email (massimo 200 schede visualizzate).
  • Creazione e modifica manuali, con un campo note per lo storico, le preferenze, le precauzioni da prendere.
  • Due scorciatoie per scheda: Nuovo appuntamento (precompila la scheda di inserimento manuale) e Invita per una seduta (precompila l'invito).
  • Eliminazione di una scheda: gli appuntamenti passati restano in agenda, sparisce soltanto la scheda della rubrica.

Questa rubrica non è un CRM e non pretende di esserlo. Risponde a una domanda: «Chi è, di preciso, la signora delle 14?»


Gli inviti per le sedute

Il caso d'uso: un cliente esistente ha diritto a una seduta — un controllo, un ritocco, una prestazione venduta altrove — e Lei vuole che scelga la data senza passare dalla prenotazione pubblica, su un servizio e una durata che stabilisce Lei.

Dalla scheda Inviti:

  1. Inserisca il nome del cliente e il titolo della seduta (obbligatori), la sua durata (da 15 a 720 minuti) e, se lo desidera, la sua email e il suo telefono.
  2. Scelga la validità del link: 60 giorni di default, da 1 a 365.
  3. Selezioni eventualmente «Invia il link al cliente per email» — il cliente riceve un'email «Scelga la data della sua seduta» con il titolo, la durata, la data di scadenza e un pulsante.
  4. Altrimenti copi il link e lo invii per SMS, WhatsApp o con il pulsante di condivisione nativo del telefono.

Il link punta alla sua pagina di prenotazione con un token privato (?owag_invite=<token>, 32 caratteri esadecimali estratti da un generatore crittografico). Il widget mostra allora il titolo e la durata della seduta, e non della consulenza standard. Il cliente compila lo stesso form breve.

Le regole che governano un link di invito:

  • Uso singolo. Una volta prenotata la seduta, il link risponde «Questo link è già stato utilizzato» (HTTP 410). Due aperture simultanee con lo stesso token non possono creare due sedute: il consumo del token avviene sotto lo stesso lock della prenotazione dello slot.
  • A tempo. Superata la scadenza, il link invita a ricontattarla (HTTP 410).
  • Senza doppio opt-in. Il cliente ha già ricevuto questo link tramite un canale che Lei controlla: la seduta viene creata direttamente come confirmed, con conferma e file calendario.
  • Riciclato in caso di annullamento. Se la seduta viene annullata (da Lei o dal cliente), l'invito viene liberato: il link torna attivo e l'invito ricompare nell'elenco degli inviti aperti. È una correzione della 1.3.0 — in precedenza, un annullamento uccideva definitivamente il link e bisognava rifarne uno.
  • Revocabile. Eliminare un invito dall'elenco disattiva il link immediatamente.

Email e file calendario (ICS)

Le email transazionali

Tutti i messaggi sono in HTML, su un layout a tabelle compatibile con Gmail e Outlook: scheda bianca su sfondo chiaro, nome del sito nell'intestazione, riquadro di riepilogo con filetto ciano, pulsanti a pillola. Vengono inviati con wp_mail(), quindi rispettano la sua configurazione SMTP e i consueti filtri WordPress.

EmailDestinatarioAttivazione
Verifica della richiestaClientePrenotazione web quando la doppia verifica è attiva
Richiesta ricevutaClienteRichiesta verificata, in attesa della sua decisione
Appuntamento confermatoClienteConferma (manuale, automatica, inserimento admin, spostamento) — con allegato ICS
Appuntamento annullatoClienteAnnullamento da parte del cliente, rifiuto o annullamento da parte dell'admin — con allegato ICS di cancellazione
PromemoriaClienteAutomaticamente, tra 12 e 36 h prima dell'appuntamento
Scelga la data della sua sedutaClienteCreazione di un invito con invio per email
Da confermare: …AdminNuova richiesta verificata in attesa — con i pulsanti Conferma / Rifiuta
Nuovo appuntamento: …AdminNuovo appuntamento confermato (conferma automatica, invito)
Annullamento cliente: …AdminIl cliente ha annullato da sé dalla propria email

L'indirizzo di notifica admin è l'impostazione notify_email (di default l'email di amministrazione del sito). Le email al cliente partono solo se l'indirizzo è valido, e mai per un blocco di slot.

Le email di conferma e di annullamento ricordano al cliente che può annullare online, con il numero di ore di preavviso effettivamente configurato.

L'allegato ICS

Il file .ics allegato alle conferme è ciò che trasforma un'email in un appuntamento realmente presente nel telefono del cliente: un gesto sull'allegato, e l'evento è nel suo calendario, con il proprio promemoria.

Il file è conforme alla RFC 5545 e contiene quanto serve perché i client di calendario (Google, Outlook, Apple) gestiscano correttamente gli aggiornamenti:

  • METHOD:REQUEST alla creazione e a ogni revisione di orario, METHOD:CANCEL all'annullamento;
  • un UID stabile derivato dall'identificativo dell'appuntamento e dal dominio del sito — è lui a permettere a una revisione di sostituire l'evento esistente invece di crearne un secondo;
  • un SEQUENCE crescente derivato dalla data di ultima modifica, ricondotta a un istante assoluto: il passaggio all'ora solare non può far arretrare il numero di revisione (e l'annullamento aggiunge 1, per restare superiore a una revisione avvenuta nello stesso secondo);
  • ORGANIZER (il suo indirizzo di notifica) e ATTENDEE (il cliente);
  • DTSTART / DTEND in UTC, STATUS:CONFIRMED o STATUS:CANCELLED;
  • ripiegamento delle righe a 75 byte senza mai spezzare un carattere UTF-8.

Uno spostamento di appuntamento confermato invia quindi un nuovo file che corregge l'evento già presente presso il cliente; un annullamento invia un file che lo elimina. È una correzione della 1.3.0: in precedenza il vecchio orario restava nel calendario del cliente.

Il file viene scritto nella directory temporanea del server — mai in wp-content/uploads/, che è servita pubblicamente — tramite l'API file di WordPress, e viene cancellato appena l'invio è concluso, anche in caso di invio fallito. Porta il nome e l'email del cliente: non ha motivo di restare sul disco un secondo più del necessario.


Promemoria e attività pianificata

Una sola attività pianificata, owag_hourly_event, eseguita ogni ora. Fa tre cose.

1. Il promemoria del giorno prima

Il promemoria parte quando l'appuntamento inizia entro 12-36 ore. Non è una finestra oraria fissa, ed è voluto: WP-Cron scatta solo alla visita di una pagina. Un sito senza traffico la sera perdeva definitivamente i promemoria del giorno successivo. Con una finestra mobile, il promemoria parte alla prima esecuzione disponibile e recupera il ritardo.

Condizioni: appuntamento confermato, indirizzo email presente, non si tratta di un blocco, e il promemoria non è già stato inviato.

Ogni promemoria viene prenotato in modo atomico prima dell'invio (un UPDATE condizionale sul flag reminder_sent): due esecuzioni di cron che si sovrappongono non possono inviare due volte lo stesso messaggio. Se l'invio fallisce, la prenotazione viene restituita e il promemoria verrà ritentato all'esecuzione successiva. Un lock breve (10 minuti) evita inoltre che due passaggi simultanei percorrano lo stesso elenco.

Spostare un appuntamento azzera il flag: il cliente riceve regolarmente un promemoria per il nuovo orario.

2. L'eliminazione delle richieste non verificate

Le richieste rimaste unverified da più di 48 ore vengono eliminate. (Il loro slot, da parte sua, era già tornato disponibile dopo 45 minuti.)

3. L'anonimizzazione GDPR

Veda la sezione GDPR.

La rete di sicurezza

Un evento WP-Cron può sparire: ottimizzazione del database, ripristino parziale, plugin di pulizia, reset dell'opzione cron. OW Agenda verifica a ogni caricamento che l'attività sia effettivamente programmata e, in caso contrario, la riprogramma. Promemoria, eliminazione e retention non possono fermarsi in silenzio.

Usare un vero cron di sistema

WP-Cron dipende dal traffico. Su un sito poco visitato, preferisca un cron di sistema:

// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e — toutes les 15 minutes
*/15 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null

Anti-spam e limiti di frequenza

La prenotazione è pubblica per natura: nessun account, nessun login, nessun nonce possibile. Cinque protezioni indipendenti lavorano quindi a monte.

1. La trappola per bot (honeypot)

Il form contiene un campo di testo fuori schermo, invisibile per un umano e appetitoso per un bot. Il campo deve essere presente e vuoto. Un campo compilato — o assente, il che tradisce un invio diretto all'API — restituisce un rifiuto secco (HTTP 403), senza dettagli sfruttabili.

2. Il tempo di compilazione

La pagina trasmette il timestamp della propria visualizzazione. Un invio arrivato meno di 4 secondi dopo il caricamento viene rifiutato. Anche qui, un timestamp assente o malformato è un rifiuto: nella 1.3.0 questi due campi sono diventati obbligatori — ometterli disattivava puramente e semplicemente il controllo.

3. Il limite orario per indirizzo

5 prenotazioni all'ora per ambito. In IPv4, l'ambito è l'indirizzo; in IPv6, è il prefisso /64 — lì un attaccante dispone di 2⁶⁴ indirizzi, contare l'indirizzo intero non limiterebbe nulla.

Il contatore viene incrementato solo dopo la validazione del form: un visitatore che sbaglia l'email tre volte di seguito non resta più bloccato un'ora per niente.

4. Il tetto giornaliero di richieste non verificate

Al massimo 3 richieste in attesa di verifica email possono trattenere uno slot nella stessa giornata. Senza questo tetto, bastavano pochi invii per congelare tutti gli slot di una data. Oltre, il visitatore riceve l'invito a riprovare più tardi o a scegliere un altro giorno (HTTP 429).

5. Il lock di prenotazione

La prenotazione di uno slot e il consumo di un invito avvengono in una sezione critica serializzata da un lock MySQL con nome, il cui nome deriva dal suo database e dal suo prefisso di tabelle (due siti sullo stesso hosting condiviso non si bloccano quindi a vicenda). Se il lock non viene ottenuto entro 5 secondi, la richiesta restituisce un HTTP 503 esplicito invece di un doppio appuntamento.

Questo lock sostituisce, dalla 1.3.0, una transazione che si basava su un SELECT nudo: sotto REPEATABLE READ non applica alcun lock di riga, e due visitatori simultanei potevano prenotare lo stesso orario.

E la doppia verifica

È il livello più efficace: anche superando tutto quanto precede, un bot non arriva mai alla sua agenda né alla sua casella di posta, dato che la notifica admin viene inviata solo dopo il clic su un link ricevuto per email. Veda La doppia verifica via email.


GDPR

Un'agenda di appuntamenti tratta potenziali dati sanitari, recapiti e storici. Le impostazioni predefinite sono volutamente conservative.

Consenso

La casella di consenso è obbligatoria e non selezionata di default sul form pubblico: «Acconsento all'uso dei miei dati di contatto per la gestione del mio appuntamento.» Una prenotazione senza consenso viene rifiutata lato server, non solo lato browser.

Minimizzazione

  • Nessun indirizzo IP viene memorizzato nel database. Il limite orario usa un contatore temporaneo (transient) la cui chiave è un digest dell'ambito di rete, eliminato dopo un'ora.
  • Nessuno user agent, nessun tracker, nessun cookie depositato dal plugin.
  • Nessun dato viene inviato a un servizio terzo: nessuna CDN, nessuna chiamata esterna, nessuna telemetria.
  • Le richieste mai verificate vengono eliminate dopo 48 ore — non lasciano alcun dato dietro di sé.
  • Gli appuntamenti annullati non vengono più restituiti dall'API dell'agenda: i dati personali inutili non circolano.

Anonimizzazione automatica

Impostazione retention_months, 24 mesi di default. Ogni ora, gli appuntamenti conclusi da più tempo di questo termine vengono anonimizzati sul posto: il nome viene sostituito da «Anonimizzato», il telefono e l'email vengono svuotati, il messaggio del cliente e le note interne vengono cancellati. La riga resta, il che preserva lo storico statistico dell'attività (quanti appuntamenti, quando, per quale prestazione) senza conservare il minimo dato personale.

Imposti 0 per disattivare l'anonimizzazione automatica — con cognizione di causa.

Da notare: l'anonimizzazione riguarda gli appuntamenti che riportano un indirizzo email. Un appuntamento inserito a mano senza email (solo nome e telefono) non viene raggiunto dall'eliminazione automatica; lo elimini manualmente se la sua politica di conservazione lo richiede.

Diritto di accesso e diritto alla cancellazione

Il plugin non si aggancia agli esportatori/cancellatori nativi di WordPress (questi lavorano sugli account utente, mentre i clienti non ne hanno). Per gestire una richiesta:

  • Accesso — cerchi la persona nella rubrica clienti (nome, telefono o email) e scorra i suoi appuntamenti in agenda. Gli amministratori di database possono anche interrogare direttamente {prefix}_owag_appointments e {prefix}_owag_customers sulla colonna customer_email / email.
  • Cancellazione — elimini la scheda della rubrica, poi annulli o lasci anonimizzare gli appuntamenti interessati. Una cancellazione immediata si esegue nel database su customer_email.
-- Effacement manuel des données personnelles d'une personne (adaptez le préfixe).
UPDATE wp_owag_appointments
   SET customer_name = 'Anonymisé', customer_phone = '', customer_email = '',
       customer_msg = NULL, admin_notes = NULL
 WHERE customer_email = 'personne@example.com';

DELETE FROM wp_owag_customers WHERE email = 'personne@example.com';

Registro dei trattamenti

Per il suo registro: finalità gestione degli appuntamenti; base giuridica consenso (prenotazione online) oppure esecuzione di un contratto / misure precontrattuali (appuntamento preso al telefono); categorie identità, recapiti, contenuto del messaggio, note interne; durata 24 mesi di default, poi anonimizzazione; destinatari nessun responsabile del trattamento oltre al suo hoster e al suo servizio di invio email.


Shortcode

[ow_agenda] — la prenotazione visitatore

Da inserire in una pagina pubblica. Nessun attributo: la prestazione, la durata e gli orari vengono dalle impostazioni. Lo shortcode carica il proprio foglio di stile e il proprio script (meno di 12 KB in totale, senza dipendenze) e restituisce un contenitore che si riempie dopo la prima chiamata all'API.

[ow_agenda]

È questo shortcode a interpretare il parametro URL ?owag_invite=<token>: la stessa pagina serve la consulenza standard e le sedute su invito.

[ow_agenda_admin] — la pagina di gestione

Da inserire in una pagina dedicata. Nessun attributo. Lo shortcode gestisce l'accesso da sé:

  • visitatore non loggato → link di accesso che rimanda alla pagina;
  • loggato senza la capability owag_manage → messaggio di accesso riservato;
  • loggato con la capability → l'interfaccia completa (agenda, in attesa, clienti, inviti).
[ow_agenda_admin]

Le due pagine vengono create automaticamente all'attivazione con questi shortcode. Se le ha eliminate, basta creare una pagina e incollarvi lo shortcode — ricordi allora di aggiornare l'opzione owag_page_admin (o owag_page_booking) affinché i link delle email e il manifest puntino al posto giusto.

Le pagine autonome

Quattro parametri URL, intercettati su qualsiasi pagina del sito, producono pagine autonome servite fuori dal tema (rendering minimale, noindex,nofollow):

URLRuolo
?owag_verify=<uid>Verifica della richiesta da parte del cliente (doppio opt-in)
?owag_cancel=<uid>Annullamento online da parte del cliente
?owag_admin_action=confirm|refuse&uid=…&sig=…Conferma / rifiuto dall'email admin
?owag_manifest=1Manifest applicativo della pagina Agenda

Queste pagine non eseguono mai un'azione al caricamento: mostrano un riepilogo e un pulsante. Nessun bot, nessun antivirus di posta, nessun prefetch del browser può confermare o annullare un appuntamento al posto di un essere umano.


REST API

Tutti gli endpoint vivono sotto il namespace owag/v1, alla consueta radice REST (https://example.com/wp-json/owag/v1/…).

Endpoint pubblici

Nessuna autenticazione: sono le route del widget di prenotazione e dei link ricevuti per email. La loro sicurezza si basa su token casuali (32 caratteri esadecimali provenienti da un generatore crittografico), su firme HMAC e sulle protezioni descritte in Anti-spam.

MetodoPercorsoParametriRuolo
GET/public/daysfrom (Y-m-d, default: oggi), token (invito, facoltativo)Restituisce label, duration e days: 14 giorni a partire da from, ciascuno con il proprio numero di slot liberi
GET/public/slotsdate (Y-m-d, obbligatorio), tokenRestituisce slots: gli orari di inizio liberi (HH:MM)
POST/public/bookdate, time, name, phone, email, message, consent, website (trappola), ts (timestamp), tokenCrea la richiesta; restituisce status e il messaggio da mostrare
POST/public/verifyuidVerifica una richiesta unverified
POST/public/canceluidAnnulla un appuntamento pending o confirmed, entro il limite di preavviso
POST/public/admin-actionuid, action (confirm|refuse), sigConferma o rifiuta dall'email admin (firma HMAC)

Esempio di prenotazione:

curl -X POST https://example.com/wp-json/owag/v1/public/book \
  -H 'Content-Type: application/json' \
  -d '{
    "date": "2026-09-15",
    "time": "14:30",
    "name": "Marie Dupont",
    "phone": "0470 12 34 56",
    "email": "marie@example.com",
    "message": "Première visite",
    "consent": 1,
    "website": "",
    "ts": 1757942400
  }'
{
  "ok": true,
  "status": "unverified",
  "message": "Un dernier geste : un e-mail vient de vous être envoyé…"
}

Endpoint di amministrazione

Tutti richiedono la capability owag_manage e un nonce REST WordPress valido (header X-WP-Nonce).

MetodoPercorsoParametriRuolo
GET/admin/agendafrom, to (Y-m-d)events (l'intervallo richiesto, annullati esclusi) e pending (tutte le richieste in attesa future)
POST/admin/appointmentkind (manual|block|consult|seance), date, time, duration (5–720 min), label, name, phone, email, notes, force, send_emailCrea un appuntamento manuale o un blocco
POST/admin/appointment/{id}status (pending|confirmed|cancelled|done|noshow), name, phone, email, label, notes, date, time, duration, force, silentAggiorna, sposta, cambia lo stato. silent=1 sopprime qualsiasi invio di email
GET/admin/customersq (ricerca)La rubrica (massimo 200 schede)
POST/admin/customersname (obbligatorio), phone, email, notesCrea una scheda
POST/admin/customers/{id}come sopraAggiorna una scheda
DELETE/admin/customers/{id}Elimina una scheda
GET/admin/invitesGli inviti aperti (mai usati o liberati, non scaduti)
POST/admin/invitesname (obbligatorio), label (obbligatorio), duration (15–720), days_valid (1–365, default 60), email, phone, send_emailCrea un invito; restituisce url e email_sent
DELETE/admin/invites/{id}Elimina un invito
GET/admin/settingsLe impostazioni effettive
POST/admin/settingscorpo JSON (veda Riferimento impostazioni)Salva le impostazioni

Ogni route dichiara esplicitamente il proprio controllo di accesso; la capability viene verificata prima dell'esecuzione di qualsiasi elaborazione.

Codici di errore

Gli errori sono WP_Error standard, con un codice leggibile e uno stato HTTP.

CodiceHTTPSignificato
owag_spam403Trappola per bot compilata, o timestamp mancante / troppo recente
owag_rate429Limite orario raggiunto per questo indirizzo
owag_day_full429Troppe richieste in attesa di verifica in questa data
owag_busy503Lock di prenotazione non ottenuto — riprovare tra un istante
owag_slot_taken409Slot preso nel frattempo
owag_overlap409Sovrapposizione rilevata (admin) — rinviare con force
owag_invite_invalid404Token di invito sconosciuto
owag_invite_used410Invito già consumato
owag_invite_expired410Invito scaduto
owag_too_late403Annullamento online fuori dal termine di preavviso
owag_bad_sig403Firma HMAC non valida
owag_not_found404Appuntamento o scheda non trovati
owag_name, owag_phone, owag_email, owag_consent400Campo non valido o consenso mancante
owag_bad_input, owag_bad_date400Data, ora o input non validi
owag_noop400Richiesta di aggiornamento vuota
owag_insert500Scrittura nel database fallita

Hook per sviluppatori

Nella 1.3.1, OW Agenda non espone né filtri né action pubbliche: non c'è alcuna API di estensione da documentare, e nulla di quanto segue va indovinato. L'unico hook utilizzabile è l'evento pianificato owag_hourly_event, al quale può agganciare la propria manutenzione:

add_action( 'owag_hourly_event', function () {
    // Votre traitement horaire, exécuté juste après celui du plugin.
} );

Per tutto il resto, la REST API è il punto di integrazione: espone esattamente ciò che fa l'interfaccia, né più né meno.


Riferimento impostazioni

Tutte le impostazioni stanno in una sola opzione, owag_settings. Lettura e scrittura in PHP:

$s = owag_settings();          // réglages effectifs (défauts + enregistrés)
$duree = (int) $s['consult_duration'];

update_option( 'owag_settings', array_merge( owag_settings(), [
    'consult_duration' => 45,
    'buffer'           => 10,
] ) );

Valori predefiniti

[
    // Horaires : clé = 1 (lundi) … 7 (dimanche), valeur = liste de plages [début, fin]
    'hours' => [
        '1' => [ [ '09:00', '18:00' ] ],
        '2' => [ [ '09:00', '18:00' ] ],
        '3' => [ [ '09:00', '18:00' ] ],
        '4' => [ [ '09:00', '18:00' ] ],
        '5' => [ [ '09:00', '18:00' ] ],
        '6' => [],   // samedi fermé
        '7' => [],   // dimanche fermé
    ],
    'slot_step'           => 30,   // granularité des créneaux proposés (minutes)
    'consult_duration'    => 60,   // durée d'une consultation (minutes)
    'buffer'              => 0,    // battement autour de chaque rendez-vous (minutes)
    'min_notice_hours'    => 24,   // délai minimum avant réservation
    'max_advance_days'    => 60,   // horizon maximum de réservation
    'auto_confirm'        => 0,    // 0 = validation manuelle, 1 = confirmation automatique
    'email_verify'        => 1,    // double vérification par e-mail
    'cancel_notice_hours' => 24,   // préavis d'annulation en ligne par le client
    'notify_email'        => get_option( 'admin_email' ),
    'retention_months'    => 24,   // anonymisation des RDV passés (0 = jamais)
    'consult_label'       => 'Consultation',
]

Dettaglio

ImpostazioneTipoLimiti dell'interfacciaEffetto
hoursarray1 o 2 fasce al giornoDue fasce permettono la pausa pranzo. Una fascia viene mantenuta solo se inizio e fine sono validi e se inizio < fine. Un giorno vuoto = chiuso
slot_stepintero5 → 120 minSpaziatura degli orari proposti. Più è fine, più l'elenco è lungo
consult_durationintero15 → 480 minDurata riservata in agenda per una consulenza web
bufferintero0 → 120 minMargine applicato prima e dopo lo slot candidato
min_notice_hoursintero0 → 168 hNon viene proposto nulla prima di adesso + questo termine
max_advance_daysintero7 → 365 ggOrizzonte oltre il quale non viene più proposto alcuno slot
auto_confirm0 / 1Conferma manuale o conferma immediata
email_verify0 / 1Doppio opt-in via email (da lasciare attivo)
cancel_notice_hoursintero0 → 168 hOltre, l'annullamento online viene rifiutato con un messaggio che invita a telefonare
notify_emailemailDestinatario delle notifiche admin; funge anche da ORGANIZER nei file ICS
retention_monthsintero0 → 120 mesiAnonimizzazione degli appuntamenti conclusi; 0 disattiva
consult_labeltestoTitolo mostrato sul widget di prenotazione

Due costanti non configurabili meritano di essere conosciute, perché governano il comportamento del doppio opt-in: lo slot di una richiesta non verificata viene trattenuto per 45 minuti, e la richiesta viene eliminata dopo 48 ore.

Il salvataggio tramite REST API accetta le stesse chiavi in JSON; gli interi vengono riportati a un minimo di zero, l'indirizzo di notifica viene accettato solo se valido, e ogni fascia oraria viene rivalidata lato server.


Dati memorizzati

Tre tabelle, tutte precedute dal prefisso della sua installazione. Le date sono DATETIME in ora locale del sito, mai in UTC — è questo a rendere le query leggibili e i confronti di orario banali.

{prefix}_owag_appointments

ColonnaTipoNote
idBIGINTChiave primaria
uidCHAR(32)Token pubblico univoco (esadecimale, generatore crittografico). Fa da chiave per i link di verifica, di annullamento e di azione admin, e da UID ICS
kindVARCHAR(16)consult, seance, manual, block
service_labelVARCHAR(120)Titolo mostrato
customer_name, customer_phone, customer_emailVARCHARRecapiti
customer_msgTEXTMessaggio lasciato dal cliente
admin_notesTEXTNote interne, mai inviate al cliente
start_dt, end_dtDATETIMEEstremi dello slot (indicizzati su start_dt)
statusVARCHAR(16)unverified, pending, confirmed, cancelled, done, noshow
sourceVARCHAR(16)web, invite, admin
invite_idBIGINTInvito di origine, se presente
reminder_sentTINYINTFlag di promemoria (riportato a 0 in caso di spostamento)
created_at, updated_atDATETIMEupdated_at alimenta il numero di revisione ICS

{prefix}_owag_invites

id, token (CHAR(32), univoco), recapiti del cliente, service_label, duration_min, expires_at, appointment_id (valorizzato quando il link viene consumato, riportato a NULL se l'appuntamento viene annullato), created_at.

{prefix}_owag_customers

id, name, phone, email, notes, created_at, updated_at. Indici su name ed email.

Una sola opzione contiene la configurazione (owag_settings); le altre sono tecniche: owag_admin_secret (segreto HMAC), owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin.


Internazionalizzazione

L'intera interfaccia è traducibile: impostazioni di amministrazione, widget di prenotazione, pagina Agenda, pagine autonome, messaggi dell'API e modelli di email. La lingua sorgente è l'inglese; il plugin dichiara il dominio di traduzione ow-agenda e il percorso /languages.

Il pacchetto consegna il template languages/ow-agenda.pot. È fornita una traduzione francese completa, prodotta a partire dalla formulazione originale dell'interfaccia.

Installare una traduzione manualmente

Compili il .po e collochi il .mo nella cartella delle traduzioni di WordPress:

msgfmt ow-agenda-fr_FR.po -o ow-agenda-fr_FR.mo
# puis : wp-content/languages/plugins/ow-agenda-fr_FR.mo

WordPress carica il catalogo alla prima stringa tradotta; non è necessaria alcuna chiamata manuale.

Due trappole per i traduttori

  • Le stringhe destinate al JavaScript usano segnaposto numerati (%1$s, %2$s) e mai un %s nudo: il piccolo formattatore incorporato negli script capisce solo quelli. Un segnaposto non numerato verrebbe mostrato alla lettera.
  • Due stringhe sono formati di data PHP, non frasi: l, F j, Y \a\t g:i a e l j F Y \a\t H:i. Le traduca come formati (riordinando i token, facendo l'escape delle lettere letterali con una barra rovesciata). Il francese usa l j F Y \à H\hi.

Disinstallazione

Disattivare il plugin fa una cosa sola: eliminare l'attività pianificata oraria. I suoi dati, le sue impostazioni e le sue pagine restano intatti, e tutto riparte alla riattivazione.

Eliminare il plugin da WordPress esegue la disinstallazione completa:

  • eliminazione delle tre tabelle (owag_appointments, owag_invites, owag_customers);
  • eliminazione delle opzioni owag_settings, owag_admin_secret, owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin;
  • eliminazione dell'attività pianificata;
  • rimozione della capability owag_manage dal ruolo amministratore.

Le due pagine create all'attivazione non vengono eliminate — possono essere state rielaborate, messe a menu, indicizzate. Sta a Lei spostarle nel cestino se non le vuole più.

L'eliminazione delle tabelle è definitiva. Esporti prima il suo database se lo storico degli appuntamenti ha un valore per Lei.


Risoluzione problemi

Non compare alcuno slot sulla pagina di prenotazione

Scorra l'elenco nell'ordine:

  1. Gli orari del giorno sono compilati? Un giorno vuoto è un giorno chiuso.
  2. Il preavviso minimo (24 h di default) nasconde necessariamente oggi e una parte di domani.
  3. La durata rientra nella fascia? Con una fascia 09:00–12:00 e una durata di 240 minuti, nessuno slot può esistere.
  4. L'orizzonte: i giorni oltre max_advance_days non vengono mai proposti.
  5. Il margine: un margine ampio su un calendario carico può chiudere tutto.
  6. Un blocco copre forse la giornata. Apra la pagina Agenda al giorno interessato.
  7. Il fuso orario del sito (Impostazioni → Generali): un fuso impostato male sfalsa tutti i calcoli.

Le email non arrivano

È quasi sempre la deliverability, non il plugin.

  1. Verifichi che l'appuntamento esista davvero nella pagina Agenda: se c'è, il plugin ha fatto il suo lavoro.
  2. Installi un plugin SMTP (Fluent SMTP, WP Mail SMTP…). La funzione mail() di PHP viene rifiutata dalla stragrande maggioranza dei server di ricezione.
  3. Verifichi SPF, DKIM e DMARC del suo dominio.
  4. Testi l'indirizzo in OW Agenda → Notifiche admin inviate a: un indirizzo non valido blocca silenziosamente le notifiche.

Il promemoria del giorno prima non è partito

Il promemoria dipende da WP-Cron, che dipende dal traffico. Su un sito poco visitato, passi a un vero cron di sistema (veda Promemoria e attività pianificata). Verifichi anche che l'appuntamento sia effettivamente confermato, che riporti un indirizzo email e che non si tratti di un blocco.

La pagina Agenda mostra «L'accesso è riservato al team»

L'utente loggato non ha la capability owag_manage. Viene assegnata agli amministratori all'attivazione; per gli altri ruoli, veda Installazione.

Il pulsante «Conferma» dell'email mostra «Link non valido»

Tre cause possibili: il link è stato troncato dal client di posta (provi a copiare l'URL completo), l'appuntamento è già stato gestito (il messaggio lo precisa), oppure il segreto HMAC del sito è stato rigenerato. In quest'ultimo caso, proceda dalla pagina Agenda: i vecchi link non possono più essere validati, per costruzione.

Due appuntamenti finiscono sullo stesso slot

Dalla 1.3.0 è impossibile tramite la prenotazione online. In compenso, l'admin può forzare una sovrapposizione dalla pagina Agenda (il plugin lo segnala e chiede conferma): verifichi prima che non si tratti di una forzatura voluta. Verifichi anche che il suo database supporti effettivamente GET_LOCK() — un hosting esotico restituirebbe allora errori 503 alla prenotazione, invece di doppioni.

Le pagine «Prenota» e «Agenda» non sono state create

Vengono create una sola volta, alla primissima attivazione. Se le ha eliminate, crei due pagine con gli shortcode [ow_agenda] e [ow_agenda_admin], poi vi punti le opzioni owag_page_booking e owag_page_admin affinché i link delle email restino corretti:

update_option( 'owag_page_booking', 42 );  // ID de votre page de réservation
update_option( 'owag_page_admin', 43 );    // ID de votre page Agenda

Il file calendario non è allegato

Il file viene scritto nella directory temporanea del server tramite l'API file di WordPress. Se questa directory non è scrivibile (quota, permessi, hosting bloccato), l'email parte senza allegato invece di fallire. Verifichi i permessi di scrittura e lo spazio su disco.

Gli orari sono sfalsati di un'ora

Impostazioni → Generali → Fuso orario. Scelga una città (Europe/Brussels) piuttosto che uno scostamento UTC fisso: solo un fuso con nome gestisce il passaggio all'ora legale.


FAQ

OW Agenda è davvero gratuito? Sì. GPL-2.0-or-later, scaricabile in .zip da https://optionweb.dev/it/addons/ow-agenda/. Nessuna versione Pro, nessuna chiave di licenza, nessuna funzionalità bloccata, nessun account da creare, nessuna quota di appuntamenti.

Gli slot online tengono conto degli appuntamenti presi al telefono? Sì. Ogni evento dell'agenda — prenotazione web, appuntamento inserito a mano, seduta su invito, blocco — rende la propria fascia oraria non disponibile alla prenotazione online.

Il cliente deve creare un account? No. Nessun account, nessuna password. Tutte le azioni del cliente (verifica, annullamento) passano da link privati ricevuti per email.

Si possono gestire più professionisti o più sale? No. OW Agenda descrive un solo calendario. Per due agende indipendenti servono due siti (o due siti di una rete multisite).

Si sincronizza con Google Calendar? Nel senso che conta per il cliente: sì. Ogni conferma incorpora un file calendario standard che aggiunge — e aggiorna, ed elimina — l'evento in Google Calendar, Outlook o nel calendario dell'iPhone. Il plugin non legge invece le sue agende esterne: le sue indisponibilità personali si inseriscono come blocchi.

Si può far pagare un acconto alla prenotazione? No, è fuori dal perimetro dichiarato del plugin.

Quante prestazioni si possono proporre online? Una sola, di cui sceglie Lei l'etichetta e la durata. Le altre prestazioni passano dagli inviti per le sedute, che le lasciano fissare titolo e durata caso per caso. È una scelta deliberata: un menu di prestazioni su una pagina pubblica moltiplica le richieste mal indirizzate.

Funziona su un multisite? Sì. Ogni sito della rete ha le proprie tabelle, le proprie impostazioni e la propria agenda.

Il plugin rallenta il sito? No. Nessuno script viene caricato al di fuori delle due pagine interessate; il widget di prenotazione pesa meno di 12 KB, senza jQuery né framework. Il lavoro periodico sta in un'unica attività oraria.

Cosa succede se un cliente non verifica mai la sua email? Il suo slot torna disponibile dopo 45 minuti e la sua richiesta viene eliminata dopo 48 ore. Lei non ne sente mai parlare.

Dove trovo il supporto?


Changelog

1.3.1

Conformità

  • Le pagine autonome di azione, verifica e annullamento non stampano più il proprio CSS né il proprio JavaScript inline: entrambi sono ora file registrati e serviti dall'API di enqueue di WordPress. I due colori variabili dei pulsanti passano da proprietà CSS personalizzate, e lo script è configurato tramite wp_localize_script().
  • I cataloghi di traduzione non sono più inclusi nel pacchetto: viene consegnato solo languages/ow-agenda.pot, mentre il francese è distribuito dai language pack WordPress.org alimentati da translate.wordpress.org.
  • La versione minima di WordPress torna a 6.3: nel pacchetto non c'è più nulla che dipenda dal rilevamento delle traduzioni incorporate introdotto nella 6.7.

REST API

  • Ogni route di amministrazione dichiara ora il proprio permission_callback in modo esplicito, invece di condividerlo tramite array_merge(). Il controllo di capability era già applicato; ora è visibile all'analisi statica.

Nessun cambiamento di comportamento.

1.3.0

Internazionalizzazione

  • Plugin interamente traducibile (dominio ow-agenda, inglese come lingua sorgente): impostazioni, pagine pubbliche, messaggi dell'API, email e interfaccia JavaScript.
  • Template languages/ow-agenda.pot consegnato e traduzione francese completa.

Sicurezza

  • Gli identificativi pubblici degli appuntamenti e i token di invito sono generati da un generatore crittografico (random_bytes()). Questi token sono l'unica autenticazione dei link di annullamento, di verifica e di invito.
  • La trappola per bot e il timestamp sono diventati obbligatori: ometterli disattivava i controlli anti-spam.
  • Il limite orario è aggregato per prefisso /64 in IPv6, e un tetto giornaliero limita le richieste non verificate — un visitatore non può più trattenere tutti gli slot di una giornata.
  • Il limite viene conteggiato solo dopo la validazione del form: un errore di battitura non blocca più un visitatore legittimo per un'ora.

Affidabilità

  • Le prenotazioni simultanee di uno stesso slot sono serializzate da un lock MySQL con nome. La transazione precedente non applicava alcun lock di riga: due visitatori potevano prenotare lo stesso orario.
  • Il promemoria del giorno prima usa una finestra mobile da 12 a 36 h e recupera il ritardo; ogni invio è prenotato in modo atomico, due esecuzioni di cron non possono più inviare due volte lo stesso promemoria.
  • L'attività oraria si riprogramma automaticamente se sparisce: promemoria, eliminazione e anonimizzazione non possono più fermarsi in silenzio.
  • Lo spostamento di un appuntamento aggiorna il calendario del cliente (SEQUENCE, METHOD:REQUEST, organizzatore e partecipante); l'annullamento invia un METHOD:CANCEL che elimina l'evento.
  • Le date del widget sono calcolate in ora locale e non in UTC: niente più giornata persa per i visitatori a est di UTC.
  • L'annullamento di un appuntamento nato da un invito libera l'invito, che torna utilizzabile.
  • Gli appuntamenti annullati e le richieste non verificate scadute non vengono più restituiti all'agenda: meno dati personali nelle risposte, niente più appuntamenti fantasma.

1.2.1

  • Conformità Plugin Check: escaping degli output, sanitizzazione degli input, nonce sulle impostazioni, readme.
  • La disinstallazione elimina anche la tabella della rubrica clienti e il segreto HMAC.

1.2.0

  • Email HTML (layout a scheda, colore d'accento del sito) per tutte le notifiche.
  • Pulsanti Conferma / Rifiuta nell'email admin (link firmati HMAC).
  • Rubrica clienti: ricerca, creazione, modifica, eliminazione, scorciatoie verso un nuovo appuntamento e un invito.

1.1.0

  • Doppia verifica via email contro i bot (slot trattenuto 45 minuti, eliminazione dopo 48 ore).

1.0.0

  • Versione iniziale: prenotazione online, agenda di amministrazione mobile-first, inviti per le sedute, email con file calendario e promemoria del giorno prima.

Realizzato da OptionWeb — Julien Daniel, Châtelet, Belgio.