193 lines
6.5 KiB
PHP
193 lines
6.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* push-lezioni-cron.php
|
|
* --------------------------------------------------------------------------
|
|
* Notifica push del mattino: ogni giorno all'ora impostata (default 08:00)
|
|
* avvisa chi ha lezioni prenotate OGGI.
|
|
*
|
|
* L'utente riceve UNA SOLA notifica al giorno: se ha piu' lezioni vengono
|
|
* raggruppate in un unico messaggio (title_multi / body_multi, con i
|
|
* segnaposto {count} e {lessons}).
|
|
*
|
|
* Da mettere in cron OGNI ORA: lo script controlla da solo se l'ora attuale
|
|
* corrisponde a notificationsetting.sendhour, cosi' l'orario si cambia dal
|
|
* pannello admin senza toccare il cron del server.
|
|
*
|
|
* 0 * * * * /usr/bin/php /percorso/public/push-lezioni-cron.php
|
|
*
|
|
* Per provarlo subito, ignorando l'orario:
|
|
* php push-lezioni-cron.php --force
|
|
*
|
|
* Riceve la notifica solo chi ha auth_users.pushnotification = 'Y'.
|
|
* Ogni lezione inclusa viene registrata in notificationlog: se lo script gira
|
|
* due volte nello stesso giorno non si ripete nulla.
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
|
|
require_once __DIR__ . '/class/db-functions.php';
|
|
require_once __DIR__ . '/class/push-functions.php';
|
|
|
|
$logFile = __DIR__ . '/logs/push_lezioni_cron.log';
|
|
$forza = in_array('--force', $argv ?? [], true) || isset($_GET['force']);
|
|
|
|
function scriviLog(string $file, string $messaggio): void
|
|
{
|
|
file_put_contents($file, date('Y-m-d H:i:s') . " - $messaggio\n", FILE_APPEND);
|
|
}
|
|
|
|
$db = DBHandlerSelect::getInstance()->getConnection();
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Impostazioni: per le lezioni c'e' una sola riga (daysbefore = 0)
|
|
// --------------------------------------------------------------------------
|
|
$impostazioni = pushSettings($db, 'lesson');
|
|
|
|
if (!$impostazioni) {
|
|
scriviLog($logFile, 'Nessuna impostazione attiva per le lezioni, esco.');
|
|
exit;
|
|
}
|
|
|
|
$impostazione = $impostazioni[0];
|
|
$oraPrevista = (int) substr((string) $impostazione['sendhour'], 0, 2);
|
|
|
|
if (!$forza && (int) date('G') !== $oraPrevista) {
|
|
// Non e' l'ora giusta: usciamo in silenzio (il cron gira ogni ora).
|
|
exit;
|
|
}
|
|
|
|
$giorno = date('Y-m-d');
|
|
scriviLog($logFile, "Avvio invio lezioni del $giorno (ora impostata {$impostazione['sendhour']}).");
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Lezioni di oggi.
|
|
// Stessi filtri usati da userpanel.php / api/my_lessons.php per le lezioni
|
|
// valide: status 'booked', non perse, non scadute.
|
|
// --------------------------------------------------------------------------
|
|
$stmt = $db->prepare("
|
|
SELECT
|
|
bc.idbookingclass,
|
|
bc.iduser,
|
|
ss.dateschedule,
|
|
s.servicename,
|
|
u.first_name,
|
|
u.last_name
|
|
FROM bookingclass bc
|
|
INNER JOIN serviceschedule ss ON bc.idserviceschedule = ss.idserviceschedule
|
|
INNER JOIN auth_users u ON bc.iduser = u.id
|
|
LEFT JOIN service s ON bc.idservice = s.idservice
|
|
WHERE bc.status = 'booked'
|
|
AND bc.lostlesson = 'N'
|
|
AND bc.expirylesson = 'N'
|
|
AND DATE(ss.dateschedule) = :giorno
|
|
AND u.pushnotification = 'Y'
|
|
AND u.status = 'Active'
|
|
ORDER BY bc.iduser ASC, ss.dateschedule ASC
|
|
");
|
|
$stmt->execute([':giorno' => $giorno]);
|
|
$lezioni = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Raggruppiamo per utente: una notifica a testa, non una per lezione.
|
|
// Le lezioni gia' notificate (rilancio manuale dello script) vengono escluse;
|
|
// se per un utente non ne resta nessuna, l'utente viene saltato del tutto.
|
|
// --------------------------------------------------------------------------
|
|
$perUtente = [];
|
|
|
|
foreach ($lezioni as $lezione) {
|
|
$iduser = (int) $lezione['iduser'];
|
|
|
|
if (pushGiaInviata($db, $iduser, 'lesson', (int) $lezione['idbookingclass'], 0)) {
|
|
continue;
|
|
}
|
|
|
|
$perUtente[$iduser][] = $lezione;
|
|
}
|
|
|
|
scriviLog($logFile, 'Lezioni da notificare: ' . count($lezioni) . ', utenti da avvisare: ' . count($perUtente));
|
|
|
|
if (!$perUtente) {
|
|
exit;
|
|
}
|
|
|
|
try {
|
|
$sender = new PushSender();
|
|
} catch (Throwable $e) {
|
|
scriviLog($logFile, 'ERRORE configurazione FCM: ' . $e->getMessage());
|
|
exit;
|
|
}
|
|
|
|
$inviate = 0;
|
|
$fallite = 0;
|
|
$senzaApp = 0;
|
|
|
|
foreach ($perUtente as $iduser => $lezioniUtente) {
|
|
$prima = $lezioniUtente[0];
|
|
$quante = count($lezioniUtente);
|
|
|
|
// Elenco leggibile: "Hatha Yoga alle 19:30, Yin Yoga alle 21:00"
|
|
$elenco = [];
|
|
foreach ($lezioniUtente as $l) {
|
|
$ora = (new DateTime($l['dateschedule']))->format('H:i');
|
|
$elenco[] = trim(($l['servicename'] ?? '') . " alle $ora");
|
|
}
|
|
|
|
$dataPrima = new DateTime($prima['dateschedule']);
|
|
|
|
$valori = [
|
|
'first_name' => $prima['first_name'] ?? '',
|
|
'last_name' => $prima['last_name'] ?? '',
|
|
'servicename' => $prima['servicename'] ?? '',
|
|
'date' => $dataPrima->format('d/m/Y'),
|
|
'time' => $dataPrima->format('H:i'),
|
|
'count' => $quante,
|
|
'lessons' => implode(', ', $elenco),
|
|
];
|
|
|
|
// Con piu' lezioni usiamo i testi "multi", se l'admin li ha compilati.
|
|
$titolo = $impostazione['title'];
|
|
$testo = $impostazione['body'];
|
|
|
|
if ($quante > 1) {
|
|
if (!empty($impostazione['title_multi'])) {
|
|
$titolo = $impostazione['title_multi'];
|
|
}
|
|
if (!empty($impostazione['body_multi'])) {
|
|
$testo = $impostazione['body_multi'];
|
|
}
|
|
}
|
|
|
|
$esito = $sender->sendToUser(
|
|
$db,
|
|
(int) $iduser,
|
|
pushRender($titolo, $valori),
|
|
pushRender($testo, $valori),
|
|
['type' => 'lesson', 'idbookingclass' => (int) $prima['idbookingclass'], 'count' => $quante]
|
|
);
|
|
|
|
// Utente senza dispositivi registrati: non ha ancora aperto l'app.
|
|
// Non e' un errore e non va segnato nello storico, altrimenti quando
|
|
// installera' l'app risulterebbe gia' "notificato".
|
|
if ($esito['no_devices']) {
|
|
$senzaApp++;
|
|
continue;
|
|
}
|
|
|
|
// Registriamo tutte le lezioni incluse nel messaggio: cosi' nessuna di
|
|
// esse verra' rinotificata se lo script viene rilanciato.
|
|
foreach ($lezioniUtente as $l) {
|
|
pushRegistraInvio($db, (int) $iduser, 'lesson', (int) $l['idbookingclass'], 0, $esito);
|
|
}
|
|
|
|
if ($esito['sent'] > 0) {
|
|
$inviate++;
|
|
} else {
|
|
$fallite++;
|
|
if ($esito['errors']) {
|
|
scriviLog($logFile, "Utente $iduser: " . implode(' | ', $esito['errors']));
|
|
}
|
|
}
|
|
}
|
|
|
|
scriviLog($logFile, "Fine. Notifiche inviate: $inviate, fallite: $fallite, senza app: $senzaApp.");
|