ITCCA Allievi — Plugin WordPress per la gestione iscrizioni
Plugin WordPress per gestire le iscrizioni ai corsi di Tai Chi della scuola ITCCA. Estende l'utente WordPress con i ~40 campi del registro INSXXX (dove XXX è la sigla a 3 lettere dell'insegnante che userà il plugin), espone un form pubblico di iscrizione e sincronizza i dati con un Google Sheet privato selezionabile da Drive.
Versione corrente: 1.2.0
Requisiti: WordPress ≥ 6.0, PHP ≥ 8.1
Licenza: GPL-2.0-or-later
Download: Release v1.2.0 — pacchetto itcca-allievi.zip
Indice
- Panoramica
- Modello dati
- Form pubblico di iscrizione
- Backoffice WordPress
- Integrazione Google (OAuth + Picker + Sheets)
- Sincronizzazione a due fasi
- Riconciliazione schema
- Dashboard analytics
- Mappa geografica e sedi
- Stato attivo/inattivo
- Storico fogli usati
- Sicurezza e GDPR
- Disinstallazione e pulizia dati
- Setup e sviluppo locale
- Changelog
Panoramica
Il plugin nasce per sostituire il workflow basato su fogli Excel/CSV annuali del registro INSXXX (XXX è la sigla a 3 lettere dell'insegnante che userà il plugin e collegherà il suo foglio personale, es. INSROS, INSBIA, ecc.) con una gestione integrata in WordPress, mantenendo però il foglio Google come fonte di backup e condivisione.
Funzionalità principali:
- Ruolo
allievo dedicato con ~40 campi custom mappati 1:1 sulle colonne del registro INSXXX.
- Form pubblico via shortcode
[itcca_iscrizione] con validazione client + server e feedback chiaro all'utente.
- Backoffice ricco: list table filtrabile, dashboard analitica, mappa delle residenze e sedi.
- Sincronizzazione Google Sheets bidirezionale in due fasi distinte (allineamento iniziale + push continuo).
- Riconciliazione schema per gestire colonne aggiunte/rinominate/ rimosse sul foglio senza perdere dati WordPress.
- Geocodifica indirizzi via OpenStreetMap Nominatim.
- Disinstallazione pulita che rimuove tutti i dati del plugin (con opt-out per conservarli).
Modello dati
Tutti i campi sono salvati come user_meta con prefisso itcca_, più l'email che usa il campo nativo user_email di WordPress.
Le 41 colonne del registro INSXXX sono raggruppate in sezioni:
- Anagrafica:
ins, cognome, nome, sesso (M/F), nascita_data, nascita_luogo, cf (Codice Fiscale)
- Residenza:
indirizzo, civico, comune, cap
- Contatti:
user_email, cellulare
- Calcolati (read-only):
X (età), Anno (anni di pratica)
- Tesseramento:
sede_u, centro, ruolo, grado, inizio (anno)
- Quote (decimal):
quota_uisp, quota_itcca, quota_ado
- Ricevuta/pagamento:
pag_chi, pag_il, ric_il, ric_n, att, pag, pro, ric, onl (gli ultimi 5 sono flag booleani)
- Stato:
r (R=rinnovo / N=nuovo), a (A=attivo / D=disattivo), active (derivato dal tab del foglio)
- UISP card:
uisp_n, uisp_d
- Altro:
doc, animale, elem, el_sx, el_dx, note
Il registro è centralizzato in class-fields.php come unica fonte di verità: list table, edit page, form pubblico e push su Sheet leggono sempre da lì (label, tipo, validatore, sezione, visibilità nel form).
Il valore del campo ins (sigla insegnante, es. INSXXX) è configurabile dalle impostazioni del plugin e viene impostato come default su ogni nuovo allievo creato dal form pubblico.
Calendario cinese (Animale + Elementi)
- Animale è un dropdown con i 12 segni dello zodiaco cinese, auto-calcolato dall'anno di nascita ma sovrascrivibile manualmente.
- Elemento / Elemento sinistro / Elemento destro sono dropdown con i 5 elementi (Terra, Metallo, Acqua, Legno, Fuoco), ciascuno con un pallino colorato accanto alla label (acqua azzurro, metallo grigio, terra ocra, legno verde, fuoco rosso).
Shortcode: [itcca_iscrizione] (da inserire in una pagina o articolo).
Tutti i campi sono obbligatori (asterisco rosso, ricontrollo server-side). Campi visibili al pubblico:
- Cognome, Nome
- Sesso (radio M / F)
- Data di nascita (date picker)
- Comune di nascita
- Codice fiscale
- Indirizzo di residenza, numero civico, comune di residenza, CAP
- Email, cellulare
- Checkbox consenso privacy + liberatoria (testo configurabile)
Tutti gli altri campi del registro vengono compilati dall'admin nel backoffice (sede, quote, ricevuta, flag, ecc.).
Validazioni
- Codice fiscale: regex client-side + checksum ministeriale server-side. Controllo unicità.
- Email: regex +
is_email() di WordPress, controllo unicità.
- CAP: esattamente 5 cifre.
- Cellulare: 9–15 cifre, prefisso internazionale opzionale.
- Data di nascita: nel passato, non oltre 120 anni fa.
La validazione non parte al caricamento pagina: gli errori compaiono solo dopo che l'utente esce da un campo (blur) o al click su Invia iscrizione. Al submit vengono controllati tutti i campi.
Messaggi di feedback
- Successo: banner verde "Iscrizione completata"; il form viene nascosto. Visibile anche sulla pagina di redirect (es. home) tramite parametro
?itcca_success=1, senza richiedere lo shortcode sulla stessa pagina.
- Errore generale: banner rosso con titolo esplicito.
- Errori per campo: messaggio inline sotto il campo + riepilogo in cima al form.
Protezioni
- Nonce WordPress
- Honeypot anti-bot nascosto
- Rate limiting per IP (max 5 invii / ora) via transient
Flusso di submit
- Validazione client-side (blur + submit)
- Validazione server-side (sempre)
- Crea utente WordPress con ruolo
allievo, username = slug di cognome.nome, password random
- Salva tutti i meta
- Email di conferma all'iscritto con link per impostare la password (sempre inviata, anche se la reset key fallisce → fallback a pagina password dimenticata)
- Email di notifica all'amministratore (
admin_email) con Reply-To dell'iscritto
- Push riga su Google Sheet (con retry differito via WP-Cron se fallisce)
- Redirect con
?itcca_success=1 (URL configurabile nelle impostazioni)
Tema grafico
Il form eredita il font del tema WordPress (--wp--preset--font-family--body o equivalente), con fallback sans-serif. Label e messaggi di validazione hanno dimensione aumentata per una migliore leggibilità. Il colore primario è sovrascrivibile dalle impostazioni del plugin.
Backoffice WordPress
Pagina utente standard
/wp-admin/user-edit.php?user_id=X
Sezioni a fisarmonica per ogni gruppo di campi (Anagrafica, Residenza, Tesseramento, Quote, Ricevuta, Stato, UISP, Note). Età e anni di pratica sono mostrati read-only come valori calcolati.
Pagina "Allievi ITCCA"
/wp-admin/admin.php?page=itcca-allievi
WP_List_Table con tutte le colonne principali, ordinabili
- Views: Attivi / Inattivi / Tutti (filtro per
itcca_active)
- Filtri rapidi: Centro, R (rinnovi/nuovi), A (attivi/disattivi), anno Inizio
- Ricerca per cognome, nome, CF
- Azioni bulk: Sincronizza con Google Sheet, Imposta A=D, Imposta A=A, Elimina definitivamente
- Azioni riga: Modifica, Pusha su foglio, Elimina (con conferma; richiede permesso
delete_users)
- Bottoni: Aggiungi allievo, Esporta CSV, Allinea da foglio (Fase A), Pusha tutti su foglio (Fase B forzata)
- Animale + Elementi visibili come pallini colorati direttamente in lista
L'eliminazione rimuove l'utente WordPress e tutti i meta associati (wp_delete_user). Non rimuove automaticamente la riga dal foglio Google: eventuale pulizia sul foglio va fatta manualmente.
Integrazione Google
Tre passi: credenziali su Google Cloud Console → connessione OAuth → selezione del foglio via Picker.
Wizard di setup OAuth
Sotto Allievi ITCCA → Impostazioni trovi un wizard guidato in 5 step con istruzioni in italiano e link diretti alle pagine giuste di Google Cloud Console:
- Crea/seleziona il progetto Cloud
- Abilita le API Google Sheets, Google Drive, Google Picker
- Configura la schermata di consenso OAuth
- Crea un OAuth Client ID di tipo "Web application" con il Redirect URI indicato dal plugin (basta copia/incolla)
- Crea una API Key per il Picker (frontend-only)
Validazione live della forma di Client ID/Secret/API Key con badge di stato per ogni step.
Scope richiesti
https://www.googleapis.com/auth/spreadsheets
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/userinfo.email
I token (access + refresh) vengono salvati in wp_options e rinnovati automaticamente alla scadenza.
Selezione del foglio (Google Picker)
Bottone "Seleziona foglio da Drive" → apre il Picker nativo di Google.
Una volta scelto il foglio, il plugin:
- Memorizza
spreadsheet_id, nome, URL Drive
- Auto-seleziona il primo tab "ragionevole" (ignora
ZZZ*, pivot)
- Auto-rileva il tab ZZZ degli allievi inattivi
- Confronta lo schema delle colonne con quello WP — se diverge, redirect alla pagina di Riconciliazione Schema
Sincronizzazione a due fasi
Fase A — Allineamento iniziale (foglio → WordPress)
Quando: ogni volta che colleghi un foglio nuovo (cambio anno) o rilanci manualmente "Allinea da foglio".
- Legge entrambi i tab (attivi + ZZZ) via Sheets API
- Match utenti WP tramite Codice Fiscale
- Preview con diff cella-per-cella e scelte granulari (checkbox per cella/riga, creazione nuovi allievi, azioni per "solo in WP")
- Applica selezionati, popola
itcca_sheet_row / itcca_sheet_tab, marca foglio allineato
Overlay full-screen con spinner durante operazioni lunghe.
Fase B — Push continuo (WordPress → foglio)
Attiva dopo la prima Fase A completata.
- Hook su registrazione / aggiornamento profilo → enqueue push
- Mappatura
user_id ↔ riga in itcca_sheet_row
- Tab scelto da
itcca_active (attivi vs ZZZ)
- Retry orario via WP-Cron su errori
- Bottone "Pusha tutti su foglio" per re-push completo
Cambio anno
- Picker → nuovo
spreadsheet_id
- Foglio precedente nello Storico fogli
- Reset di tutti gli
itcca_sheet_row
- Fase B disabilitata fino a nuova Fase A
- Eventuale Riconciliazione Schema
Riconciliazione schema
Il foglio Google evolve: colonne aggiunte, rinominate, rimosse. Il plugin gestisce le mutazioni preservando i dati WordPress.
Fields::baseline() contiene i 42 campi INSXXX di partenza. Fields::overrides() (in wp_options['itcca_schema_overrides']) traccia renames, soft-delete (deleted_ prefix) e additions.
Campi soft-deleted restano editabili in admin nella sezione "Campi rimossi (storico)" ma non vengono pushati su Sheet né esportati in CSV.
Dashboard analytics
/wp-admin/admin.php?page=itcca-allievi-dashboard
- KPI: età media, allievo più giovane, più anziano
- Grafico a barre: distribuzione nascite per mese
- 4 pie chart inline SVG: animale, elemento, elemento sx, elemento dx
- Filtri Attivi / Inattivi / Tutti coerenti con la list table
Mappa geografica e sedi
- Sedi di insegnamento: CRUD in Impostazioni (nome, indirizzo, lat/lng, flag "Abbandonata")
- Geocodifica: OpenStreetMap Nominatim, rate-limit 1 req/sec, cache per hash indirizzo
- Mappa Leaflet in dashboard: marker sedi (★), residenze allievi (●), sedi abbandonate in scala di grigi
- Batch geocode con progress bar da admin
Stato attivo/inattivo
- Meta
itcca_active: 1 = attivo (tab principale foglio), 0 = inattivo (tab ZZZ auto-rilevato)
- Fase A imposta il flag in base al tab di provenienza della riga
- Views Attivi/Inattivi/Tutti nella list table e dashboard
- Marker mappa differenziati per allievi inattivi
Storico fogli usati
In Impostazioni → Storico fogli usati: elenco fogli precedentemente collegati con data connessione/disconnessione. Ogni voce può essere eliminata dallo storico (non cancella il foglio su Drive).
Sicurezza e GDPR
- Nonce su tutti i form admin e sul form pubblico
- Rate limiting iscrizioni (5/ora per IP)
- Honeypot anti-bot
- Hook GDPR WordPress: export ed erase dati allievo
- Token Google salvati cifrati in
wp_options
- Header email sanitizzati contro injection
Disinstallazione e pulizia dati
WordPress → Plugin → Elimina (non "Disattiva") esegue uninstall.php:
- Rimuove ruolo
allievo, tutte le opzioni itcca_*, meta utente, cron job
- Opzione "Non cancellare nulla quando il plugin viene eliminato" in Impostazioni per conservare i dati (utile per aggiornamenti manuali via zip)
Setup e sviluppo locale
Stack Docker in /Users/fabio.arrigoni/Studio/Itcca-allievi/:
cp .env.example .env
docker compose up -d
docker compose run --rm composer install
Vedi README.md nel repository per istruzioni Google Cloud Console e comandi utili.
Changelog
v1.2.0
- Form iscrizione: validazione solo su blur/submit, messaggi Success/Error chiari, banner successo globale anche dopo redirect a home
- Form: email conferma + password sempre inviata; email admin migliorata
- Backoffice: eliminazione allievo (riga singola + bulk)
- Tipografia form: font ereditato dal tema, label e errori ingranditi
v1.1.x
- Miglioramenti UX form (touched pattern, alert strutturati, riepilogo errori)
v1.0.0
- Prima release stabile: ruolo allievo, form pubblico, sync Google Sheets Fase A/B, dashboard, mappa, riconciliazione schema, GDPR, disinstallazione