diff --git a/scripts/migrate_add_reminder_fields.php b/scripts/migrate_add_reminder_fields.php deleted file mode 100644 index 0eea06a..0000000 --- a/scripts/migrate_add_reminder_fields.php +++ /dev/null @@ -1,45 +0,0 @@ -setQuery("SHOW COLUMNS FROM #__sportsmanager_turnier"); - $existing = array_column($db->loadAssocList(), 'Field'); - $alter = []; - if (!in_array('reminder_24h_sent', $existing)) { - $alter[] = 'ADD COLUMN `reminder_24h_sent` DATETIME DEFAULT NULL'; - } - if (!in_array('reminder_3d_sent', $existing)) { - $alter[] = 'ADD COLUMN `reminder_3d_sent` DATETIME DEFAULT NULL'; - } - if (!in_array('reminder_7d_sent', $existing)) { - $alter[] = 'ADD COLUMN `reminder_7d_sent` DATETIME DEFAULT NULL'; - } - if ($alter) { - $query = 'ALTER TABLE #__sportsmanager_turnier ' . implode(', ', $alter); - $db->setQuery($query); - $db->execute(); - echo "Migration successful: reminder fields added.\n"; - } else { - echo "Migration skipped: fields already exist.\n"; - } -} - -addReminderFieldsToTurnierTable(); diff --git a/scripts/send_missing_results_reminder.php b/scripts/send_missing_results_reminder.php deleted file mode 100644 index feef687..0000000 --- a/scripts/send_missing_results_reminder.php +++ /dev/null @@ -1,53 +0,0 @@ -getQuery(true) - ->select('t.*, u.email AS user_email, v.email AS verband_email') - ->from('#__sportsmanager_turnier AS t') - ->leftJoin('#__users AS u ON t.responsible_user_id = u.id') - ->leftJoin('#__sportsmanager_verband AS v ON t.verband_id = v.verband_id') - ->where('t.letzter_tag BETWEEN ' . $db->quote($twoWeeksAgo) . ' AND ' . $db->quote($oneDayAgo)) - ->where('NOT EXISTS (SELECT 1 FROM #__sportsmanager_turnierergebnis e WHERE e.turnier_id = t.turnier_id)') - ->where('(t.reminder_sent IS NULL OR t.reminder_sent < DATE_SUB(' . $db->quote($now) . ', INTERVAL 1 DAY))'); - $db->setQuery($query); - $tournaments = $db->loadObjectList(); - - foreach ($tournaments as $tournament) { - $mailer = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); - $config = Factory::getConfig(); - $mailer->setSender([$config->get('mailfrom'), $config->get('fromname')]); - $mailer->setSubject('Erinnerung: Turnierergebnisse fehlen für ' . $tournament->turnierbezeichnung); - $body = "Für das Turnier '" . $tournament->turnierbezeichnung . "' am " . $tournament->letzter_tag . - " wurden noch keine Ergebnisse hochgeladen. Laut Turnierordnung müssen die Ergebnisse spätestens 24 Stunden nach Turnierende eingetragen werden. Bitte reichen Sie die Ergebnisse umgehend nach."; - $mailer->setBody($body); - $mailer->addRecipient($tournament->user_email); - if (!empty($tournament->verband_email)) { - $mailer->addBcc($tournament->verband_email); - } - $mailer->send(); - - // Mark reminder as sent (or log in a separate table for multiple reminders) - $db->setQuery('UPDATE #__sportsmanager_turnier SET reminder_sent = ' . $db->quote($now) . ' WHERE turnier_id = ' . (int)$tournament->turnier_id); - $db->execute(); - } -} - -sendMissingTournamentResultsReminders(); diff --git a/src/structure/components/com_sportsmanager/admin.php b/src/structure/components/com_sportsmanager/admin.php index 1a42438..dfbd2f6 100644 --- a/src/structure/components/com_sportsmanager/admin.php +++ b/src/structure/components/com_sportsmanager/admin.php @@ -661,15 +661,12 @@ function adminEinstellungen(): void $spalte_mitglieder_zeigen = $jInput->get('spalte_mitglieder_zeigen', 0, 'INT'); $turnierbaum_zeigen = $jInput->get('turnierbaum_zeigen', 0, 'INT'); $termine_beantragen = $jInput->get('termine_beantragen', 0, 'INT'); + $enableEmailReminders = $jInput->get('enable_email_reminders', 0, 'INT'); + $spielerimport_persoenliche_daten_vorauswahl = $jInput->get('spielerimport_persoenliche_daten_vorauswahl', 0, 'INT'); $api_push_key = $jInput->get('api_push_key', '', 'RAW'); - /* - $twitter_benutzername = $db->escape(trim( $jInput->get('twitter_benutzername', '', 'RAW') )); - $twitter_kennwort = !empty($twitter_benutzername) ? $db->escape(trim( $jInput->get('twitter_kennwort', '', 'RAW') )) : ""; - */ - $query = "REPLACE #__sportsmanager_einstellungen" . "\n SET name = 'basis_spielernr'" . ", wert = '$basis_spielernr'"; @@ -780,6 +777,12 @@ function adminEinstellungen(): void die($db->stderr(true)); } + $query = "REPLACE #__sportsmanager_einstellungen SET name = 'enable_email_reminders', wert = '$enableEmailReminders'"; + $db->setQuery($query); + if (!$db->execute()) { + die($db->stderr(true)); + } + redirectSportsManagerURL('&task=admin_uebersicht'); } @@ -10218,7 +10221,7 @@ function adminBegegnungenPokalrundeAuslosenForm(): void if (!$db->execute()) { die($db->stderr(true)); } - + redirectSportsManagerURL('&task=admin_begegnungen&veranstaltungid=' . $veranstaltungId); } else{ @@ -10564,6 +10567,7 @@ function adminEditTurnier(): void $turnierort = $db->escape(trim($jInput->get('turnierort', '', 'RAW'))); $erster_tag = normalisiertesDatum(sprintf("%04d-%02d-%02d", $jInput->get('erster_tag_jahr', 2000, 'INT'), $jInput->get('erster_tag_monat', 1, 'INT'), $jInput->get('erster_tag_tag', 1, 'INT'))); $mehrtaegig = $jInput->get('mehrtaegig', 0, 'INT'); + $reminder_count = $jInput->get('reminder_count', 0, 'INT'); if (!$mehrtaegig) $letzter_tag = $erster_tag; else @@ -10587,7 +10591,7 @@ function adminEditTurnier(): void } if ($id == 0) { - $query = "INSERT INTO #__sportsmanager_turnier (veranstalter_id, turnierbezeichnung, saison_id, turnierort, erster_tag" . ($letzter_tag != null ? ", letzter_tag" : "") . ", kategorie) VALUES ('$veranstalterId', '$turnierbezeichnung', '$saison_id', '$turnierort', '$erster_tag'" . ($letzter_tag != null ? ", '$letzter_tag'" : "") . ", '$kategorie');"; + $query = "INSERT INTO #__sportsmanager_turnier (veranstalter_id, turnierbezeichnung, saison_id, turnierort, erster_tag" . ($letzter_tag != null ? ", letzter_tag" : "") . ", kategorie, reminder_count) VALUES ('$veranstalterId', '$turnierbezeichnung', '$saison_id', '$turnierort', '$erster_tag'" . ($letzter_tag != null ? ", '$letzter_tag'" : "") . ", '$kategorie', '0');"; $db->setQuery($query); if (!$db->execute()) { die($db->stderr(true)); @@ -10601,7 +10605,8 @@ function adminEditTurnier(): void . "\n turnierort = '$turnierort'," . "\n erster_tag = '$erster_tag'," . "\n letzter_tag = " . ($letzter_tag != null ? "'$letzter_tag'" : "NULL") . "," - . "\n kategorie = '$kategorie'" + . "\n kategorie = '$kategorie'," + . "\n reminder_count = '$reminder_count'" . "\n WHERE turnier_id = $id"; $db->setQuery($query); if (!$db->execute()) { diff --git a/src/structure/components/com_sportsmanager/database/update.php b/src/structure/components/com_sportsmanager/database/update.php index 9b3055b..e824373 100644 --- a/src/structure/components/com_sportsmanager/database/update.php +++ b/src/structure/components/com_sportsmanager/database/update.php @@ -5300,11 +5300,11 @@ function updateDatabase(): void $query = "INSERT IGNORE #__sportsmanager_einstellungen SET name = 'verband_anzeigen', wert = '1';"; $db->setQuery( $query ); if (!$db->execute()) { die($db->stderr(true)); } - + $query = "INSERT IGNORE #__sportsmanager_einstellungen SET name = 'turnierbaum_zeigen', wert = '0';"; $db->setQuery( $query ); if (!$db->execute()) { die($db->stderr(true)); } - + $query = "INSERT IGNORE #__sportsmanager_einstellungen SET name = 'spalte_mitglieder_zeigen', wert = '1';"; $db->setQuery( $query ); if (!$db->execute()) { die($db->stderr(true)); } @@ -5318,6 +5318,24 @@ function updateDatabase(): void } } + if ($datenbank_version < 108) { + $query = "ALTER TABLE #__sportsmanager_turnier ADD COLUMN `reminder_count` TINYINT DEFAULT '3'"; // 3: prevent email flood for past tournaments + $db->setQuery($query); + if (!$db->execute()) { die($db->stderr(true)); } + + $query = "INSERT IGNORE #__sportsmanager_einstellungen SET name = 'enable_email_reminders', wert = '0';"; + $db->setQuery( $query ); + if (!$db->execute()) { die($db->stderr(true)); } + + $query = "UPDATE #__sportsmanager_einstellungen" + . "\n SET wert = '108'" + . "\n WHERE name = 'datenbank_version'"; + $db->setQuery($query); + if (!$db->execute()) { + die($db->stderr(true)); + } + } + if ($termin_aktionen_email_setzen) { $query = "SELECT aktion_user_id, termin_aktion_id" . "\n FROM #__sportsmanager_termin_aktion"; diff --git a/src/structure/components/com_sportsmanager/sportsmanager.php b/src/structure/components/com_sportsmanager/sportsmanager.php index bec7237..5d0b164 100644 --- a/src/structure/components/com_sportsmanager/sportsmanager.php +++ b/src/structure/components/com_sportsmanager/sportsmanager.php @@ -42,11 +42,14 @@ require_once JPATH_SITE . '/components/com_sportsmanager/views/sportsmanager/vie require_once JPATH_SITE . '/components/com_sportsmanager/views/sportsmanager/view_admin.php'; require_once JPATH_SITE . '/components/com_sportsmanager/views/sportsmanager/view_ticker.php'; require_once JPATH_SITE . '/components/com_sportsmanager/util/image.php'; +require_once JPATH_SITE . '/components/com_sportsmanager/util/email.php'; require_once JPATH_SITE . '/components/com_sportsmanager/database/update.php'; // will also include init.php and util.php initDatabase(); updateDatabase(); +sentEmailReminders(); + if (isset($_POST['filter_saison_id'])) setcookie('sportsmanager_filter_saison_id', $_POST['filter_saison_id'], time() + (60 * 60 * 24)); else if (isset($_REQUEST['filter_saison_id'])) diff --git a/src/structure/components/com_sportsmanager/util/email.php b/src/structure/components/com_sportsmanager/util/email.php new file mode 100644 index 0000000..4b2b5c5 --- /dev/null +++ b/src/structure/components/com_sportsmanager/util/email.php @@ -0,0 +1,125 @@ +get(SiteApplication::class); + $db = getDatabase(); + + $query = $db->getQuery(true) + ->select('wert') + ->from('#__sportsmanager_einstellungen') + ->where('name = ' . $db->quote('enable_email_reminders')); + $row = loadResult($db, $query); + + if (!$row) { + return; // quit when email reminders are disabled + } + + $query = $db->getQuery(true) + ->select('tournament.turnier_id, tournament.turnierbezeichnung, tournament.letzter_tag, tournament.reminder_count, GROUP_CONCAT(user.email SEPARATOR ", ") as emails') + ->from($db->quoteName('#__sportsmanager_turnier', 'tournament')) + ->join('INNER', $db->quoteName('#__sportsmanager_berechtigt_fuer_turnier', 'entitled') . ' ON tournament.turnier_id = entitled.berechtigt_turnier_id') + ->join('INNER', $db->quoteName('#__users', 'user') . ' ON entitled.berechtigt_user_id = user.id') + ->where('tournament.reminder_count < 3') + ->group('tournament.turnier_id, tournament.turnierbezeichnung'); + $rows = loadObjectList($db, $query); + + if(!empty($rows)) { + $mailFrom = $app->getCfg('mailfrom'); + $fromName = $app->getCfg('fromname'); + + $mailer = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); + $mailer->setSender($mailFrom, $fromName); + foreach ($rows as $row) { + $currentReminder = $row->reminder_count + 1; + + if (hasResultsAlready($db, $row)) { + updateDBReminders($db, $row, 3); // do not sent any more reminders + continue; + } + + if (!isset($row->emails) || $row->emails == "" || $row->emails == NULL) { + Log::add('can\'t sent ' . $currentReminder .'. email reminder for tournament ' . $row->turnierbezeichnung . ': no recipient set', Log::WARNING, 'com_sportsmanager'); + continue; + } + + $now = new DateTime(); + $last_day = new DateTime($row->letzter_tag); + $last_day->modify('+1 day'); // start to count at the end of the day, not at the beginning + $diff = $now->getTimestamp() - $last_day->getTimestamp(); + + $reminderDelays = [ + 1 => 24*60*60, // 24h + 2 => 3*24*60*60, // 3d + 3 => 13*24*60*60 // 13d + ]; + + foreach ($reminderDelays as $count => $delay) { + if ($diff >= $delay && $row->reminder_count < $count) { + $subject = ($row->reminder_count == 2 ? "Letzte " : "") . "Erinnerung: " . $row->turnierbezeichnung . " Ergebnisse einreichen!"; + $body = "Hi," + . "\n\nDies ist die " . $currentReminder . ". " . ($row->reminder_count == 2 ? "*und damit letzte* " : "") . "Erinnerung die Turnierergebnisse einzureichen." + . "\n\nTurnier: " . $row->turnierbezeichnung + . "\nTurnierende: " . FormatiertesDatum($row->letzter_tag, false, false) + . "\n\nLaut Turnierordnung müssen die Ergebnisse spätestens 24 Stunden nach Turnierende eingetragen werden. Bitte reich die Ergebnisse umgehend nach." + . "\n\nDu erhältst diese Mail, weil du als Berechtigter für das Turnier eingetragen wurdest. Falls du nicht der Veranstalter bist, leite diese Email bitte entsprechend weiter." + . "\n\nHochladen der Ergebnisse über " . SportsManagerURL('&task=admin_turnierdisziplinen&turnierid=' . $row->turnier_id, -1) . "."; + + $mailer->setSubject($subject); + $mailer->setBody($body); + + $emailArray = explode(", ", $row->emails); + foreach ($emailArray as $email) { + $mailer->addBcc($email); + } + $mailer->send(); + + updateDBReminders($db, $currentReminder, $row->turnier_id); + } + } + } + } +} + +function updateDBReminders($db, $reminder, $tournamentId): void +{ + $query = $db->getQuery(true) + ->update($db->quoteName('#__sportsmanager_turnier')) + ->set($db->quoteName('reminder_count') . ' = ' . $db->quote($reminder)) + ->where($db->quoteName('turnier_id') . ' = ' . $db->quote($tournamentId)); + + $db->setQuery($query); + $db->execute(); +} + +/** + * checks if a tournament has at least one result entry for a discipline + * @param $db + * @param $row mixed tournament entry + * @return bool true if at least one result is given, else false + * @since 2.2 + */ +function hasResultsAlready($db, mixed $row): bool +{ + $subQuery = $db->getQuery(true) + ->select($db->quoteName('turnierdisziplin_id')) + ->from($db->quoteName('#__sportsmanager_turnierdisziplin')) + ->where($db->quoteName('turnier_id') . ' = ' . $db->quote($row->turnier_id)); + + $query = $db->getQuery(true) + ->select('COUNT(*) AS count') + ->from($db->quoteName('#__sportsmanager_turniermeldung', 'tm')) + ->where($db->quoteName('tm.turnierdisziplin_id') . ' IN (' . $subQuery . ')'); + + $result = loadResult($db, $query); + return $result && $result[0]->count > 0; +} diff --git a/src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php b/src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php index 261b5ce..f4236f6 100644 --- a/src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php +++ b/src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php @@ -727,9 +727,10 @@ class HTML_sportsmanager_admin :